mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 03:37:08 -06:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 851aae286c | |||
| 71413305d7 | |||
| 938bcd258d |
@@ -73,4 +73,4 @@ cpp_space_around_assignment_operator=insert
|
|||||||
cpp_space_pointer_reference_alignment=left
|
cpp_space_pointer_reference_alignment=left
|
||||||
cpp_space_around_ternary_operator=insert
|
cpp_space_around_ternary_operator=insert
|
||||||
cpp_wrap_preserve_blocks=one_liners
|
cpp_wrap_preserve_blocks=one_liners
|
||||||
cpp_indent_comment=false
|
cpp_indent_comment=fasle
|
||||||
|
|||||||
10
.env.example
10
.env.example
@@ -3,20 +3,12 @@ CLIENT_PATH=./client
|
|||||||
# Updates NET_VERSION in CMakeVariables.txt
|
# Updates NET_VERSION in CMakeVariables.txt
|
||||||
NET_VERSION=171022
|
NET_VERSION=171022
|
||||||
# make sure this is a long random string
|
# make sure this is a long random string
|
||||||
# generate a "SHA 256-bit Key" from here: https://gchq.github.io/CyberChef/#recipe=Pseudo-Random_Number_Generator(256,'Hex')
|
# grab a "SHA 256-bit Key" from here: https://keygen.io/
|
||||||
ACCOUNT_MANAGER_SECRET=
|
ACCOUNT_MANAGER_SECRET=
|
||||||
# Should be the externally facing IP of your server host
|
# Should be the externally facing IP of your server host
|
||||||
EXTERNAL_IP=localhost
|
EXTERNAL_IP=localhost
|
||||||
|
|
||||||
# The database type that will be used.
|
|
||||||
# Acceptable values are `sqlite`, `mysql`, `mariadb`, `maria`.
|
|
||||||
# Case insensitive.
|
|
||||||
DATABASE_TYPE=mariadb
|
|
||||||
SQLITE_DATABASE_PATH=resServer/dlu.sqlite
|
|
||||||
|
|
||||||
# Database values
|
# Database values
|
||||||
# Be careful with special characters here. It is more safe to use normal characters and/or numbers.
|
# Be careful with special characters here. It is more safe to use normal characters and/or numbers.
|
||||||
MARIADB_USER=darkflame
|
MARIADB_USER=darkflame
|
||||||
MARIADB_PASSWORD=
|
MARIADB_PASSWORD=
|
||||||
MARIADB_DATABASE=darkflame
|
MARIADB_DATABASE=darkflame
|
||||||
SKIP_ACCOUNT_CREATION=1
|
|
||||||
|
|||||||
31
.github/workflows/build-and-test.yml
vendored
31
.github/workflows/build-and-test.yml
vendored
@@ -16,12 +16,12 @@ jobs:
|
|||||||
os: [ windows-2022, ubuntu-22.04, macos-13 ]
|
os: [ windows-2022, ubuntu-22.04, macos-13 ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Add msbuild to PATH (Windows only)
|
- name: Add msbuild to PATH (Windows only)
|
||||||
if: ${{ matrix.os == 'windows-2022' }}
|
if: ${{ matrix.os == 'windows-2022' }}
|
||||||
uses: microsoft/setup-msbuild@v2
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
with:
|
with:
|
||||||
vs-version: '[17,18)'
|
vs-version: '[17,18)'
|
||||||
msbuild-architecture: x64
|
msbuild-architecture: x64
|
||||||
@@ -33,20 +33,21 @@ jobs:
|
|||||||
- name: cmake
|
- name: cmake
|
||||||
uses: lukka/run-cmake@v10
|
uses: lukka/run-cmake@v10
|
||||||
with:
|
with:
|
||||||
workflowPreset: "ci-${{matrix.os}}"
|
configurePreset: "ci-${{matrix.os}}"
|
||||||
|
buildPreset: "ci-${{matrix.os}}"
|
||||||
|
testPreset: "ci-${{matrix.os}}"
|
||||||
- name: artifacts
|
- name: artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: build-${{matrix.os}}
|
name: build-${{matrix.os}}
|
||||||
path: |
|
path: |
|
||||||
build/*/*Server*
|
build/*Server*
|
||||||
build/*/*.ini
|
build/*.ini
|
||||||
build/*/*.so
|
build/*.so
|
||||||
build/*/*.dll
|
build/*.dll
|
||||||
build/*/*.dylib
|
build/vanity/
|
||||||
build/*/vanity/
|
build/navmeshes/
|
||||||
build/*/navmeshes/
|
build/migrations/
|
||||||
build/*/migrations/
|
build/*.dcf
|
||||||
build/*/*.dcf
|
!build/*.pdb
|
||||||
!build/*/*.pdb
|
!build/d*/
|
||||||
!build/*/d*/
|
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -6,6 +6,7 @@ docker/configs
|
|||||||
# Third party libraries
|
# Third party libraries
|
||||||
thirdparty/mysql/
|
thirdparty/mysql/
|
||||||
thirdparty/mysql_linux/
|
thirdparty/mysql_linux/
|
||||||
|
CMakeVariables.txt
|
||||||
|
|
||||||
# Build folders
|
# Build folders
|
||||||
build/
|
build/
|
||||||
@@ -94,7 +95,6 @@ ipch/
|
|||||||
|
|
||||||
# Exceptions:
|
# Exceptions:
|
||||||
CMakeSettings.json
|
CMakeSettings.json
|
||||||
CMakeUserPresets.json
|
|
||||||
*.vcxproj
|
*.vcxproj
|
||||||
*.filters
|
*.filters
|
||||||
*.cmake
|
*.cmake
|
||||||
@@ -122,7 +122,4 @@ docker/__pycache__
|
|||||||
docker-compose.override.yml
|
docker-compose.override.yml
|
||||||
|
|
||||||
!*Test.bin
|
!*Test.bin
|
||||||
|
|
||||||
# CMake scripts
|
|
||||||
!cmake/*
|
!cmake/*
|
||||||
!cmake/toolchains/*
|
|
||||||
|
|||||||
132
CMakeLists.txt
132
CMakeLists.txt
@@ -1,23 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(Darkflame
|
project(Darkflame)
|
||||||
HOMEPAGE_URL "https://github.com/DarkflameUniverse/DarkflameServer"
|
|
||||||
LANGUAGES C CXX
|
|
||||||
)
|
|
||||||
|
|
||||||
# check if the path to the source directory contains a space
|
|
||||||
if("${CMAKE_SOURCE_DIR}" MATCHES " ")
|
|
||||||
message(FATAL_ERROR "The server cannot build in the path (" ${CMAKE_SOURCE_DIR} ") because it contains a space. Please move the server to a path without spaces.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
|
set(CMAKE_CXX_VISIBILITY_PRESET hidden) # Set C++ symbol visibility to default to hidden
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
|
||||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
# Read variables from file
|
# Read variables from file
|
||||||
@@ -66,37 +54,34 @@ set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|||||||
# Disabled no-register
|
# Disabled no-register
|
||||||
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
add_link_options("-Wl,-rpath,$ORIGIN/")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wuninitialized -fPIC")
|
||||||
add_compile_options("-fPIC")
|
|
||||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0)
|
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0)
|
||||||
|
|
||||||
# For all except Clang and Apple Clang
|
if(NOT APPLE)
|
||||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -lstdc++fs")
|
||||||
add_compile_options("-static-libgcc" "-lstdc++fs")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${DYNAMIC} AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(${DYNAMIC} AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
add_link_options("-export-dynamic")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${GGDB})
|
if(${GGDB})
|
||||||
add_compile_options("-ggdb")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
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
|
||||||
# Also disable non-portable MSVC volatile behavior
|
add_compile_options("/wd4267" "/utf-8")
|
||||||
add_compile_options("/wd4267" "/utf-8" "/volatile:iso" "/Zc:inline")
|
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Our output dir
|
# Our output dir
|
||||||
|
set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR})
|
||||||
#set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) # unfortunately, forces all libraries to be built in series, which will slow down the build process
|
#set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) # unfortunately, forces all libraries to be built in series, which will slow down the build process
|
||||||
|
|
||||||
# TODO make this not have to override the build type directories
|
# TODO make this not have to override the build type directories
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
|
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
|
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
|
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||||
@@ -116,39 +101,31 @@ make_directory(${CMAKE_BINARY_DIR}/resServer)
|
|||||||
# Create a /logs directory
|
# Create a /logs directory
|
||||||
make_directory(${CMAKE_BINARY_DIR}/logs)
|
make_directory(${CMAKE_BINARY_DIR}/logs)
|
||||||
|
|
||||||
# Get DLU config directory
|
|
||||||
if(DEFINED ENV{DLU_CONFIG_DIR})
|
|
||||||
set(DLU_CONFIG_DIR $ENV{DLU_CONFIG_DIR})
|
|
||||||
else()
|
|
||||||
set(DLU_CONFIG_DIR ${PROJECT_BINARY_DIR})
|
|
||||||
endif()
|
|
||||||
message(STATUS "Variable: DLU_CONFIG_DIR = ${DLU_CONFIG_DIR}")
|
|
||||||
|
|
||||||
# Copy resource files on first build
|
# Copy resource files on first build
|
||||||
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blocklist.dcf")
|
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
||||||
message(STATUS "Checking resource file integrity")
|
message(STATUS "Checking resource file integrity")
|
||||||
|
|
||||||
include(Utils)
|
include(Utils)
|
||||||
UpdateConfigOption(${DLU_CONFIG_DIR}/authconfig.ini "port" "auth_server_port")
|
UpdateConfigOption(${PROJECT_BINARY_DIR}/authconfig.ini "port" "auth_server_port")
|
||||||
UpdateConfigOption(${DLU_CONFIG_DIR}/chatconfig.ini "port" "chat_server_port")
|
UpdateConfigOption(${PROJECT_BINARY_DIR}/chatconfig.ini "port" "chat_server_port")
|
||||||
UpdateConfigOption(${DLU_CONFIG_DIR}/masterconfig.ini "port" "master_server_port")
|
UpdateConfigOption(${PROJECT_BINARY_DIR}/masterconfig.ini "port" "master_server_port")
|
||||||
|
|
||||||
foreach(resource_file ${RESOURCE_FILES})
|
foreach(resource_file ${RESOURCE_FILES})
|
||||||
set(file_size 0)
|
set(file_size 0)
|
||||||
|
|
||||||
if(EXISTS ${DLU_CONFIG_DIR}/${resource_file})
|
if(EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
||||||
file(SIZE ${DLU_CONFIG_DIR}/${resource_file} file_size)
|
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${file_size} EQUAL 0)
|
if(${file_size} EQUAL 0)
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${DLU_CONFIG_DIR}/${resource_file}
|
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
message(STATUS "Moved " ${resource_file} " to DLU config directory")
|
message(STATUS "Moved " ${resource_file} " to project binary directory")
|
||||||
elseif(resource_file MATCHES ".ini")
|
elseif(resource_file MATCHES ".ini")
|
||||||
message(STATUS "Checking " ${resource_file} " for missing config options")
|
message(STATUS "Checking " ${resource_file} " for missing config options")
|
||||||
file(READ ${DLU_CONFIG_DIR}/${resource_file} current_file_contents)
|
file(READ ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
|
||||||
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
|
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
|
||||||
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
|
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
|
||||||
set(parsed_current_file_contents "")
|
set(parsed_current_file_contents "")
|
||||||
@@ -175,18 +152,16 @@ foreach(resource_file ${RESOURCE_FILES})
|
|||||||
list(GET line_split 0 variable_name)
|
list(GET line_split 0 variable_name)
|
||||||
|
|
||||||
if(NOT ${parsed_current_file_contents} MATCHES ${variable_name})
|
if(NOT ${parsed_current_file_contents} MATCHES ${variable_name})
|
||||||
# For backwards compatibility with older setup versions, dont add this option.
|
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
||||||
if(NOT ${variable_name} MATCHES "database_type")
|
set(line_to_add ${line_to_add} ${line})
|
||||||
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
|
||||||
set(line_to_add ${line_to_add} ${line})
|
|
||||||
|
|
||||||
foreach(line_to_append ${line_to_add})
|
foreach(line_to_append ${line_to_add})
|
||||||
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n" ${line_to_append})
|
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n")
|
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(line_to_add "")
|
set(line_to_add "")
|
||||||
else()
|
else()
|
||||||
set(line_to_add ${line_to_add} ${line})
|
set(line_to_add ${line_to_add} ${line})
|
||||||
@@ -216,8 +191,21 @@ foreach(file ${VANITY_FILES})
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Move our migrations for MasterServer to run
|
# Move our migrations for MasterServer to run
|
||||||
file(REMOVE_RECURSE ${PROJECT_BINARY_DIR}/migrations)
|
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/dlu/)
|
||||||
file(COPY ${CMAKE_SOURCE_DIR}/migrations DESTINATION ${CMAKE_BINARY_DIR})
|
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql)
|
||||||
|
|
||||||
|
foreach(file ${SQL_FILES})
|
||||||
|
get_filename_component(file ${file} NAME)
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/dlu/${file})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/cdserver/)
|
||||||
|
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/cdserver/*.sql)
|
||||||
|
|
||||||
|
foreach(file ${SQL_FILES})
|
||||||
|
get_filename_component(file ${file} NAME)
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
@@ -240,15 +228,14 @@ include_directories(
|
|||||||
"tests/dGameTests"
|
"tests/dGameTests"
|
||||||
"tests/dGameTests/dComponentsTests"
|
"tests/dGameTests/dComponentsTests"
|
||||||
|
|
||||||
SYSTEM
|
SYSTEM "thirdparty/magic_enum/include/magic_enum"
|
||||||
"thirdparty/magic_enum/include/magic_enum"
|
SYSTEM "thirdparty/raknet/Source"
|
||||||
"thirdparty/raknet/Source"
|
SYSTEM "thirdparty/tinyxml2"
|
||||||
"thirdparty/tinyxml2"
|
SYSTEM "thirdparty/recastnavigation"
|
||||||
"thirdparty/recastnavigation"
|
SYSTEM "thirdparty/SQLite"
|
||||||
"thirdparty/SQLite"
|
SYSTEM "thirdparty/cpplinq"
|
||||||
"thirdparty/cpplinq"
|
SYSTEM "thirdparty/cpp-httplib"
|
||||||
"thirdparty/cpp-httplib"
|
SYSTEM "thirdparty/MD5"
|
||||||
"thirdparty/MD5"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
||||||
@@ -257,17 +244,10 @@ if(APPLE)
|
|||||||
include_directories("/usr/local/include/")
|
include_directories("/usr/local/include/")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Set warning flags
|
|
||||||
if(MSVC)
|
|
||||||
# add_compile_options("/W4")
|
|
||||||
# Want to enable warnings eventually, but WAY too much noise right now
|
|
||||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
|
||||||
add_compile_options("-Wuninitialized" "-Wold-style-cast")
|
|
||||||
else()
|
|
||||||
message(WARNING "Unknown compiler: '${CMAKE_CXX_COMPILER_ID}' - No warning flags enabled.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Add linking directories:
|
# Add linking directories:
|
||||||
|
if (UNIX)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast -Werror") # Warning flags
|
||||||
|
endif()
|
||||||
file(
|
file(
|
||||||
GLOB HEADERS_DZONEMANAGER
|
GLOB HEADERS_DZONEMANAGER
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
@@ -302,7 +282,7 @@ add_subdirectory(dPhysics)
|
|||||||
add_subdirectory(dServer)
|
add_subdirectory(dServer)
|
||||||
|
|
||||||
# Create a list of common libraries shared between all binaries
|
# Create a list of common libraries shared between all binaries
|
||||||
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
|
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "MariaDB::ConnCpp" "magic_enum")
|
||||||
|
|
||||||
# Add platform specific common libraries
|
# Add platform specific common libraries
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
|
|||||||
@@ -1,638 +1,128 @@
|
|||||||
{
|
{
|
||||||
"version": 6,
|
"version": 3,
|
||||||
"cmakeMinimumRequired": {
|
"cmakeMinimumRequired": {
|
||||||
"major": 3,
|
"major": 3,
|
||||||
"minor": 25,
|
"minor": 14,
|
||||||
"patch": 0
|
"patch": 0
|
||||||
},
|
},
|
||||||
"configurePresets": [
|
"configurePresets": [
|
||||||
{
|
{
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"displayName": "Default configure step",
|
"displayName": "Default configure step",
|
||||||
"description": "Use 'build' dir and Unix makefiles",
|
"description": "Use 'build' dir and Unix makefiles",
|
||||||
"binaryDir": "${sourceDir}/build",
|
"binaryDir": "${sourceDir}/build",
|
||||||
"generator": "Unix Makefiles"
|
"generator": "Unix Makefiles"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "debug-config",
|
"name": "ci-ubuntu-22.04",
|
||||||
"hidden": true,
|
"displayName": "CI configure step for Ubuntu",
|
||||||
"cacheVariables": {
|
"description": "Same as default, Used in GitHub actions workflow",
|
||||||
"CMAKE_BUILD_TYPE": "Debug"
|
"inherits": "default"
|
||||||
}
|
},
|
||||||
},
|
{
|
||||||
{
|
"name": "ci-macos-13",
|
||||||
"name": "relwithdebinfo-config",
|
"displayName": "CI configure step for MacOS",
|
||||||
"hidden": true,
|
"description": "Same as default, Used in GitHub actions workflow",
|
||||||
"cacheVariables": {
|
"inherits": "default"
|
||||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
},
|
||||||
}
|
{
|
||||||
},
|
"name": "ci-windows-2022",
|
||||||
{
|
"displayName": "CI configure step for Windows",
|
||||||
"name": "release-config",
|
"description": "Set architecture to 64-bit (b/c RakNet)",
|
||||||
"hidden": true,
|
"inherits": "default",
|
||||||
"cacheVariables": {
|
"generator": "Visual Studio 17 2022",
|
||||||
"CMAKE_BUILD_TYPE": "Release"
|
"architecture": {
|
||||||
}
|
"value": "x64"
|
||||||
},
|
},
|
||||||
{
|
"cacheVariables": {
|
||||||
"name": "clang-config",
|
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||||
"hidden": true,
|
}
|
||||||
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-clang.cmake"
|
},
|
||||||
},
|
{
|
||||||
{
|
"name": "windows-default",
|
||||||
"name": "gnu-config",
|
"inherits": "ci-windows-2022",
|
||||||
"hidden": true,
|
"displayName": "Windows only Configure Settings",
|
||||||
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-gnu.cmake"
|
"description": "Sets build and install directories",
|
||||||
},
|
"generator": "Ninja",
|
||||||
{
|
"architecture": {
|
||||||
"name": "windows-msvc",
|
"value": "x64",
|
||||||
"inherits": "default",
|
"strategy": "external"
|
||||||
"displayName": "[Multi] Windows (MSVC)",
|
}
|
||||||
"description": "Set architecture to 64-bit (b/c RakNet)",
|
}
|
||||||
"generator": "Visual Studio 17 2022",
|
],
|
||||||
"binaryDir": "${sourceDir}/build/msvc",
|
"buildPresets": [
|
||||||
"architecture": {
|
{
|
||||||
"value": "x64"
|
"name": "default",
|
||||||
},
|
"configurePreset": "default",
|
||||||
"condition": {
|
"displayName": "Default Build",
|
||||||
"type": "equals",
|
"description": "Default Build",
|
||||||
"lhs": "${hostSystemName}",
|
"jobs": 2
|
||||||
"rhs": "Windows"
|
},
|
||||||
}
|
{
|
||||||
},
|
"name": "ci-windows-2022",
|
||||||
{
|
"configurePreset": "ci-windows-2022",
|
||||||
"name": "windows-default",
|
"displayName": "Windows CI Build",
|
||||||
"inherits": "windows-msvc",
|
"description": "This preset is used by the CI build on windows",
|
||||||
"displayName": "Windows only Configure Settings",
|
"configuration": "RelWithDebInfo",
|
||||||
"description": "Sets build and install directories",
|
"jobs": 2
|
||||||
"generator": "Ninja",
|
},
|
||||||
"condition": {
|
{
|
||||||
"type": "equals",
|
"name": "ci-ubuntu-22.04",
|
||||||
"lhs": "${hostSystemName}",
|
"configurePreset": "ci-ubuntu-22.04",
|
||||||
"rhs": "Windows"
|
"displayName": "Linux CI Build",
|
||||||
},
|
"description": "This preset is used by the CI build on linux",
|
||||||
"architecture": {
|
"jobs": 2
|
||||||
"value": "x64"
|
},
|
||||||
}
|
{
|
||||||
},
|
"name": "ci-macos-13",
|
||||||
{
|
"configurePreset": "ci-macos-13",
|
||||||
"name": "linux-config",
|
"displayName": "MacOS CI Build",
|
||||||
"inherits": "default",
|
"description": "This preset is used by the CI build on MacOS",
|
||||||
"hidden": true,
|
"jobs": 2
|
||||||
"condition": {
|
}
|
||||||
"type": "equals",
|
],
|
||||||
"lhs": "${hostSystemName}",
|
"testPresets": [
|
||||||
"rhs": "Linux"
|
{
|
||||||
}
|
"name": "ci-ubuntu-22.04",
|
||||||
},
|
"configurePreset": "ci-ubuntu-22.04",
|
||||||
{
|
"displayName": "CI Tests on Linux",
|
||||||
"name": "linux-clang-debug",
|
"description": "Runs all tests on a linux configuration",
|
||||||
"inherits": [
|
"execution": {
|
||||||
"linux-config",
|
|
||||||
"clang-config",
|
|
||||||
"debug-config"
|
|
||||||
],
|
|
||||||
"displayName": "EXPERIMENTAL - [Debug] Linux (Clang)",
|
|
||||||
"description": "Create a debug build using the Clang toolchain for Linux",
|
|
||||||
"binaryDir": "${sourceDir}/build/clang-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-relwithdebinfo",
|
|
||||||
"inherits": [
|
|
||||||
"linux-config",
|
|
||||||
"clang-config",
|
|
||||||
"relwithdebinfo-config"
|
|
||||||
],
|
|
||||||
"displayName": "EXPERIMENTAL - [RelWithDebInfo] Linux (Clang)",
|
|
||||||
"description": "Create a release build with debug info using the Clang toolchain for Linux",
|
|
||||||
"binaryDir": "${sourceDir}/build/clang-relwithdebinfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-release",
|
|
||||||
"inherits": [
|
|
||||||
"linux-config",
|
|
||||||
"clang-config",
|
|
||||||
"release-config"
|
|
||||||
],
|
|
||||||
"displayName": "EXPERIMENTAL - [Release] Linux (Clang)",
|
|
||||||
"description": "Create a release build using the Clang toolchain for Linux",
|
|
||||||
"binaryDir": "${sourceDir}/build/clang-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-debug",
|
|
||||||
"inherits": [
|
|
||||||
"linux-config",
|
|
||||||
"gnu-config",
|
|
||||||
"debug-config"
|
|
||||||
],
|
|
||||||
"displayName": "[Debug] Linux (GNU)",
|
|
||||||
"description": "Create a debug build using the GNU toolchain for Linux",
|
|
||||||
"binaryDir": "${sourceDir}/build/gnu-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-relwithdebinfo",
|
|
||||||
"inherits": [
|
|
||||||
"linux-config",
|
|
||||||
"gnu-config",
|
|
||||||
"relwithdebinfo-config"
|
|
||||||
],
|
|
||||||
"displayName": "[RelWithDebInfo] Linux (GNU)",
|
|
||||||
"description": "Create a release build with debug info using the GNU toolchain for Linux",
|
|
||||||
"binaryDir": "${sourceDir}/build/gnu-relwithdebinfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-release",
|
|
||||||
"inherits": [
|
|
||||||
"linux-config",
|
|
||||||
"gnu-config",
|
|
||||||
"release-config"
|
|
||||||
],
|
|
||||||
"displayName": "[Release] Linux (GNU)",
|
|
||||||
"description": "Create a release build using the GNU toolchain for Linux",
|
|
||||||
"binaryDir": "${sourceDir}/build/gnu-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos",
|
|
||||||
"inherits": "default",
|
|
||||||
"displayName": "[Multi] MacOS",
|
|
||||||
"description": "Create a build for MacOS",
|
|
||||||
"condition": {
|
|
||||||
"type": "equals",
|
|
||||||
"lhs": "${hostSystemName}",
|
|
||||||
"rhs": "Darwin"
|
|
||||||
},
|
|
||||||
"binaryDir": "${sourceDir}/build/macos"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buildPresets": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"configurePreset": "default",
|
|
||||||
"displayName": "Default Build",
|
|
||||||
"description": "Default Build",
|
|
||||||
"jobs": 2
|
"jobs": 2
|
||||||
},
|
},
|
||||||
{
|
"output": {
|
||||||
"name": "windows-msvc-debug",
|
"outputOnFailure": true
|
||||||
"inherits": "default",
|
}
|
||||||
"configurePreset": "windows-msvc",
|
},
|
||||||
"displayName": "[Debug] Windows (MSVC)",
|
{
|
||||||
"description": "This preset is used to build in debug mode using the MSVC toolchain on Windows",
|
"name": "ci-macos-13",
|
||||||
"configuration": "Debug"
|
"configurePreset": "ci-macos-13",
|
||||||
|
"displayName": "CI Tests on MacOS",
|
||||||
|
"description": "Runs all tests on a Mac configuration",
|
||||||
|
"execution": {
|
||||||
|
"jobs": 2
|
||||||
},
|
},
|
||||||
{
|
"output": {
|
||||||
"name": "windows-msvc-relwithdebinfo",
|
"outputOnFailure": true
|
||||||
"inherits": "default",
|
}
|
||||||
"configurePreset": "windows-msvc",
|
},
|
||||||
"displayName": "[RelWithDebInfo] Windows (MSVC)",
|
{
|
||||||
"description": "This preset is used to build in debug mode using the MSVC toolchain on Windows",
|
"name": "ci-windows-2022",
|
||||||
"configuration": "RelWithDebInfo"
|
"configurePreset": "ci-windows-2022",
|
||||||
|
"displayName": "CI Tests on windows",
|
||||||
|
"description": "Runs all tests on a windows configuration",
|
||||||
|
"configuration": "RelWithDebInfo",
|
||||||
|
"execution": {
|
||||||
|
"jobs": 2
|
||||||
},
|
},
|
||||||
{
|
"output": {
|
||||||
"name": "windows-msvc-release",
|
"outputOnFailure": true
|
||||||
"inherits": "default",
|
},
|
||||||
"configurePreset": "windows-msvc",
|
"filter": {
|
||||||
"displayName": "[Release] Windows (MSVC)",
|
"exclude": {
|
||||||
"description": "This preset is used to build in release mode using the MSVC toolchain on Windows",
|
"name": "((example)|(minigzip))+"
|
||||||
"configuration": "Release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-debug",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-clang-debug",
|
|
||||||
"displayName": "EXPERIMENTAL - [Debug] Linux (Clang)",
|
|
||||||
"description": "This preset is used to build in debug mode using the Clang toolchain on Linux",
|
|
||||||
"configuration": "Debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-relwithdebinfo",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-clang-relwithdebinfo",
|
|
||||||
"displayName": "EXPERIMENTAL - [RelWithDebInfo] Linux (Clang)",
|
|
||||||
"description": "This preset is used to build in release mode with debug info using the Clang toolchain on Linux",
|
|
||||||
"configuration": "RelWithDebInfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-release",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-clang-release",
|
|
||||||
"displayName": "EXPERIMENTAL - [Release] Linux (Clang)",
|
|
||||||
"description": "This preset is used to build in release mode using the Clang toolchain on Linux",
|
|
||||||
"configuration": "Release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-debug",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-gnu-debug",
|
|
||||||
"displayName": "[Debug] Linux (GNU)",
|
|
||||||
"description": "This preset is used to build in debug mode using the GNU toolchain on Linux",
|
|
||||||
"configuration": "Debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-relwithdebinfo",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-gnu-relwithdebinfo",
|
|
||||||
"displayName": "[RelWithDebInfo] Linux (GNU)",
|
|
||||||
"description": "This preset is used to build in release mode with debug info using the GNU toolchain on Linux",
|
|
||||||
"configuration": "RelWithDebInfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-release",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-gnu-release",
|
|
||||||
"displayName": "[Release] Linux (GNU)",
|
|
||||||
"description": "This preset is used to build in release mode using the GNU toolchain on Linux",
|
|
||||||
"configuration": "Release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-debug",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "macos",
|
|
||||||
"displayName": "[Debug] MacOS",
|
|
||||||
"description": "This preset is used to build in debug mode on MacOS",
|
|
||||||
"configuration": "Debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-relwithdebinfo",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "macos",
|
|
||||||
"displayName": "[RelWithDebInfo] MacOS",
|
|
||||||
"description": "This preset is used to build in release mode with debug info on MacOS",
|
|
||||||
"configuration": "RelWithDebInfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-release",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "macos",
|
|
||||||
"displayName": "[Release] MacOS",
|
|
||||||
"description": "This preset is used to build in release mode on MacOS",
|
|
||||||
"configuration": "Release"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"testPresets": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"configurePreset": "default",
|
|
||||||
"execution": {
|
|
||||||
"jobs": 2
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"outputOnFailure": true
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "windows-msvc-test",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "windows-msvc",
|
|
||||||
"hidden": true,
|
|
||||||
"filter": {
|
|
||||||
"exclude": {
|
|
||||||
"name": "((example)|(minigzip))+"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "windows-msvc-debug",
|
|
||||||
"inherits": "windows-msvc-test",
|
|
||||||
"configurePreset": "windows-msvc",
|
|
||||||
"displayName": "[Debug] Windows (MSVC)",
|
|
||||||
"description": "Runs all tests on a Windows configuration",
|
|
||||||
"configuration": "Debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "windows-msvc-relwithdebinfo",
|
|
||||||
"inherits": "windows-msvc-test",
|
|
||||||
"configurePreset": "windows-msvc",
|
|
||||||
"displayName": "[RelWithDebInfo] Windows (MSVC)",
|
|
||||||
"description": "Runs all tests on a Windows configuration",
|
|
||||||
"configuration": "RelWithDebInfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "windows-msvc-release",
|
|
||||||
"inherits": "windows-msvc-test",
|
|
||||||
"configurePreset": "windows-msvc",
|
|
||||||
"displayName": "[Release] Windows (MSVC)",
|
|
||||||
"description": "Runs all tests on a Windows configuration",
|
|
||||||
"configuration": "Release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-debug",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-clang-debug",
|
|
||||||
"displayName": "EXPERIMENTAL - [Debug] Linux (Clang)",
|
|
||||||
"description": "Runs all tests on a Linux Clang configuration",
|
|
||||||
"configuration": "Release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-relwithdebinfo",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-clang-relwithdebinfo",
|
|
||||||
"displayName": "EXPERIMENTAL - [RelWithDebInfo] Linux (Clang)",
|
|
||||||
"description": "Runs all tests on a Linux Clang configuration",
|
|
||||||
"configuration": "RelWithDebInfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-release",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-clang-release",
|
|
||||||
"displayName": "EXPERIMENTAL - [Release] Linux (Clang)",
|
|
||||||
"description": "Runs all tests on a Linux Clang configuration",
|
|
||||||
"configuration": "Release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-debug",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-gnu-debug",
|
|
||||||
"displayName": "[Debug] Linux (GNU)",
|
|
||||||
"description": "Runs all tests on a Linux GNU configuration",
|
|
||||||
"configuration": "Release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-relwithdebinfo",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-gnu-relwithdebinfo",
|
|
||||||
"displayName": "[RelWithDebInfo] Linux (GNU)",
|
|
||||||
"description": "Runs all tests on a Linux GNU configuration",
|
|
||||||
"configuration": "RelWithDebInfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-release",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "linux-gnu-release",
|
|
||||||
"displayName": "[Release] Linux (GNU)",
|
|
||||||
"description": "Runs all tests on a Linux GNU configuration",
|
|
||||||
"configuration": "Release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-debug",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "macos",
|
|
||||||
"displayName": "[Debug] MacOS",
|
|
||||||
"description": "Runs all tests on a MacOS configuration",
|
|
||||||
"configuration": "Debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-relwithdebinfo",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "macos",
|
|
||||||
"displayName": "[RelWithDebInfo] MacOS",
|
|
||||||
"description": "Runs all tests on a MacOS configuration",
|
|
||||||
"configuration": "RelWithDebInfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-release",
|
|
||||||
"inherits": "default",
|
|
||||||
"configurePreset": "macos",
|
|
||||||
"displayName": "[Release] MacOS",
|
|
||||||
"description": "Runs all tests on a MacOS configuration",
|
|
||||||
"configuration": "Release"
|
|
||||||
}
|
}
|
||||||
],
|
}
|
||||||
"workflowPresets": [
|
]
|
||||||
{
|
}
|
||||||
"name": "default",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "default"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "windows-msvc-debug",
|
|
||||||
"displayName": "[Debug] Windows (MSVC)",
|
|
||||||
"description": "MSVC debug workflow preset for Windows",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "windows-msvc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "windows-msvc-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "windows-msvc-debug"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "windows-msvc-relwithdebinfo",
|
|
||||||
"displayName": "[RelWithDebInfo] Windows (MSVC)",
|
|
||||||
"description": "MSVC release with debug info workflow preset for Windows",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "windows-msvc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "windows-msvc-relwithdebinfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "windows-msvc-relwithdebinfo"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-windows-2022",
|
|
||||||
"displayName": "[Release] Windows (MSVC)",
|
|
||||||
"description": "CI workflow preset for Windows",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "windows-msvc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "windows-msvc-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "windows-msvc-release"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-debug",
|
|
||||||
"displayName": "[Debug] Linux (GNU)",
|
|
||||||
"description": "GNU debug workflow preset for Linux",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "linux-gnu-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "linux-gnu-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "linux-gnu-debug"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-gnu-relwithdebinfo",
|
|
||||||
"displayName": "[RelWithDebInfo] Linux (GNU)",
|
|
||||||
"description": "GNU release with debug info workflow preset for Linux",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "linux-gnu-relwithdebinfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "linux-gnu-relwithdebinfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "linux-gnu-relwithdebinfo"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-ubuntu-22.04",
|
|
||||||
"displayName": "[Release] Linux (GNU)",
|
|
||||||
"description": "CI workflow preset for Ubuntu",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "linux-gnu-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "linux-gnu-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "linux-gnu-release"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-debug",
|
|
||||||
"displayName": "EXPERIMENTAL - [Debug] Linux (Clang)",
|
|
||||||
"description": "Clang debug workflow preset for Linux",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "linux-clang-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "linux-clang-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "linux-clang-debug"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-relwithdebinfo",
|
|
||||||
"displayName": "EXPERIMENTAL - [RelWithDebInfo] Linux (Clang)",
|
|
||||||
"description": "Clang release with debug info workflow preset for Linux",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "linux-clang-relwithdebinfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "linux-clang-relwithdebinfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "linux-clang-relwithdebinfo"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "linux-clang-release",
|
|
||||||
"displayName": "EXPERIMENTAL - [Release] Linux (Clang)",
|
|
||||||
"description": "Clang release workflow preset for Linux",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "linux-clang-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "linux-clang-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "linux-clang-release"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-debug",
|
|
||||||
"displayName": "[Debug] MacOS",
|
|
||||||
"description": "Release workflow preset for MacOS",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "macos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "macos-debug"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "macos-debug"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-relwithdebinfo",
|
|
||||||
"displayName": "[RelWithDebInfo] MacOS",
|
|
||||||
"description": "Release with debug info workflow preset for MacOS",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "macos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "macos-relwithdebinfo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "macos-relwithdebinfo"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-macos-13",
|
|
||||||
"displayName": "[Release] MacOS",
|
|
||||||
"description": "CI workflow preset for MacOS",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"type": "configure",
|
|
||||||
"name": "macos"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "build",
|
|
||||||
"name": "macos-release"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "test",
|
|
||||||
"name": "macos-release"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
PROJECT_VERSION_MAJOR=3
|
PROJECT_VERSION_MAJOR=1
|
||||||
PROJECT_VERSION_MINOR=0
|
PROJECT_VERSION_MINOR=1
|
||||||
PROJECT_VERSION_PATCH=0
|
PROJECT_VERSION_PATCH=1
|
||||||
|
|
||||||
# Debugging
|
# Debugging
|
||||||
# Set DYNAMIC to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
# Set DYNAMIC to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ COPY --from=build /app/build/*Server /app/
|
|||||||
|
|
||||||
# Necessary suplimentary files
|
# Necessary suplimentary files
|
||||||
COPY --from=build /app/build/*.ini /app/configs/
|
COPY --from=build /app/build/*.ini /app/configs/
|
||||||
COPY --from=build /app/build/vanity/*.* /app/vanity/
|
COPY --from=build /app/build/vanity/*.* /app/vanity/*
|
||||||
COPY --from=build /app/build/navmeshes /app/navmeshes
|
COPY --from=build /app/build/navmeshes /app/navmeshes
|
||||||
COPY --from=build /app/build/migrations /app/migrations
|
COPY --from=build /app/build/migrations /app/migrations
|
||||||
COPY --from=build /app/build/*.dcf /app/
|
COPY --from=build /app/build/*.dcf /app/
|
||||||
@@ -39,7 +39,7 @@ COPY --from=build /app/build/*.dcf /app/
|
|||||||
# backup of config and vanity files to copy to the host incase
|
# backup of config and vanity files to copy to the host incase
|
||||||
# of a mount clobbering the copy from above
|
# of a mount clobbering the copy from above
|
||||||
COPY --from=build /app/build/*.ini /app/default-configs/
|
COPY --from=build /app/build/*.ini /app/default-configs/
|
||||||
COPY --from=build /app/build/vanity/*.* /app/default-vanity/
|
COPY --from=build /app/build/vanity/*.* /app/default-vanity/*
|
||||||
|
|
||||||
# needed as the container runs with the root user
|
# needed as the container runs with the root user
|
||||||
# and therefore sudo doesn't exist
|
# and therefore sudo doesn't exist
|
||||||
|
|||||||
41
README.md
41
README.md
@@ -13,33 +13,21 @@ Darkflame Universe is licensed under AGPLv3, please read [LICENSE](LICENSE). Som
|
|||||||
* You must disclose any changes you make to the code when you distribute it
|
* You must disclose any changes you make to the code when you distribute it
|
||||||
* Hosting a server for others counts as distribution
|
* Hosting a server for others counts as distribution
|
||||||
|
|
||||||
|
## Disclaimers
|
||||||
|
### Setup difficulty
|
||||||
|
Throughout the entire build and setup process a level of familiarity with the command line and preferably a Unix-like development environment is greatly advantageous.
|
||||||
|
|
||||||
### Hosting a server
|
### Hosting a server
|
||||||
We do not recommend hosting public servers. Darkflame Universe is intended for small scale deployment, for example within a group of friends. It has not been tested for large scale deployment which comes with additional security risks.
|
We do not recommend hosting public servers. Darkflame Universe is intended for small scale deployment, for example within a group of friends. It has not been tested for large scale deployment which comes with additional security risks.
|
||||||
|
|
||||||
### Supply of resource files
|
### Supply of resource files
|
||||||
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed [here](#verifying-your-client-files) to see if a client will work.
|
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed [here](#verifying-your-client-files) to see if a client will work.
|
||||||
|
|
||||||
## Setting up a single player server
|
## Step by step walkthrough for a single-player server
|
||||||
* If you don't know what WSL is, skip this warning.
|
If you would like a setup for a single player server only on a Windows machine, use the [Native Windows Setup Guide by HailStorm](https://gist.github.com/HailStorm32/169df65a47a104199b5cc57d10fa57de) and skip this README.
|
||||||
Warning: WSL version 1 does NOT support using sqlite as a database due to how it handles filesystem synchronization.
|
|
||||||
You must use Version 2 if you must run the server under WSL. Not doing so will result in save data loss.
|
|
||||||
* Single player installs now no longer require building the server from source or installing development tools.
|
|
||||||
* Download the [latest windows release](https://github.com/DarkflameUniverse/DarkflameServer/releases) (or whichever release you need) and extract the files into a folder inside your client. Note that this setup is expecting that when double clicking the folder that you put in the same folder as `legouniverse.exe`, the file `MasterServer.exe` is in there.
|
|
||||||
* You should be able to see the folder with the server files in the same folder as `legouniverse.exe`.
|
|
||||||
* Go into the server files folder and open `sharedconfig.ini`. Find the line that says `client_location` and put `..` after it so the line reads `client_location=..`.
|
|
||||||
* To run the server, double-click `MasterServer.exe`.
|
|
||||||
* You will be asked to create an account the first time you run the server. After you have created the account, the server will shutdown and need to be restarted.
|
|
||||||
* To connect to the server, either delete the file `boot.cfg` which is found in your LEGO Universe client, rename the file `boot.cfg` to something else or follow the steps [here](#allowing-a-user-to-connect-to-your-server) if you wish to keep the file.
|
|
||||||
* When shutting down the server, it is highly recommended to click the `MasterServer.exe` window and hold `ctrl` while pressing `c` to stop the server.
|
|
||||||
* We are working on a way to make it so when you close the game, the server stops automatically alongside when you open the game, the server starts automatically.
|
|
||||||
|
|
||||||
<font size="32">**If you are not planning on hosting a server for others, working in the codebase or wanting to use MariaDB for a database, you can stop reading here.**</font>
|
## Steps to setup server
|
||||||
|
|
||||||
If you would like to use a MariaDB as a database instead of the default of sqlite, follow the steps [here](#database-setup).
|
|
||||||
|
|
||||||
# Steps to setup a development environment
|
|
||||||
* [Clone this repository](#clone-the-repository)
|
* [Clone this repository](#clone-the-repository)
|
||||||
* [Setting up a development environment](#setting-up-a-development-environment)
|
|
||||||
* [Install dependencies](#install-dependencies)
|
* [Install dependencies](#install-dependencies)
|
||||||
* [Database setup](#database-setup)
|
* [Database setup](#database-setup)
|
||||||
* [Build the server](#build-the-server)
|
* [Build the server](#build-the-server)
|
||||||
@@ -51,13 +39,6 @@ If you would like to use a MariaDB as a database instead of the default of sqlit
|
|||||||
* [User Guide](#user-guide)
|
* [User Guide](#user-guide)
|
||||||
* [Docker](#docker)
|
* [Docker](#docker)
|
||||||
|
|
||||||
## Disclaimers
|
|
||||||
### Setup difficulty
|
|
||||||
Throughout the entire build and setup process a level of familiarity with the command line and preferably a Unix-like development environment is greatly advantageous.
|
|
||||||
|
|
||||||
## Step by step walkthrough for building a single-player Windows server from source
|
|
||||||
If you would like a setup for a single player server only on a Windows machine built from source, use the [Native Windows Setup Guide by HailStorm](https://gist.github.com/HailStorm32/169df65a47a104199b5cc57d10fa57de) and skip this README.
|
|
||||||
|
|
||||||
## Clone the repository
|
## Clone the repository
|
||||||
If you are on Windows, you will need to download and install git from [here](https://git-scm.com/download/win)
|
If you are on Windows, you will need to download and install git from [here](https://git-scm.com/download/win)
|
||||||
|
|
||||||
@@ -92,7 +73,7 @@ sudo apt install build-essential gcc zlib1g-dev libssl-dev openssl mariadb-serve
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Required CMake version
|
#### Required CMake version
|
||||||
This project uses <font size="4">**CMake version 3.25**</font> or higher and as such you will need to ensure you have this version installed.
|
This project uses <font size="4">**CMake version 3.18**</font> or higher and as such you will need to ensure you have this version installed.
|
||||||
You can check your CMake version by using the following command in a terminal.
|
You can check your CMake version by using the following command in a terminal.
|
||||||
```bash
|
```bash
|
||||||
cmake --version
|
cmake --version
|
||||||
@@ -285,8 +266,8 @@ systemctl stop darkflame.service
|
|||||||
journalctl -xeu darkflame.service
|
journalctl -xeu darkflame.service
|
||||||
```
|
```
|
||||||
|
|
||||||
### First user or adding more users.
|
### First admin user
|
||||||
The first time you run `MasterServer`, you will be prompted to create an account. To create more accounts from the command line, `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users!
|
Run `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users!
|
||||||
|
|
||||||
### Account management tool (Nexus Dashboard)
|
### Account management tool (Nexus Dashboard)
|
||||||
**If you are just using this server for yourself, you can skip setting up Nexus Dashboard**
|
**If you are just using this server for yourself, you can skip setting up Nexus Dashboard**
|
||||||
@@ -390,7 +371,7 @@ at once. For that:
|
|||||||
- Download the [.env.example](.env.example) file and place it next to `client` with the file name `.env`
|
- Download the [.env.example](.env.example) file and place it next to `client` with the file name `.env`
|
||||||
- You may get warnings that this name starts with a dot, acknowledge those, this is intentional. Depending on your operating system, you may need to activate showing hidden files (e.g. Ctrl-H in Gnome on Linux) and/or file extensions ("File name extensions" in the "View" tab on Windows).
|
- You may get warnings that this name starts with a dot, acknowledge those, this is intentional. Depending on your operating system, you may need to activate showing hidden files (e.g. Ctrl-H in Gnome on Linux) and/or file extensions ("File name extensions" in the "View" tab on Windows).
|
||||||
- Update the `ACCOUNT_MANAGER_SECRET` and `MARIADB_PASSWORD` with strong random passwords.
|
- Update the `ACCOUNT_MANAGER_SECRET` and `MARIADB_PASSWORD` with strong random passwords.
|
||||||
- Use a password generator <https://gchq.github.io/CyberChef/#recipe=Pseudo-Random_Number_Generator(256,'Hex')>
|
- Use a password generator like <https://keygen.io>
|
||||||
- Avoid `:` and `@` characters
|
- Avoid `:` and `@` characters
|
||||||
- Once the database user is created, changing the password will not update it, so the server will just fail to connect.
|
- Once the database user is created, changing the password will not update it, so the server will just fail to connect.
|
||||||
- Set `EXTERNAL_IP` to your LAN IP or public IP if you want to host the game for friends & family
|
- Set `EXTERNAL_IP` to your LAN IP or public IP if you want to host the game for friends & family
|
||||||
|
|||||||
3
build.sh
3
build.sh
@@ -6,7 +6,8 @@ mkdir -p build
|
|||||||
cd build
|
cd build
|
||||||
|
|
||||||
# Run cmake to generate make files
|
# Run cmake to generate make files
|
||||||
cmake -DCMAKE_BUILD_TYPE="Release" ..
|
cmake ..
|
||||||
|
|
||||||
# To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
|
# To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
|
||||||
cmake --build . --config Release $1
|
cmake --build . --config Release $1
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
# Try and find a clang-16 install, falling back to a generic clang install otherwise
|
|
||||||
find_program(CLANG_C_COMPILER clang-16 | clang REQUIRED)
|
|
||||||
find_program(CLANG_CXX_COMPILER clang++-16 | clang++ REQUIRED)
|
|
||||||
|
|
||||||
# Debug messages
|
|
||||||
message(DEBUG "CLANG_C_COMPILER = ${CLANG_C_COMPILER}")
|
|
||||||
message(DEBUG "CLANG_CXX_COMPILER = ${CLANG_CXX_COMPILER}")
|
|
||||||
|
|
||||||
# Set compilers to clang (need to cache for VSCode tools to work correctly)
|
|
||||||
set(CMAKE_C_COMPILER ${CLANG_C_COMPILER} CACHE STRING "Set C compiler")
|
|
||||||
set(CMAKE_CXX_COMPILER ${CLANG_CXX_COMPILER} CACHE STRING "Set C++ compiler")
|
|
||||||
|
|
||||||
# Set linker to lld
|
|
||||||
add_link_options("-fuse-ld=lld")
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Try and find a gcc/g++ install
|
|
||||||
find_program(GNU_C_COMPILER cc | gcc REQUIRED)
|
|
||||||
find_program(GNU_CXX_COMPILER c++ | g++ REQUIRED)
|
|
||||||
|
|
||||||
# Debug messages
|
|
||||||
message(DEBUG "GNU_C_COMPILER = ${GNU_C_COMPILER}")
|
|
||||||
message(DEBUG "GNU_CXX_COMPILER = ${GNU_CXX_COMPILER}")
|
|
||||||
|
|
||||||
# Set compilers to GNU (need to cache for VSCode tools to work correctly)
|
|
||||||
set(CMAKE_C_COMPILER ${GNU_C_COMPILER} CACHE STRING "Set C compiler")
|
|
||||||
set(CMAKE_CXX_COMPILER ${GNU_CXX_COMPILER} CACHE STRING "Set C++ compiler")
|
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
//Auth includes:
|
//Auth includes:
|
||||||
#include "AuthPackets.h"
|
#include "AuthPackets.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "MessageType/Server.h"
|
#include "eServerMessageType.h"
|
||||||
#include "MessageType/Auth.h"
|
#include "eAuthMessageType.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
@@ -60,7 +60,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Database::Connect();
|
Database::Connect();
|
||||||
} catch (std::exception& ex) {
|
} catch (sql::SQLException& ex) {
|
||||||
LOG("Got an error while connecting to the database: %s", ex.what());
|
LOG("Got an error while connecting to the database: %s", ex.what());
|
||||||
Database::Destroy("AuthServer");
|
Database::Destroy("AuthServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
@@ -102,7 +102,7 @@ int main(int argc, char** argv) {
|
|||||||
uint32_t framesSinceLastSQLPing = 0;
|
uint32_t framesSinceLastSQLPing = 0;
|
||||||
|
|
||||||
AuthPackets::LoadClaimCodes();
|
AuthPackets::LoadClaimCodes();
|
||||||
|
|
||||||
Game::logger->Flush(); // once immediately before main loop
|
Game::logger->Flush(); // once immediately before main loop
|
||||||
while (!Game::ShouldShutdown()) {
|
while (!Game::ShouldShutdown()) {
|
||||||
//Check if we're still connected to master:
|
//Check if we're still connected to master:
|
||||||
@@ -166,11 +166,11 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
|
||||||
if (static_cast<MessageType::Server>(packet->data[3]) == MessageType::Server::VERSION_CONFIRM) {
|
if (static_cast<eServerMessageType>(packet->data[3]) == eServerMessageType::VERSION_CONFIRM) {
|
||||||
AuthPackets::HandleHandshake(Game::server, packet);
|
AuthPackets::HandleHandshake(Game::server, packet);
|
||||||
}
|
}
|
||||||
} else if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::AUTH) {
|
} else if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::AUTH) {
|
||||||
if (static_cast<MessageType::Auth>(packet->data[3]) == MessageType::Auth::LOGIN_REQUEST) {
|
if (static_cast<eAuthMessageType>(packet->data[3]) == eAuthMessageType::LOGIN_REQUEST) {
|
||||||
AuthPackets::HandleLoginRequest(Game::server, packet);
|
AuthPackets::HandleLoginRequest(Game::server, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
|
|||||||
ExportWordlistToDCF(filepath + ".dcf", true);
|
ExportWordlistToDCF(filepath + ".dcf", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BinaryIO::DoesFileExist("blocklist.dcf")) {
|
if (BinaryIO::DoesFileExist("blacklist.dcf")) {
|
||||||
ReadWordlistDCF("blocklist.dcf", false);
|
ReadWordlistDCF("blacklist.dcf", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read player names that are ok as well:
|
//Read player names that are ok as well:
|
||||||
@@ -44,20 +44,20 @@ dChatFilter::~dChatFilter() {
|
|||||||
m_DeniedWords.clear();
|
m_DeniedWords.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool allowList) {
|
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
|
||||||
if (allowList) m_ApprovedWords.push_back(CalculateHash(line));
|
if (whiteList) m_ApprovedWords.push_back(CalculateHash(line));
|
||||||
else m_DeniedWords.push_back(CalculateHash(line));
|
else m_DeniedWords.push_back(CalculateHash(line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
|
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;
|
||||||
@@ -70,13 +70,13 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
|
|||||||
if (hdr.formatVersion == formatVersion) {
|
if (hdr.formatVersion == formatVersion) {
|
||||||
size_t wordsToRead = 0;
|
size_t wordsToRead = 0;
|
||||||
BinaryIO::BinaryRead(file, wordsToRead);
|
BinaryIO::BinaryRead(file, wordsToRead);
|
||||||
if (allowList) m_ApprovedWords.reserve(wordsToRead);
|
if (whiteList) m_ApprovedWords.reserve(wordsToRead);
|
||||||
else m_DeniedWords.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);
|
||||||
if (allowList) m_ApprovedWords.push_back(word);
|
if (whiteList) m_ApprovedWords.push_back(word);
|
||||||
else m_DeniedWords.push_back(word);
|
else m_DeniedWords.push_back(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,14 +90,14 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool allowList) {
|
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(allowList ? m_ApprovedWords.size() : m_DeniedWords.size()));
|
BinaryIO::BinaryWrite(file, size_t(whiteList ? m_ApprovedWords.size() : m_DeniedWords.size()));
|
||||||
|
|
||||||
for (size_t word : allowList ? m_ApprovedWords : m_DeniedWords) {
|
for (size_t word : whiteList ? m_ApprovedWords : m_DeniedWords) {
|
||||||
BinaryIO::BinaryWrite(file, word);
|
BinaryIO::BinaryWrite(file, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,10 +105,10 @@ void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool allowLis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList) {
|
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList) {
|
||||||
if (gmLevel > eGameMasterLevel::FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
|
if (gmLevel > eGameMasterLevel::FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
|
||||||
if (message.empty()) return { };
|
if (message.empty()) return { };
|
||||||
if (!allowList && m_DeniedWords.empty()) return { { 0, message.length() } };
|
if (!whiteList && m_DeniedWords.empty()) return { { 0, message.length() } };
|
||||||
|
|
||||||
std::stringstream sMessage(message);
|
std::stringstream sMessage(message);
|
||||||
std::string segment;
|
std::string segment;
|
||||||
@@ -126,16 +126,16 @@ std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::
|
|||||||
|
|
||||||
size_t hash = CalculateHash(segment);
|
size_t hash = CalculateHash(segment);
|
||||||
|
|
||||||
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && allowList) {
|
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
|
||||||
listOfBadSegments.emplace_back(position, originalSegment.length());
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && allowList) {
|
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && whiteList) {
|
||||||
m_UserUnapprovedWordCache.push_back(hash);
|
m_UserUnapprovedWordCache.push_back(hash);
|
||||||
listOfBadSegments.emplace_back(position, originalSegment.length());
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !allowList) {
|
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !whiteList) {
|
||||||
m_UserUnapprovedWordCache.push_back(hash);
|
m_UserUnapprovedWordCache.push_back(hash);
|
||||||
listOfBadSegments.emplace_back(position, originalSegment.length());
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ public:
|
|||||||
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
|
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
|
||||||
~dChatFilter();
|
~dChatFilter();
|
||||||
|
|
||||||
void ReadWordlistPlaintext(const std::string& filepath, bool allowList);
|
void ReadWordlistPlaintext(const std::string& filepath, bool whiteList);
|
||||||
bool ReadWordlistDCF(const std::string& filepath, bool allowList);
|
bool ReadWordlistDCF(const std::string& filepath, bool whiteList);
|
||||||
void ExportWordlistToDCF(const std::string& filepath, bool allowList);
|
void ExportWordlistToDCF(const std::string& filepath, bool whiteList);
|
||||||
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList = true);
|
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_DontGenerateDCF;
|
bool m_DontGenerateDCF;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "ChatIgnoreList.h"
|
#include "ChatIgnoreList.h"
|
||||||
#include "PlayerContainer.h"
|
#include "PlayerContainer.h"
|
||||||
#include "MessageType/Chat.h"
|
#include "eChatInternalMessageType.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
// The only thing not auto-handled is instance activities force joining the team on the server.
|
// The only thing not auto-handled is instance activities force joining the team on the server.
|
||||||
|
|
||||||
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
|
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receivingPlayer);
|
bitStream.Write(receivingPlayer);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "MessageType/Chat.h"
|
#include "eChatMessageType.h"
|
||||||
#include "MessageType/Client.h"
|
#include "eChatInternalMessageType.h"
|
||||||
#include "MessageType/Game.h"
|
#include "eClientMessageType.h"
|
||||||
|
#include "eGameMessageType.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "ChatPackets.h"
|
|
||||||
|
|
||||||
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||||
//Get from the packet which player we want to do something with:
|
//Get from the packet which player we want to do something with:
|
||||||
@@ -60,11 +60,11 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
|
|
||||||
//Now, we need to send the friendlist to the server they came from:
|
//Now, we need to send the friendlist to the server they came from:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(playerID);
|
bitStream.Write(playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::GET_FRIENDS_LIST_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(0);
|
bitStream.Write<uint8_t>(0);
|
||||||
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
||||||
bitStream.Write<uint16_t>(player.friends.size());
|
bitStream.Write<uint16_t>(player.friends.size());
|
||||||
@@ -355,68 +355,7 @@ void ChatPacketHandler::HandleGMLevelUpdate(Packet* packet) {
|
|||||||
inStream.Read(player.gmLevel);
|
inStream.Read(player.gmLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the structure the client uses to send this packet is shared in many chat messages
|
||||||
void ChatPacketHandler::HandleWho(Packet* packet) {
|
|
||||||
CINSTREAM_SKIP_HEADER;
|
|
||||||
FindPlayerRequest request;
|
|
||||||
request.Deserialize(inStream);
|
|
||||||
|
|
||||||
const auto& sender = Game::playerContainer.GetPlayerData(request.requestor);
|
|
||||||
if (!sender) return;
|
|
||||||
|
|
||||||
const auto& player = Game::playerContainer.GetPlayerData(request.playerName.GetAsString());
|
|
||||||
bool online = player;
|
|
||||||
|
|
||||||
CBITSTREAM;
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
|
||||||
bitStream.Write(request.requestor);
|
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::WHO_RESPONSE);
|
|
||||||
bitStream.Write<uint8_t>(online);
|
|
||||||
bitStream.Write(player.zoneID.GetMapID());
|
|
||||||
bitStream.Write(player.zoneID.GetInstanceID());
|
|
||||||
bitStream.Write(player.zoneID.GetCloneID());
|
|
||||||
bitStream.Write(request.playerName);
|
|
||||||
|
|
||||||
SystemAddress sysAddr = sender.sysAddr;
|
|
||||||
SEND_PACKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatPacketHandler::HandleShowAll(Packet* packet) {
|
|
||||||
CINSTREAM_SKIP_HEADER;
|
|
||||||
ShowAllRequest request;
|
|
||||||
request.Deserialize(inStream);
|
|
||||||
|
|
||||||
const auto& sender = Game::playerContainer.GetPlayerData(request.requestor);
|
|
||||||
if (!sender) return;
|
|
||||||
|
|
||||||
CBITSTREAM;
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
|
||||||
bitStream.Write(request.requestor);
|
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::SHOW_ALL_RESPONSE);
|
|
||||||
bitStream.Write<uint8_t>(!request.displayZoneData && !request.displayIndividualPlayers);
|
|
||||||
bitStream.Write(Game::playerContainer.GetPlayerCount());
|
|
||||||
bitStream.Write(Game::playerContainer.GetSimCount());
|
|
||||||
bitStream.Write<uint8_t>(request.displayIndividualPlayers);
|
|
||||||
bitStream.Write<uint8_t>(request.displayZoneData);
|
|
||||||
if (request.displayZoneData || request.displayIndividualPlayers){
|
|
||||||
for (auto& [playerID, playerData ]: Game::playerContainer.GetAllPlayers()){
|
|
||||||
if (!playerData) continue;
|
|
||||||
bitStream.Write<uint8_t>(0); // structure packing
|
|
||||||
if (request.displayIndividualPlayers) bitStream.Write(LUWString(playerData.playerName));
|
|
||||||
if (request.displayZoneData) {
|
|
||||||
bitStream.Write(playerData.zoneID.GetMapID());
|
|
||||||
bitStream.Write(playerData.zoneID.GetInstanceID());
|
|
||||||
bitStream.Write(playerData.zoneID.GetCloneID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SystemAddress sysAddr = sender.sysAddr;
|
|
||||||
SEND_PACKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the structure the client uses to send this packet is shared in many chat messages
|
|
||||||
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
|
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
|
||||||
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
@@ -428,7 +367,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
eChatChannel channel;
|
eChatChannel channel;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
inStream.IgnoreBytes(4);
|
inStream.IgnoreBytes(4);
|
||||||
inStream.Read(channel);
|
inStream.Read(channel);
|
||||||
inStream.Read(size);
|
inStream.Read(size);
|
||||||
@@ -436,7 +375,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
LUWString message(size);
|
LUWString message(size);
|
||||||
inStream.Read(message);
|
inStream.Read(message);
|
||||||
|
|
||||||
LOG("Got a message from (%s) via [%s]: %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str());
|
LOG("Got a message from (%s) via [%s]: %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str());
|
||||||
|
|
||||||
switch (channel) {
|
switch (channel) {
|
||||||
@@ -457,7 +396,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the structure the client uses to send this packet is shared in many chat messages
|
// the structure the client uses to send this packet is shared in many chat messages
|
||||||
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
|
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
|
||||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
@@ -484,7 +423,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
LUWString message(size);
|
LUWString message(size);
|
||||||
inStream.Read(message);
|
inStream.Read(message);
|
||||||
|
|
||||||
LOG("Got a message from (%s) via [%s]: %s to %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str(), receiverName.c_str());
|
LOG("Got a message from (%s) via [%s]: %s to %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str(), receiverName.c_str());
|
||||||
|
|
||||||
const auto& receiver = Game::playerContainer.GetPlayerData(receiverName);
|
const auto& receiver = Game::playerContainer.GetPlayerData(receiverName);
|
||||||
@@ -515,10 +454,10 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) {
|
void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(routeTo.playerID);
|
bitStream.Write(routeTo.playerID);
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(sender.playerID);
|
bitStream.Write(sender.playerID);
|
||||||
bitStream.Write(channel);
|
bitStream.Write(channel);
|
||||||
bitStream.Write<uint32_t>(0); // not used
|
bitStream.Write<uint32_t>(0); // not used
|
||||||
@@ -757,11 +696,11 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
|
void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::TEAM_INVITE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
||||||
|
|
||||||
bitStream.Write(LUWString(sender.playerName.c_str()));
|
bitStream.Write(LUWString(sender.playerName.c_str()));
|
||||||
bitStream.Write(sender.playerID);
|
bitStream.Write(sender.playerID);
|
||||||
@@ -770,68 +709,86 @@ void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerD
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, TeamData* team, uint8_t responseCode) {
|
||||||
|
if(!team) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER;
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
bitStream.Write(MessageType::Game::TEAM_INVITE_CONFIRM);
|
bitStream.Write(eGameMessageType::TEAM_INVITE_CONFIRM);
|
||||||
|
const auto& leader = Game::playerContainer.GetPlayerData(team->leaderID);
|
||||||
|
|
||||||
bitStream.Write(bLeaderIsFreeTrial);
|
bitStream.Write(leader.isFTP);
|
||||||
bitStream.Write(i64LeaderID);
|
bitStream.Write(team->leaderID);
|
||||||
bitStream.Write(i64LeaderZoneID);
|
bitStream.Write(leader.zoneID);
|
||||||
bitStream.Write<uint32_t>(0); // BinaryBuffe, no clue what's in here
|
bitStream.Write<uint32_t>((team->memberIDs.size() - 1) * ((sizeof(int16_t) * 33) + sizeof(LWOOBJID) + sizeof(LWOZONEID)));
|
||||||
bitStream.Write(ucLootFlag);
|
for (const auto memberid: team->memberIDs){
|
||||||
bitStream.Write(ucNumOfOtherPlayers);
|
if (memberid == team->leaderID) continue;
|
||||||
bitStream.Write(ucResponseCode);
|
const auto& member = Game::playerContainer.GetPlayerData(memberid);
|
||||||
bitStream.Write<uint32_t>(wsLeaderName.size());
|
bitStream.Write(LUWString(member.playerName));
|
||||||
for (const auto character : wsLeaderName) {
|
bitStream.Write(memberid);
|
||||||
bitStream.Write(character);
|
bitStream.Write(member.zoneID);
|
||||||
}
|
}
|
||||||
|
bitStream.Write(team->lootFlag);
|
||||||
|
bitStream.Write(team->memberIDs.size());
|
||||||
|
bitStream.Write(responseCode);
|
||||||
|
const std::u16string wsLeaderName = GeneralUtils::UTF8ToUTF16(leader.playerName);
|
||||||
|
bitStream.Write<uint32_t>(wsLeaderName.size());
|
||||||
|
bitStream.Write(wsLeaderName);
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver.sysAddr;
|
SystemAddress sysAddr = receiver.sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, TeamData* team) {
|
||||||
|
if(!team) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
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(MessageType::Game::TEAM_GET_STATUS_RESPONSE);
|
bitStream.Write(eGameMessageType::TEAM_GET_STATUS_RESPONSE);
|
||||||
|
|
||||||
bitStream.Write(i64LeaderID);
|
bitStream.Write(team->leaderID);
|
||||||
bitStream.Write(i64LeaderZoneID);
|
const auto& leader = Game::playerContainer.GetPlayerData(team->leaderID);
|
||||||
bitStream.Write<uint32_t>(0); // BinaryBuffe, no clue what's in here
|
|
||||||
bitStream.Write(ucLootFlag);
|
bitStream.Write(leader.zoneID);
|
||||||
bitStream.Write(ucNumOfOtherPlayers);
|
bitStream.Write<uint32_t>((team->memberIDs.size() - 1) * ((sizeof(int16_t) * 33) + sizeof(LWOOBJID) + sizeof(LWOZONEID)));
|
||||||
bitStream.Write<uint32_t>(wsLeaderName.size());
|
for (const auto memberid: team->memberIDs){
|
||||||
for (const auto character : wsLeaderName) {
|
if (memberid == team->leaderID) continue;
|
||||||
bitStream.Write(character);
|
const auto& member = Game::playerContainer.GetPlayerData(memberid);
|
||||||
|
bitStream.Write(LUWString(member.playerName));
|
||||||
|
bitStream.Write(memberid);
|
||||||
|
bitStream.Write(member.zoneID);
|
||||||
}
|
}
|
||||||
|
bitStream.Write(team->lootFlag);
|
||||||
|
bitStream.Write(team->memberIDs.size());
|
||||||
|
const std::u16string wsLeaderName = GeneralUtils::UTF8ToUTF16(leader.playerName);
|
||||||
|
bitStream.Write<uint32_t>(wsLeaderName.size());
|
||||||
|
bitStream.Write(wsLeaderName);
|
||||||
SystemAddress sysAddr = receiver.sysAddr;
|
SystemAddress sysAddr = receiver.sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
|
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER;
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
bitStream.Write(MessageType::Game::TEAM_SET_LEADER);
|
bitStream.Write(eGameMessageType::TEAM_SET_LEADER);
|
||||||
|
|
||||||
bitStream.Write(i64PlayerID);
|
bitStream.Write(i64PlayerID);
|
||||||
|
|
||||||
@@ -841,14 +798,14 @@ void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER;
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
bitStream.Write(MessageType::Game::TEAM_ADD_PLAYER);
|
bitStream.Write(eGameMessageType::TEAM_ADD_PLAYER);
|
||||||
|
|
||||||
bitStream.Write(bIsFreeTrial);
|
bitStream.Write(bIsFreeTrial);
|
||||||
bitStream.Write(bLocal);
|
bitStream.Write(bLocal);
|
||||||
@@ -870,14 +827,14 @@ void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFr
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER;
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
bitStream.Write(MessageType::Game::TEAM_REMOVE_PLAYER);
|
bitStream.Write(eGameMessageType::TEAM_REMOVE_PLAYER);
|
||||||
|
|
||||||
bitStream.Write(bDisband);
|
bitStream.Write(bDisband);
|
||||||
bitStream.Write(bIsKicked);
|
bitStream.Write(bIsKicked);
|
||||||
@@ -896,14 +853,14 @@ void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bD
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
CMSGHEADER;
|
CMSGHEADER;
|
||||||
|
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
bitStream.Write(MessageType::Game::TEAM_SET_OFF_WORLD_FLAG);
|
bitStream.Write(eGameMessageType::TEAM_SET_OFF_WORLD_FLAG);
|
||||||
|
|
||||||
bitStream.Write(i64PlayerID);
|
bitStream.Write(i64PlayerID);
|
||||||
if (receiver.zoneID.GetCloneID() == zoneID.GetCloneID()) {
|
if (receiver.zoneID.GetCloneID() == zoneID.GetCloneID()) {
|
||||||
@@ -930,11 +887,11 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
|
|||||||
[bool] - is FTP*/
|
[bool] - is FTP*/
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(friendData.playerID);
|
bitStream.Write(friendData.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::UPDATE_FRIEND_NOTIFY);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
||||||
bitStream.Write<uint8_t>(notifyType);
|
bitStream.Write<uint8_t>(notifyType);
|
||||||
|
|
||||||
std::string playerName = playerData.playerName.c_str();
|
std::string playerName = playerData.playerName.c_str();
|
||||||
@@ -967,11 +924,11 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::ADD_FRIEND_REQUEST);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
||||||
bitStream.Write(LUWString(sender.playerName));
|
bitStream.Write(LUWString(sender.playerName));
|
||||||
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
||||||
|
|
||||||
@@ -981,11 +938,11 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
|
|||||||
|
|
||||||
void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) {
|
void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
// Portion that will get routed:
|
// Portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::ADD_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
||||||
bitStream.Write(responseCode);
|
bitStream.Write(responseCode);
|
||||||
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
||||||
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender.sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender.sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
@@ -1004,11 +961,11 @@ void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const Pla
|
|||||||
|
|
||||||
void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
|
void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::REMOVE_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
||||||
bitStream.Write(LUWString(personToRemove));
|
bitStream.Write(LUWString(personToRemove));
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
|
|
||||||
struct PlayerData;
|
struct PlayerData;
|
||||||
|
struct TeamData;
|
||||||
|
|
||||||
enum class eAddFriendResponseType : uint8_t;
|
enum class eAddFriendResponseType : uint8_t;
|
||||||
|
|
||||||
@@ -50,8 +51,6 @@ namespace ChatPacketHandler {
|
|||||||
void HandleFriendResponse(Packet* packet);
|
void HandleFriendResponse(Packet* packet);
|
||||||
void HandleRemoveFriend(Packet* packet);
|
void HandleRemoveFriend(Packet* packet);
|
||||||
void HandleGMLevelUpdate(Packet* packet);
|
void HandleGMLevelUpdate(Packet* packet);
|
||||||
void HandleWho(Packet* packet);
|
|
||||||
void HandleShowAll(Packet* packet);
|
|
||||||
|
|
||||||
void HandleChatMessage(Packet* packet);
|
void HandleChatMessage(Packet* packet);
|
||||||
void HandlePrivateChatMessage(Packet* packet);
|
void HandlePrivateChatMessage(Packet* packet);
|
||||||
@@ -66,8 +65,8 @@ namespace ChatPacketHandler {
|
|||||||
void HandleTeamStatusRequest(Packet* packet);
|
void HandleTeamStatusRequest(Packet* packet);
|
||||||
|
|
||||||
void SendTeamInvite(const PlayerData& receiver, const PlayerData& sender);
|
void SendTeamInvite(const PlayerData& receiver, const PlayerData& sender);
|
||||||
void SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName);
|
void SendTeamInviteConfirm(const PlayerData& receiver, TeamData* team, uint8_t responseCode);
|
||||||
void SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName);
|
void SendTeamStatus(const PlayerData& receiver, TeamData* team);
|
||||||
void SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID);
|
void SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID);
|
||||||
void SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID);
|
void SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID);
|
||||||
void SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName);
|
void SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName);
|
||||||
|
|||||||
@@ -16,8 +16,9 @@
|
|||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "PlayerContainer.h"
|
#include "PlayerContainer.h"
|
||||||
#include "ChatPacketHandler.h"
|
#include "ChatPacketHandler.h"
|
||||||
#include "MessageType/Chat.h"
|
#include "eChatMessageType.h"
|
||||||
#include "MessageType/World.h"
|
#include "eChatInternalMessageType.h"
|
||||||
|
#include "eWorldMessageType.h"
|
||||||
#include "ChatIgnoreList.h"
|
#include "ChatIgnoreList.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ int main(int argc, char** argv) {
|
|||||||
//Connect to the MySQL Database
|
//Connect to the MySQL Database
|
||||||
try {
|
try {
|
||||||
Database::Connect();
|
Database::Connect();
|
||||||
} catch (std::exception& ex) {
|
} catch (sql::SQLException& ex) {
|
||||||
LOG("Got an error while connecting to the database: %s", ex.what());
|
LOG("Got an error while connecting to the database: %s", ex.what());
|
||||||
Database::Destroy("ChatServer");
|
Database::Destroy("ChatServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
@@ -108,7 +109,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
|
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
|
||||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
||||||
|
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
|
|
||||||
Game::playerContainer.Initialize();
|
Game::playerContainer.Initialize();
|
||||||
@@ -179,168 +180,185 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
if (packet->length < 1) return;
|
|
||||||
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) {
|
||||||
LOG("A server has disconnected, erasing their connected players from the list.");
|
LOG("A server has disconnected, erasing their connected players from the list.");
|
||||||
} else if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
}
|
||||||
|
|
||||||
|
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
||||||
LOG("A server is connecting, awaiting user list.");
|
LOG("A server is connecting, awaiting user list.");
|
||||||
} else if (packet->length < 4 || packet->data[0] != ID_USER_PACKET_ENUM) return; // Nothing left to process or not the right packet type
|
}
|
||||||
|
|
||||||
CINSTREAM;
|
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
|
||||||
inStream.SetReadOffset(BYTES_TO_BITS(1));
|
|
||||||
|
|
||||||
eConnectionType connection;
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
|
||||||
MessageType::Chat chatMessageID;
|
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
|
||||||
|
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
|
||||||
|
Game::playerContainer.InsertPlayer(packet);
|
||||||
|
break;
|
||||||
|
|
||||||
inStream.Read(connection);
|
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
|
||||||
if (connection != eConnectionType::CHAT) return;
|
Game::playerContainer.RemovePlayer(packet);
|
||||||
inStream.Read(chatMessageID);
|
break;
|
||||||
|
|
||||||
switch (chatMessageID) {
|
case eChatInternalMessageType::MUTE_UPDATE:
|
||||||
case MessageType::Chat::GM_MUTE:
|
|
||||||
Game::playerContainer.MuteUpdate(packet);
|
Game::playerContainer.MuteUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::CREATE_TEAM:
|
case eChatInternalMessageType::CREATE_TEAM:
|
||||||
Game::playerContainer.CreateTeamServer(packet);
|
Game::playerContainer.CreateTeamServer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::GET_FRIENDS_LIST:
|
case eChatInternalMessageType::ANNOUNCEMENT: {
|
||||||
|
//we just forward this packet to every connected server
|
||||||
|
CINSTREAM;
|
||||||
|
Game::server->Send(inStream, packet->systemAddress, true); //send to everyone except origin
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOG("Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
|
||||||
|
eChatMessageType chat_message_type = static_cast<eChatMessageType>(packet->data[3]);
|
||||||
|
switch (chat_message_type) {
|
||||||
|
case eChatMessageType::GET_FRIENDS_LIST:
|
||||||
ChatPacketHandler::HandleFriendlistRequest(packet);
|
ChatPacketHandler::HandleFriendlistRequest(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::GET_IGNORE_LIST:
|
case eChatMessageType::GET_IGNORE_LIST:
|
||||||
ChatIgnoreList::GetIgnoreList(packet);
|
ChatIgnoreList::GetIgnoreList(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::ADD_IGNORE:
|
case eChatMessageType::ADD_IGNORE:
|
||||||
ChatIgnoreList::AddIgnore(packet);
|
ChatIgnoreList::AddIgnore(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::REMOVE_IGNORE:
|
case eChatMessageType::REMOVE_IGNORE:
|
||||||
ChatIgnoreList::RemoveIgnore(packet);
|
ChatIgnoreList::RemoveIgnore(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::TEAM_GET_STATUS:
|
case eChatMessageType::TEAM_GET_STATUS:
|
||||||
ChatPacketHandler::HandleTeamStatusRequest(packet);
|
ChatPacketHandler::HandleTeamStatusRequest(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::ADD_FRIEND_REQUEST:
|
case eChatMessageType::ADD_FRIEND_REQUEST:
|
||||||
//this involves someone sending the initial request, the response is below, response as in from the other player.
|
//this involves someone sending the initial request, the response is below, response as in from the other player.
|
||||||
//We basically just check to see if this player is online or not and route the packet.
|
//We basically just check to see if this player is online or not and route the packet.
|
||||||
ChatPacketHandler::HandleFriendRequest(packet);
|
ChatPacketHandler::HandleFriendRequest(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::ADD_FRIEND_RESPONSE:
|
case eChatMessageType::ADD_FRIEND_RESPONSE:
|
||||||
//This isn't the response a server sent, rather it is a player's response to a received request.
|
//This isn't the response a server sent, rather it is a player's response to a received request.
|
||||||
//Here, we'll actually have to add them to eachother's friend lists depending on the response code.
|
//Here, we'll actually have to add them to eachother's friend lists depending on the response code.
|
||||||
ChatPacketHandler::HandleFriendResponse(packet);
|
ChatPacketHandler::HandleFriendResponse(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::REMOVE_FRIEND:
|
case eChatMessageType::REMOVE_FRIEND:
|
||||||
ChatPacketHandler::HandleRemoveFriend(packet);
|
ChatPacketHandler::HandleRemoveFriend(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::GENERAL_CHAT_MESSAGE:
|
case eChatMessageType::GENERAL_CHAT_MESSAGE:
|
||||||
ChatPacketHandler::HandleChatMessage(packet);
|
ChatPacketHandler::HandleChatMessage(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::PRIVATE_CHAT_MESSAGE:
|
case eChatMessageType::PRIVATE_CHAT_MESSAGE:
|
||||||
//This message is supposed to be echo'd to both the sender and the receiver
|
//This message is supposed to be echo'd to both the sender and the receiver
|
||||||
//BUT: they have to have different responseCodes, so we'll do some of the ol hacky wacky to fix that right up.
|
//BUT: they have to have different responseCodes, so we'll do some of the ol hacky wacky to fix that right up.
|
||||||
ChatPacketHandler::HandlePrivateChatMessage(packet);
|
ChatPacketHandler::HandlePrivateChatMessage(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::TEAM_INVITE:
|
case eChatMessageType::TEAM_INVITE:
|
||||||
ChatPacketHandler::HandleTeamInvite(packet);
|
ChatPacketHandler::HandleTeamInvite(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::TEAM_INVITE_RESPONSE:
|
case eChatMessageType::TEAM_INVITE_RESPONSE:
|
||||||
ChatPacketHandler::HandleTeamInviteResponse(packet);
|
ChatPacketHandler::HandleTeamInviteResponse(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::TEAM_LEAVE:
|
case eChatMessageType::TEAM_LEAVE:
|
||||||
ChatPacketHandler::HandleTeamLeave(packet);
|
ChatPacketHandler::HandleTeamLeave(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::TEAM_SET_LEADER:
|
case eChatMessageType::TEAM_SET_LEADER:
|
||||||
ChatPacketHandler::HandleTeamPromote(packet);
|
ChatPacketHandler::HandleTeamPromote(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::TEAM_KICK:
|
case eChatMessageType::TEAM_KICK:
|
||||||
ChatPacketHandler::HandleTeamKick(packet);
|
ChatPacketHandler::HandleTeamKick(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType::Chat::TEAM_SET_LOOT:
|
case eChatMessageType::TEAM_SET_LOOT:
|
||||||
ChatPacketHandler::HandleTeamLootOption(packet);
|
ChatPacketHandler::HandleTeamLootOption(packet);
|
||||||
break;
|
break;
|
||||||
case MessageType::Chat::GMLEVEL_UPDATE:
|
case eChatMessageType::GMLEVEL_UPDATE:
|
||||||
ChatPacketHandler::HandleGMLevelUpdate(packet);
|
ChatPacketHandler::HandleGMLevelUpdate(packet);
|
||||||
break;
|
break;
|
||||||
case MessageType::Chat::LOGIN_SESSION_NOTIFY:
|
case eChatMessageType::LOGIN_SESSION_NOTIFY:
|
||||||
Game::playerContainer.InsertPlayer(packet);
|
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
|
||||||
break;
|
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
|
||||||
case MessageType::Chat::GM_ANNOUNCE:{
|
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
|
||||||
// we just forward this packet to every connected server
|
case eChatMessageType::WORLD_PARCEL_RESPONSE:
|
||||||
inStream.ResetReadPointer();
|
case eChatMessageType::TEAM_MISSED_INVITE_CHECK:
|
||||||
Game::server->Send(inStream, packet->systemAddress, true); // send to everyone except origin
|
case eChatMessageType::GUILD_CREATE:
|
||||||
}
|
case eChatMessageType::GUILD_INVITE:
|
||||||
break;
|
case eChatMessageType::GUILD_INVITE_RESPONSE:
|
||||||
case MessageType::Chat::UNEXPECTED_DISCONNECT:
|
case eChatMessageType::GUILD_LEAVE:
|
||||||
Game::playerContainer.RemovePlayer(packet);
|
case eChatMessageType::GUILD_KICK:
|
||||||
break;
|
case eChatMessageType::GUILD_GET_STATUS:
|
||||||
case MessageType::Chat::WHO:
|
case eChatMessageType::GUILD_GET_ALL:
|
||||||
ChatPacketHandler::HandleWho(packet);
|
case eChatMessageType::SHOW_ALL:
|
||||||
break;
|
case eChatMessageType::BLUEPRINT_MODERATED:
|
||||||
case MessageType::Chat::SHOW_ALL:
|
case eChatMessageType::BLUEPRINT_MODEL_READY:
|
||||||
ChatPacketHandler::HandleShowAll(packet);
|
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
|
||||||
break;
|
case eChatMessageType::PROPERTY_MODERATION_CHANGED:
|
||||||
case MessageType::Chat::USER_CHANNEL_CHAT_MESSAGE:
|
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED:
|
||||||
case MessageType::Chat::WORLD_DISCONNECT_REQUEST:
|
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED_REPORT:
|
||||||
case MessageType::Chat::WORLD_PROXIMITY_RESPONSE:
|
case eChatMessageType::MAIL:
|
||||||
case MessageType::Chat::WORLD_PARCEL_RESPONSE:
|
case eChatMessageType::WORLD_INSTANCE_LOCATION_REQUEST:
|
||||||
case MessageType::Chat::TEAM_MISSED_INVITE_CHECK:
|
case eChatMessageType::REPUTATION_UPDATE:
|
||||||
case MessageType::Chat::GUILD_CREATE:
|
case eChatMessageType::SEND_CANNED_TEXT:
|
||||||
case MessageType::Chat::GUILD_INVITE:
|
case eChatMessageType::CHARACTER_NAME_CHANGE_REQUEST:
|
||||||
case MessageType::Chat::GUILD_INVITE_RESPONSE:
|
case eChatMessageType::CSR_REQUEST:
|
||||||
case MessageType::Chat::GUILD_LEAVE:
|
case eChatMessageType::CSR_REPLY:
|
||||||
case MessageType::Chat::GUILD_KICK:
|
case eChatMessageType::GM_KICK:
|
||||||
case MessageType::Chat::GUILD_GET_STATUS:
|
case eChatMessageType::GM_ANNOUNCE:
|
||||||
case MessageType::Chat::GUILD_GET_ALL:
|
case eChatMessageType::WORLD_ROUTE_PACKET:
|
||||||
case MessageType::Chat::BLUEPRINT_MODERATED:
|
case eChatMessageType::GET_ZONE_POPULATIONS:
|
||||||
case MessageType::Chat::BLUEPRINT_MODEL_READY:
|
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
|
||||||
case MessageType::Chat::PROPERTY_READY_FOR_APPROVAL:
|
case eChatMessageType::MATCH_REQUEST:
|
||||||
case MessageType::Chat::PROPERTY_MODERATION_CHANGED:
|
case eChatMessageType::UGCMANIFEST_REPORT_MISSING_FILE:
|
||||||
case MessageType::Chat::PROPERTY_BUILDMODE_CHANGED:
|
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
|
||||||
case MessageType::Chat::PROPERTY_BUILDMODE_CHANGED_REPORT:
|
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
||||||
case MessageType::Chat::MAIL:
|
case eChatMessageType::UGCC_REQUEST:
|
||||||
case MessageType::Chat::WORLD_INSTANCE_LOCATION_REQUEST:
|
case eChatMessageType::WHO:
|
||||||
case MessageType::Chat::REPUTATION_UPDATE:
|
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
||||||
case MessageType::Chat::SEND_CANNED_TEXT:
|
case eChatMessageType::ACHIEVEMENT_NOTIFY:
|
||||||
case MessageType::Chat::CHARACTER_NAME_CHANGE_REQUEST:
|
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
||||||
case MessageType::Chat::CSR_REQUEST:
|
case eChatMessageType::UNEXPECTED_DISCONNECT:
|
||||||
case MessageType::Chat::CSR_REPLY:
|
case eChatMessageType::PLAYER_READY:
|
||||||
case MessageType::Chat::GM_KICK:
|
case eChatMessageType::GET_DONATION_TOTAL:
|
||||||
case MessageType::Chat::WORLD_ROUTE_PACKET:
|
case eChatMessageType::UPDATE_DONATION:
|
||||||
case MessageType::Chat::GET_ZONE_POPULATIONS:
|
case eChatMessageType::PRG_CSR_COMMAND:
|
||||||
case MessageType::Chat::REQUEST_MINIMUM_CHAT_MODE:
|
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
|
||||||
case MessageType::Chat::MATCH_REQUEST:
|
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
|
||||||
case MessageType::Chat::UGCMANIFEST_REPORT_MISSING_FILE:
|
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chat_message_type).data(), chat_message_type);
|
||||||
case MessageType::Chat::UGCMANIFEST_REPORT_DONE_FILE:
|
|
||||||
case MessageType::Chat::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
|
||||||
case MessageType::Chat::UGCC_REQUEST:
|
|
||||||
case MessageType::Chat::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
|
||||||
case MessageType::Chat::ACHIEVEMENT_NOTIFY:
|
|
||||||
case MessageType::Chat::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
|
||||||
case MessageType::Chat::PLAYER_READY:
|
|
||||||
case MessageType::Chat::GET_DONATION_TOTAL:
|
|
||||||
case MessageType::Chat::UPDATE_DONATION:
|
|
||||||
case MessageType::Chat::PRG_CSR_COMMAND:
|
|
||||||
case MessageType::Chat::HEARTBEAT_REQUEST_FROM_WORLD:
|
|
||||||
case MessageType::Chat::UPDATE_FREE_TRIAL_STATUS:
|
|
||||||
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG("Unknown CHAT Message id: %i", chatMessageID);
|
LOG("Unknown CHAT Message id: %i", chat_message_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) {
|
||||||
|
switch (static_cast<eWorldMessageType>(packet->data[3])) {
|
||||||
|
case eWorldMessageType::ROUTE_PACKET: {
|
||||||
|
LOG("Routing packet from world");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOG("Unknown World id: %i", int(packet->data[3]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
|
#include "eChatInternalMessageType.h"
|
||||||
#include "ChatPackets.h"
|
#include "ChatPackets.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "MessageType/Chat.h"
|
|
||||||
|
|
||||||
void PlayerContainer::Initialize() {
|
void PlayerContainer::Initialize() {
|
||||||
m_MaxNumberOfBestFriends =
|
m_MaxNumberOfBestFriends =
|
||||||
@@ -36,23 +36,19 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
data.playerID = playerId;
|
data.playerID = playerId;
|
||||||
|
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
if (!inStream.Read<uint32_t>(len)) return;
|
inStream.Read<uint32_t>(len);
|
||||||
|
|
||||||
if (len > 33) {
|
for (int i = 0; i < len; i++) {
|
||||||
LOG("Received a really long player name, probably a fake packet %i.", len);
|
char character; inStream.Read<char>(character);
|
||||||
return;
|
data.playerName += character;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.playerName.resize(len);
|
inStream.Read(data.zoneID);
|
||||||
inStream.ReadAlignedBytes(reinterpret_cast<unsigned char*>(data.playerName.data()), len);
|
inStream.Read(data.muteExpire);
|
||||||
|
inStream.Read(data.gmLevel);
|
||||||
if (!inStream.Read(data.zoneID)) return;
|
|
||||||
if (!inStream.Read(data.muteExpire)) return;
|
|
||||||
if (!inStream.Read(data.gmLevel)) return;
|
|
||||||
data.sysAddr = packet->systemAddress;
|
data.sysAddr = packet->systemAddress;
|
||||||
|
|
||||||
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
|
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
|
||||||
m_PlayerCount++;
|
|
||||||
|
|
||||||
LOG("Added user: %s (%llu), zone: %i", data.playerName.c_str(), data.playerID, data.zoneID.GetMapID());
|
LOG("Added user: %s (%llu), zone: %i", data.playerName.c_str(), data.playerID, data.zoneID.GetMapID());
|
||||||
|
|
||||||
@@ -91,7 +87,6 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_PlayerCount--;
|
|
||||||
LOG("Removed user: %llu", playerID);
|
LOG("Removed user: %llu", playerID);
|
||||||
m_Players.erase(playerID);
|
m_Players.erase(playerID);
|
||||||
|
|
||||||
@@ -125,11 +120,6 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
|||||||
size_t membersSize = 0;
|
size_t membersSize = 0;
|
||||||
inStream.Read(membersSize);
|
inStream.Read(membersSize);
|
||||||
|
|
||||||
if (membersSize >= 4) {
|
|
||||||
LOG("Tried to create a team with more than 4 players");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<LWOOBJID> members;
|
std::vector<LWOOBJID> members;
|
||||||
|
|
||||||
members.reserve(membersSize);
|
members.reserve(membersSize);
|
||||||
@@ -148,13 +138,14 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
|||||||
|
|
||||||
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;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::GM_MUTE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(player);
|
bitStream.Write(player);
|
||||||
bitStream.Write(time);
|
bitStream.Write(time);
|
||||||
@@ -237,7 +228,7 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
|||||||
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader.playerName);
|
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader.playerName);
|
||||||
const auto memberName = GeneralUtils::UTF8ToUTF16(member.playerName);
|
const auto memberName = GeneralUtils::UTF8ToUTF16(member.playerName);
|
||||||
|
|
||||||
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader.playerID, leader.zoneID, team->lootFlag, 0, 0, leaderName);
|
ChatPacketHandler::SendTeamInviteConfirm(member, team, 0);
|
||||||
|
|
||||||
if (!team->local) {
|
if (!team->local) {
|
||||||
ChatPacketHandler::SendTeamSetLeader(member, leader.playerID);
|
ChatPacketHandler::SendTeamSetLeader(member, leader.playerID);
|
||||||
@@ -352,7 +343,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
|||||||
if (!otherMember) continue;
|
if (!otherMember) continue;
|
||||||
|
|
||||||
if (!team->local) {
|
if (!team->local) {
|
||||||
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader.zoneID, team->lootFlag, 0, leaderName);
|
ChatPacketHandler::SendTeamStatus(otherMember, team);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +352,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
|||||||
|
|
||||||
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::TEAM_GET_STATUS);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(team->teamID);
|
bitStream.Write(team->teamID);
|
||||||
bitStream.Write(deleteTeam);
|
bitStream.Write(deleteTeam);
|
||||||
@@ -399,7 +390,7 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
|
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
|
||||||
return m_Players.contains(playerID) ? m_Players[playerID] : m_Players[LWOOBJID_EMPTY];
|
return m_Players[playerID];
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {
|
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {
|
||||||
|
|||||||
@@ -71,9 +71,6 @@ public:
|
|||||||
const PlayerData& GetPlayerData(const std::string& playerName);
|
const PlayerData& GetPlayerData(const std::string& playerName);
|
||||||
PlayerData& GetPlayerDataMutable(const LWOOBJID& playerID);
|
PlayerData& GetPlayerDataMutable(const LWOOBJID& playerID);
|
||||||
PlayerData& GetPlayerDataMutable(const std::string& playerName);
|
PlayerData& GetPlayerDataMutable(const std::string& playerName);
|
||||||
uint32_t GetPlayerCount() { return m_PlayerCount; };
|
|
||||||
uint32_t GetSimCount() { return m_SimCount; };
|
|
||||||
const std::map<LWOOBJID, PlayerData>& GetAllPlayers() { return m_Players; };
|
|
||||||
|
|
||||||
TeamData* CreateLocalTeam(std::vector<LWOOBJID> members);
|
TeamData* CreateLocalTeam(std::vector<LWOOBJID> members);
|
||||||
TeamData* CreateTeam(LWOOBJID leader, bool local = false);
|
TeamData* CreateTeam(LWOOBJID leader, bool local = false);
|
||||||
@@ -96,7 +93,5 @@ private:
|
|||||||
std::unordered_map<LWOOBJID, std::u16string> m_Names;
|
std::unordered_map<LWOOBJID, std::u16string> m_Names;
|
||||||
uint32_t m_MaxNumberOfBestFriends = 5;
|
uint32_t m_MaxNumberOfBestFriends = 5;
|
||||||
uint32_t m_MaxNumberOfFriends = 50;
|
uint32_t m_MaxNumberOfFriends = 50;
|
||||||
uint32_t m_PlayerCount = 0;
|
|
||||||
uint32_t m_SimCount = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,54 +9,73 @@
|
|||||||
* AMF3 Deserializer written by EmosewaMC
|
* AMF3 Deserializer written by EmosewaMC
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::unique_ptr<AMFBaseValue> AMFDeserialize::Read(RakNet::BitStream& inStream) {
|
AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream& inStream) {
|
||||||
|
AMFBaseValue* returnValue = nullptr;
|
||||||
// Read in the value type from the bitStream
|
// Read in the value type from the bitStream
|
||||||
eAmf marker;
|
eAmf marker;
|
||||||
inStream.Read(marker);
|
inStream.Read(marker);
|
||||||
// Based on the typing, create the value associated with that and return the base value class
|
// Based on the typing, create the value associated with that and return the base value class
|
||||||
switch (marker) {
|
switch (marker) {
|
||||||
case eAmf::Undefined:
|
case eAmf::Undefined: {
|
||||||
return std::make_unique<AMFBaseValue>();
|
returnValue = new AMFBaseValue();
|
||||||
case eAmf::Null:
|
break;
|
||||||
return std::make_unique<AMFNullValue>();
|
}
|
||||||
case eAmf::False:
|
|
||||||
return std::make_unique<AMFBoolValue>(false);
|
case eAmf::Null: {
|
||||||
case eAmf::True:
|
returnValue = new AMFNullValue();
|
||||||
return std::make_unique<AMFBoolValue>(true);
|
break;
|
||||||
case eAmf::Integer:
|
}
|
||||||
return ReadAmfInteger(inStream);
|
|
||||||
case eAmf::Double:
|
case eAmf::False: {
|
||||||
return ReadAmfDouble(inStream);
|
returnValue = new AMFBoolValue(false);
|
||||||
case eAmf::String:
|
break;
|
||||||
return ReadAmfString(inStream);
|
}
|
||||||
case eAmf::Array:
|
|
||||||
return ReadAmfArray(inStream);
|
case eAmf::True: {
|
||||||
|
returnValue = new AMFBoolValue(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::Integer: {
|
||||||
|
returnValue = ReadAmfInteger(inStream);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::Double: {
|
||||||
|
returnValue = ReadAmfDouble(inStream);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::String: {
|
||||||
|
returnValue = ReadAmfString(inStream);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::Array: {
|
||||||
|
returnValue = ReadAmfArray(inStream);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// These values are unimplemented in the live client and will remain unimplemented
|
// These values are unimplemented in the live client and will remain unimplemented
|
||||||
// unless someone modifies the client to allow serializing of these values.
|
// unless someone modifies the client to allow serializing of these values.
|
||||||
case eAmf::XMLDoc:
|
case eAmf::XMLDoc:
|
||||||
[[fallthrough]];
|
|
||||||
case eAmf::Date:
|
case eAmf::Date:
|
||||||
[[fallthrough]];
|
|
||||||
case eAmf::Object:
|
case eAmf::Object:
|
||||||
[[fallthrough]];
|
|
||||||
case eAmf::XML:
|
case eAmf::XML:
|
||||||
[[fallthrough]];
|
|
||||||
case eAmf::ByteArray:
|
case eAmf::ByteArray:
|
||||||
[[fallthrough]];
|
|
||||||
case eAmf::VectorInt:
|
case eAmf::VectorInt:
|
||||||
[[fallthrough]];
|
|
||||||
case eAmf::VectorUInt:
|
case eAmf::VectorUInt:
|
||||||
[[fallthrough]];
|
|
||||||
case eAmf::VectorDouble:
|
case eAmf::VectorDouble:
|
||||||
[[fallthrough]];
|
|
||||||
case eAmf::VectorObject:
|
case eAmf::VectorObject:
|
||||||
[[fallthrough]];
|
case eAmf::Dictionary: {
|
||||||
case eAmf::Dictionary:
|
|
||||||
throw marker;
|
throw marker;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast<int32_t>(marker)));
|
throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast<int32_t>(marker)));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AMFDeserialize::ReadU29(RakNet::BitStream& inStream) {
|
uint32_t AMFDeserialize::ReadU29(RakNet::BitStream& inStream) {
|
||||||
@@ -99,14 +118,14 @@ const std::string AMFDeserialize::ReadString(RakNet::BitStream& inStream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<AMFDoubleValue> AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) {
|
||||||
double value;
|
double value;
|
||||||
inStream.Read<double>(value);
|
inStream.Read<double>(value);
|
||||||
return std::make_unique<AMFDoubleValue>(value);
|
return new AMFDoubleValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<AMFArrayValue> AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) {
|
||||||
auto arrayValue = std::make_unique<AMFArrayValue>();
|
auto arrayValue = new AMFArrayValue();
|
||||||
|
|
||||||
// Read size of dense array
|
// Read size of dense array
|
||||||
const auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
const auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
||||||
@@ -124,10 +143,10 @@ std::unique_ptr<AMFArrayValue> AMFDeserialize::ReadAmfArray(RakNet::BitStream& i
|
|||||||
return arrayValue;
|
return arrayValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<AMFStringValue> AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) {
|
||||||
return std::make_unique<AMFStringValue>(ReadString(inStream));
|
return new AMFStringValue(ReadString(inStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<AMFIntValue> AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) {
|
||||||
return std::make_unique<AMFIntValue>(ReadU29(inStream)); // NOTE: NARROWING CONVERSION FROM UINT TO INT. IS THIS INTENDED?
|
return new AMFIntValue(ReadU29(inStream));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Amf3.h"
|
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
class AMFBaseValue;
|
||||||
|
|
||||||
class AMFDeserialize {
|
class AMFDeserialize {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -15,7 +15,7 @@ public:
|
|||||||
* @param inStream inStream to read value from.
|
* @param inStream inStream to read value from.
|
||||||
* @return Returns an AMFValue with all the information from the bitStream in it.
|
* @return Returns an AMFValue with all the information from the bitStream in it.
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<AMFBaseValue> Read(RakNet::BitStream& inStream);
|
AMFBaseValue* Read(RakNet::BitStream& inStream);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Private method to read a U29 integer from a bitstream
|
* @brief Private method to read a U29 integer from a bitstream
|
||||||
@@ -39,7 +39,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Double value represented as an AMFValue
|
* @return Double value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
static std::unique_ptr<AMFDoubleValue> ReadAmfDouble(RakNet::BitStream& inStream);
|
AMFBaseValue* ReadAmfDouble(RakNet::BitStream& inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFArray from a bitStream
|
* @brief Read an AMFArray from a bitStream
|
||||||
@@ -47,7 +47,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Array value represented as an AMFValue
|
* @return Array value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<AMFArrayValue> ReadAmfArray(RakNet::BitStream& inStream);
|
AMFBaseValue* ReadAmfArray(RakNet::BitStream& inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFString from a bitStream
|
* @brief Read an AMFString from a bitStream
|
||||||
@@ -55,7 +55,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return String value represented as an AMFValue
|
* @return String value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<AMFStringValue> ReadAmfString(RakNet::BitStream& inStream);
|
AMFBaseValue* ReadAmfString(RakNet::BitStream& inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFInteger from a bitStream
|
* @brief Read an AMFInteger from a bitStream
|
||||||
@@ -63,7 +63,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Integer value represented as an AMFValue
|
* @return Integer value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
static std::unique_ptr<AMFIntValue> ReadAmfInteger(RakNet::BitStream& inStream);
|
AMFBaseValue* ReadAmfInteger(RakNet::BitStream& inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of strings read so far saved to be read by reference.
|
* List of strings read so far saved to be read by reference.
|
||||||
|
|||||||
@@ -105,14 +105,27 @@ using AMFDoubleValue = AMFValue<double>;
|
|||||||
* and are not to be deleted by a caller.
|
* and are not to be deleted by a caller.
|
||||||
*/
|
*/
|
||||||
class AMFArrayValue : public AMFBaseValue {
|
class AMFArrayValue : public AMFBaseValue {
|
||||||
using AMFAssociative =
|
using AMFAssociative = std::unordered_map<std::string, AMFBaseValue*>;
|
||||||
std::unordered_map<std::string, std::unique_ptr<AMFBaseValue>, GeneralUtils::transparent_string_hash, std::equal_to<>>;
|
using AMFDense = std::vector<AMFBaseValue*>;
|
||||||
|
|
||||||
using AMFDense = std::vector<std::unique_ptr<AMFBaseValue>>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::Array; }
|
[[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::Array; }
|
||||||
|
|
||||||
|
~AMFArrayValue() override {
|
||||||
|
for (const auto* valueToDelete : GetDense()) {
|
||||||
|
if (valueToDelete) {
|
||||||
|
delete valueToDelete;
|
||||||
|
valueToDelete = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto valueToDelete : GetAssociative()) {
|
||||||
|
if (valueToDelete.second) {
|
||||||
|
delete valueToDelete.second;
|
||||||
|
valueToDelete.second = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Associative portion of the object
|
* Returns the Associative portion of the object
|
||||||
*/
|
*/
|
||||||
@@ -138,32 +151,30 @@ public:
|
|||||||
* or nullptr if a key existed and was not the same type
|
* or nullptr if a key existed and was not the same type
|
||||||
*/
|
*/
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string_view key, const ValueType value) {
|
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, const ValueType value) {
|
||||||
const auto element = m_Associative.find(key);
|
const auto element = m_Associative.find(key);
|
||||||
AMFValue<ValueType>* val = nullptr;
|
AMFValue<ValueType>* val = nullptr;
|
||||||
bool found = true;
|
bool found = true;
|
||||||
if (element == m_Associative.cend()) {
|
if (element == m_Associative.cend()) {
|
||||||
auto newVal = std::make_unique<AMFValue<ValueType>>(value);
|
val = new AMFValue<ValueType>(value);
|
||||||
val = newVal.get();
|
m_Associative.emplace(key, val);
|
||||||
m_Associative.emplace(key, std::move(newVal));
|
|
||||||
} else {
|
} else {
|
||||||
val = dynamic_cast<AMFValue<ValueType>*>(element->second.get());
|
val = dynamic_cast<AMFValue<ValueType>*>(element->second);
|
||||||
found = false;
|
found = false;
|
||||||
}
|
}
|
||||||
return std::make_pair(val, found);
|
return std::make_pair(val, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Associates an array with a string key
|
// Associates an array with a string key
|
||||||
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string_view key) {
|
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
|
||||||
const auto element = m_Associative.find(key);
|
const auto element = m_Associative.find(key);
|
||||||
AMFArrayValue* val = nullptr;
|
AMFArrayValue* val = nullptr;
|
||||||
bool found = true;
|
bool found = true;
|
||||||
if (element == m_Associative.cend()) {
|
if (element == m_Associative.cend()) {
|
||||||
auto newVal = std::make_unique<AMFArrayValue>();
|
val = new AMFArrayValue();
|
||||||
val = newVal.get();
|
m_Associative.emplace(key, val);
|
||||||
m_Associative.emplace(key, std::move(newVal));
|
|
||||||
} else {
|
} else {
|
||||||
val = dynamic_cast<AMFArrayValue*>(element->second.get());
|
val = dynamic_cast<AMFArrayValue*>(element->second);
|
||||||
found = false;
|
found = false;
|
||||||
}
|
}
|
||||||
return std::make_pair(val, found);
|
return std::make_pair(val, found);
|
||||||
@@ -171,13 +182,15 @@ public:
|
|||||||
|
|
||||||
// Associates an array with an integer key
|
// Associates an array with an integer key
|
||||||
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const size_t index) {
|
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const size_t index) {
|
||||||
|
AMFArrayValue* val = nullptr;
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
if (index >= m_Dense.size()) {
|
if (index >= m_Dense.size()) {
|
||||||
m_Dense.resize(index + 1);
|
m_Dense.resize(index + 1);
|
||||||
m_Dense.at(index) = std::make_unique<AMFArrayValue>();
|
val = new AMFArrayValue();
|
||||||
|
m_Dense.at(index) = val;
|
||||||
inserted = true;
|
inserted = true;
|
||||||
}
|
}
|
||||||
return std::make_pair(dynamic_cast<AMFArrayValue*>(m_Dense.at(index).get()), inserted);
|
return std::make_pair(dynamic_cast<AMFArrayValue*>(m_Dense.at(index)), inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -192,13 +205,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const size_t index, const ValueType value) {
|
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const size_t index, const ValueType value) {
|
||||||
|
AMFValue<ValueType>* val = nullptr;
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
if (index >= m_Dense.size()) {
|
if (index >= m_Dense.size()) {
|
||||||
m_Dense.resize(index + 1);
|
m_Dense.resize(index + 1);
|
||||||
m_Dense.at(index) = std::make_unique<AMFValue<ValueType>>(value);
|
val = new AMFValue<ValueType>(value);
|
||||||
|
m_Dense.at(index) = val;
|
||||||
inserted = true;
|
inserted = true;
|
||||||
}
|
}
|
||||||
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(m_Dense.at(index).get()), inserted);
|
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(m_Dense.at(index)), inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,12 +225,13 @@ public:
|
|||||||
* @param key The key to associate with the value
|
* @param key The key to associate with the value
|
||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
void Insert(const std::string_view key, std::unique_ptr<AMFBaseValue> value) {
|
void Insert(const std::string& key, AMFBaseValue* const value) {
|
||||||
const auto element = m_Associative.find(key);
|
const auto element = m_Associative.find(key);
|
||||||
if (element != m_Associative.cend() && element->second) {
|
if (element != m_Associative.cend() && element->second) {
|
||||||
element->second = std::move(value);
|
delete element->second;
|
||||||
|
element->second = value;
|
||||||
} else {
|
} else {
|
||||||
m_Associative.emplace(key, std::move(value));
|
m_Associative.emplace(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,11 +244,14 @@ public:
|
|||||||
* @param key The key to associate with the value
|
* @param key The key to associate with the value
|
||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
void Insert(const size_t index, std::unique_ptr<AMFBaseValue> value) {
|
void Insert(const size_t index, AMFBaseValue* const value) {
|
||||||
if (index >= m_Dense.size()) {
|
if (index < m_Dense.size()) {
|
||||||
|
const AMFDense::const_iterator itr = m_Dense.cbegin() + index;
|
||||||
|
if (*itr) delete m_Dense.at(index);
|
||||||
|
} else {
|
||||||
m_Dense.resize(index + 1);
|
m_Dense.resize(index + 1);
|
||||||
}
|
}
|
||||||
m_Dense.at(index) = std::move(value);
|
m_Dense.at(index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -260,7 +279,8 @@ public:
|
|||||||
void Remove(const std::string& key, const bool deleteValue = true) {
|
void Remove(const std::string& key, const bool deleteValue = true) {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||||
if (it != m_Associative.cend()) {
|
if (it != m_Associative.cend()) {
|
||||||
if (deleteValue) m_Associative.erase(it);
|
if (deleteValue) delete it->second;
|
||||||
|
m_Associative.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +290,7 @@ public:
|
|||||||
void Remove(const size_t index) {
|
void Remove(const size_t index) {
|
||||||
if (!m_Dense.empty() && index < m_Dense.size()) {
|
if (!m_Dense.empty() && index < m_Dense.size()) {
|
||||||
const auto itr = m_Dense.cbegin() + index;
|
const auto itr = m_Dense.cbegin() + index;
|
||||||
|
if (*itr) delete (*itr);
|
||||||
m_Dense.erase(itr);
|
m_Dense.erase(itr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,16 +299,16 @@ public:
|
|||||||
if (!m_Dense.empty()) Remove(m_Dense.size() - 1);
|
if (!m_Dense.empty()) Remove(m_Dense.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] AMFArrayValue* GetArray(const std::string_view key) const {
|
[[nodiscard]] AMFArrayValue* GetArray(const std::string& key) const {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||||
return it != m_Associative.cend() ? dynamic_cast<AMFArrayValue*>(it->second.get()) : nullptr;
|
return it != m_Associative.cend() ? dynamic_cast<AMFArrayValue*>(it->second) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] AMFArrayValue* GetArray(const size_t index) const {
|
[[nodiscard]] AMFArrayValue* GetArray(const size_t index) const {
|
||||||
return index < m_Dense.size() ? dynamic_cast<AMFArrayValue*>(m_Dense.at(index).get()) : nullptr;
|
return index < m_Dense.size() ? dynamic_cast<AMFArrayValue*>(m_Dense.at(index)) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string_view key) {
|
[[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string& key) {
|
||||||
return static_cast<AMFArrayValue*>(Insert(key).first);
|
return static_cast<AMFArrayValue*>(Insert(key).first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,17 +330,17 @@ public:
|
|||||||
* @return The AMFValue
|
* @return The AMFValue
|
||||||
*/
|
*/
|
||||||
template <typename AmfType>
|
template <typename AmfType>
|
||||||
[[nodiscard]] AMFValue<AmfType>* Get(const std::string_view key) const {
|
[[nodiscard]] AMFValue<AmfType>* Get(const std::string& key) const {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||||
return it != m_Associative.cend() ?
|
return it != m_Associative.cend() ?
|
||||||
dynamic_cast<AMFValue<AmfType>*>(it->second.get()) :
|
dynamic_cast<AMFValue<AmfType>*>(it->second) :
|
||||||
nullptr;
|
nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get from the array but dont cast it
|
// Get from the array but dont cast it
|
||||||
[[nodiscard]] AMFBaseValue* Get(const std::string_view key) const {
|
[[nodiscard]] AMFBaseValue* Get(const std::string& key) const {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||||
return it != m_Associative.cend() ? it->second.get() : nullptr;
|
return it != m_Associative.cend() ? it->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -334,13 +355,13 @@ public:
|
|||||||
template <typename AmfType>
|
template <typename AmfType>
|
||||||
[[nodiscard]] AMFValue<AmfType>* Get(const size_t index) const {
|
[[nodiscard]] AMFValue<AmfType>* Get(const size_t index) const {
|
||||||
return index < m_Dense.size() ?
|
return index < m_Dense.size() ?
|
||||||
dynamic_cast<AMFValue<AmfType>*>(m_Dense.at(index).get()) :
|
dynamic_cast<AMFValue<AmfType>*>(m_Dense.at(index)) :
|
||||||
nullptr;
|
nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get from the dense but dont cast it
|
// Get from the dense but dont cast it
|
||||||
[[nodiscard]] AMFBaseValue* Get(const size_t index) const {
|
[[nodiscard]] AMFBaseValue* Get(const size_t index) const {
|
||||||
return index < m_Dense.size() ? m_Dense.at(index).get() : nullptr;
|
return index < m_Dense.size() ? m_Dense.at(index) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -2,25 +2,16 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
//For reading null-terminated strings
|
//For reading null-terminated strings
|
||||||
template<typename StringType>
|
std::string BinaryIO::ReadString(std::istream& instream) {
|
||||||
StringType ReadString(std::istream& instream) {
|
std::string toReturn;
|
||||||
StringType toReturn{};
|
char buffer;
|
||||||
typename StringType::value_type buffer{};
|
|
||||||
|
|
||||||
BinaryIO::BinaryRead(instream, buffer);
|
BinaryIO::BinaryRead(instream, buffer);
|
||||||
|
|
||||||
while (buffer != 0x00) {
|
while (buffer != 0x00) {
|
||||||
toReturn += buffer;
|
toReturn += buffer;
|
||||||
BinaryIO::BinaryRead(instream, buffer);
|
BinaryRead(instream, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BinaryIO::ReadString(std::istream& instream) {
|
|
||||||
return ::ReadString<std::string>(instream);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::u8string BinaryIO::ReadU8String(std::istream& instream) {
|
|
||||||
return ::ReadString<std::u8string>(instream);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ namespace BinaryIO {
|
|||||||
|
|
||||||
std::string ReadString(std::istream& instream);
|
std::string ReadString(std::istream& instream);
|
||||||
|
|
||||||
std::u8string ReadU8String(std::istream& instream);
|
|
||||||
|
|
||||||
inline bool DoesFileExist(const std::string& name) {
|
inline bool DoesFileExist(const std::string& name) {
|
||||||
std::ifstream f(name.c_str());
|
std::ifstream f(name.c_str());
|
||||||
return f.good();
|
return f.good();
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
|
|||||||
Database::Get()->UpdateUgcModelData(model.id, outputStringStream);
|
Database::Get()->UpdateUgcModelData(model.id, outputStringStream);
|
||||||
LOG("Updated model %i to sd0", model.id);
|
LOG("Updated model %i to sd0", model.id);
|
||||||
updatedModels++;
|
updatedModels++;
|
||||||
} catch (std::exception& exception) {
|
} catch (sql::SQLException exception) {
|
||||||
LOG("Failed to update model %i. This model should be inspected manually to see why."
|
LOG("Failed to update model %i. This model should be inspected manually to see why."
|
||||||
"The database error is %s", model.id, exception.what());
|
"The database error is %s", model.id, exception.what());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ target_include_directories(dCommon
|
|||||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
|
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
|
||||||
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
|
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
|
||||||
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase"
|
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase"
|
||||||
|
"${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/include"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
|
|||||||
@@ -120,8 +120,6 @@ void CatchUnhandled(int sig) {
|
|||||||
if (eptr) std::rethrow_exception(eptr);
|
if (eptr) std::rethrow_exception(eptr);
|
||||||
} catch(const std::exception& e) {
|
} catch(const std::exception& e) {
|
||||||
LOG("Caught exception: '%s'", e.what());
|
LOG("Caught exception: '%s'", e.what());
|
||||||
} catch (...) {
|
|
||||||
LOG("Caught unknown exception.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef INCLUDE_BACKTRACE
|
#ifndef INCLUDE_BACKTRACE
|
||||||
@@ -201,7 +199,7 @@ void OnTerminate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MakeBacktrace() {
|
void MakeBacktrace() {
|
||||||
struct sigaction sigact{};
|
struct sigaction sigact;
|
||||||
|
|
||||||
sigact.sa_sigaction = CritErrHdlr;
|
sigact.sa_sigaction = CritErrHdlr;
|
||||||
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
|
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||||
|
|||||||
@@ -65,14 +65,13 @@ int64_t FdbToSqlite::Convert::ReadInt64(std::istream& cdClientBuffer) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cdclient is encoded in latin1
|
|
||||||
std::string FdbToSqlite::Convert::ReadString(std::istream& cdClientBuffer) {
|
std::string FdbToSqlite::Convert::ReadString(std::istream& cdClientBuffer) {
|
||||||
int32_t prevPosition = SeekPointer(cdClientBuffer);
|
int32_t prevPosition = SeekPointer(cdClientBuffer);
|
||||||
|
|
||||||
const auto readString = BinaryIO::ReadU8String(cdClientBuffer);
|
auto readString = BinaryIO::ReadString(cdClientBuffer);
|
||||||
|
|
||||||
cdClientBuffer.seekg(prevPosition);
|
cdClientBuffer.seekg(prevPosition);
|
||||||
return GeneralUtils::Latin1ToUTF8(readString);
|
return readString;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t FdbToSqlite::Convert::SeekPointer(std::istream& cdClientBuffer) {
|
int32_t FdbToSqlite::Convert::SeekPointer(std::istream& cdClientBuffer) {
|
||||||
|
|||||||
@@ -8,23 +8,23 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline size_t MinSize(const size_t size, const std::basic_string_view<T> string) {
|
inline size_t MinSize(size_t size, const std::basic_string_view<T>& string) {
|
||||||
if (size == SIZE_MAX || size > string.size()) {
|
if (size == size_t(-1) || size > string.size()) {
|
||||||
return string.size();
|
return string.size();
|
||||||
} else {
|
} else {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsLeadSurrogate(const char16_t c) {
|
inline bool IsLeadSurrogate(char16_t c) {
|
||||||
return (0xD800 <= c) && (c <= 0xDBFF);
|
return (0xD800 <= c) && (c <= 0xDBFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsTrailSurrogate(const char16_t c) {
|
inline bool IsTrailSurrogate(char16_t c) {
|
||||||
return (0xDC00 <= c) && (c <= 0xDFFF);
|
return (0xDC00 <= c) && (c <= 0xDFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PushUTF8CodePoint(std::string& ret, const char32_t cp) {
|
inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
|
||||||
if (cp <= 0x007F) {
|
if (cp <= 0x007F) {
|
||||||
ret.push_back(static_cast<uint8_t>(cp));
|
ret.push_back(static_cast<uint8_t>(cp));
|
||||||
} else if (cp <= 0x07FF) {
|
} else if (cp <= 0x07FF) {
|
||||||
@@ -46,16 +46,16 @@ inline void PushUTF8CodePoint(std::string& ret, const char32_t cp) {
|
|||||||
|
|
||||||
constexpr const char16_t REPLACEMENT_CHARACTER = 0xFFFD;
|
constexpr const char16_t REPLACEMENT_CHARACTER = 0xFFFD;
|
||||||
|
|
||||||
bool static _IsSuffixChar(const uint8_t c) {
|
bool _IsSuffixChar(uint8_t c) {
|
||||||
return (c & 0xC0) == 0x80;
|
return (c & 0xC0) == 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneralUtils::details::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
||||||
const size_t rem = slice.length();
|
size_t rem = slice.length();
|
||||||
if (slice.empty()) return false;
|
if (slice.empty()) return false;
|
||||||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&slice.front());
|
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&slice.front());
|
||||||
if (rem > 0) {
|
if (rem > 0) {
|
||||||
const uint8_t first = bytes[0];
|
uint8_t first = bytes[0];
|
||||||
if (first < 0x80) { // 1 byte character
|
if (first < 0x80) { // 1 byte character
|
||||||
out = static_cast<uint32_t>(first & 0x7F);
|
out = static_cast<uint32_t>(first & 0x7F);
|
||||||
slice.remove_prefix(1);
|
slice.remove_prefix(1);
|
||||||
@@ -64,7 +64,7 @@ bool GeneralUtils::details::_NextUTF8Char(std::string_view& slice, uint32_t& out
|
|||||||
// middle byte, not valid at start, fall through
|
// middle byte, not valid at start, fall through
|
||||||
} else if (first < 0xE0) { // two byte character
|
} else if (first < 0xE0) { // two byte character
|
||||||
if (rem > 1) {
|
if (rem > 1) {
|
||||||
const uint8_t second = bytes[1];
|
uint8_t second = bytes[1];
|
||||||
if (_IsSuffixChar(second)) {
|
if (_IsSuffixChar(second)) {
|
||||||
out = (static_cast<uint32_t>(first & 0x1F) << 6)
|
out = (static_cast<uint32_t>(first & 0x1F) << 6)
|
||||||
+ static_cast<uint32_t>(second & 0x3F);
|
+ static_cast<uint32_t>(second & 0x3F);
|
||||||
@@ -74,8 +74,8 @@ bool GeneralUtils::details::_NextUTF8Char(std::string_view& slice, uint32_t& out
|
|||||||
}
|
}
|
||||||
} else if (first < 0xF0) { // three byte character
|
} else if (first < 0xF0) { // three byte character
|
||||||
if (rem > 2) {
|
if (rem > 2) {
|
||||||
const uint8_t second = bytes[1];
|
uint8_t second = bytes[1];
|
||||||
const uint8_t third = bytes[2];
|
uint8_t third = bytes[2];
|
||||||
if (_IsSuffixChar(second) && _IsSuffixChar(third)) {
|
if (_IsSuffixChar(second) && _IsSuffixChar(third)) {
|
||||||
out = (static_cast<uint32_t>(first & 0x0F) << 12)
|
out = (static_cast<uint32_t>(first & 0x0F) << 12)
|
||||||
+ (static_cast<uint32_t>(second & 0x3F) << 6)
|
+ (static_cast<uint32_t>(second & 0x3F) << 6)
|
||||||
@@ -86,9 +86,9 @@ bool GeneralUtils::details::_NextUTF8Char(std::string_view& slice, uint32_t& out
|
|||||||
}
|
}
|
||||||
} else if (first < 0xF8) { // four byte character
|
} else if (first < 0xF8) { // four byte character
|
||||||
if (rem > 3) {
|
if (rem > 3) {
|
||||||
const uint8_t second = bytes[1];
|
uint8_t second = bytes[1];
|
||||||
const uint8_t third = bytes[2];
|
uint8_t third = bytes[2];
|
||||||
const uint8_t fourth = bytes[3];
|
uint8_t fourth = bytes[3];
|
||||||
if (_IsSuffixChar(second) && _IsSuffixChar(third) && _IsSuffixChar(fourth)) {
|
if (_IsSuffixChar(second) && _IsSuffixChar(third) && _IsSuffixChar(fourth)) {
|
||||||
out = (static_cast<uint32_t>(first & 0x07) << 18)
|
out = (static_cast<uint32_t>(first & 0x07) << 18)
|
||||||
+ (static_cast<uint32_t>(second & 0x3F) << 12)
|
+ (static_cast<uint32_t>(second & 0x3F) << 12)
|
||||||
@@ -107,7 +107,7 @@ bool GeneralUtils::details::_NextUTF8Char(std::string_view& slice, uint32_t& out
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// See <https://www.ietf.org/rfc/rfc2781.html#section-2.1>
|
/// See <https://www.ietf.org/rfc/rfc2781.html#section-2.1>
|
||||||
bool PushUTF16CodePoint(std::u16string& output, const uint32_t U, const size_t size) {
|
bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
|
||||||
if (output.length() >= size) return false;
|
if (output.length() >= size) return false;
|
||||||
if (U < 0x10000) {
|
if (U < 0x10000) {
|
||||||
// If U < 0x10000, encode U as a 16-bit unsigned integer and terminate.
|
// If U < 0x10000, encode U as a 16-bit unsigned integer and terminate.
|
||||||
@@ -120,7 +120,7 @@ bool PushUTF16CodePoint(std::u16string& output, const uint32_t U, const size_t s
|
|||||||
// Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,
|
// 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
|
// U' must be less than or equal to 0xFFFFF. That is, U' can be
|
||||||
// represented in 20 bits.
|
// represented in 20 bits.
|
||||||
const uint32_t Ut = U - 0x10000;
|
uint32_t Ut = U - 0x10000;
|
||||||
|
|
||||||
// Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
|
// Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
|
||||||
// 0xDC00, respectively. These integers each have 10 bits free to
|
// 0xDC00, respectively. These integers each have 10 bits free to
|
||||||
@@ -141,25 +141,25 @@ bool PushUTF16CodePoint(std::u16string& output, const uint32_t U, const size_t s
|
|||||||
} else return false;
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view string, const size_t size) {
|
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view& string, size_t size) {
|
||||||
const size_t newSize = MinSize(size, string);
|
size_t newSize = MinSize(size, string);
|
||||||
std::u16string output;
|
std::u16string output;
|
||||||
output.reserve(newSize);
|
output.reserve(newSize);
|
||||||
std::string_view iterator = string;
|
std::string_view iterator = string;
|
||||||
|
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
while (details::_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
|
while (_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
|
||||||
return output;
|
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_view string, const size_t size) {
|
std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t size) {
|
||||||
const 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++) {
|
||||||
const char c = string[i];
|
char c = string[i];
|
||||||
// Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
|
// Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
|
||||||
ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
|
ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
|
||||||
}
|
}
|
||||||
@@ -167,29 +167,20 @@ std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view string, const s
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GeneralUtils::Latin1ToUTF8(const std::u8string_view string, const size_t size) {
|
|
||||||
std::string toReturn{};
|
|
||||||
|
|
||||||
for (const auto u : string) {
|
|
||||||
PushUTF8CodePoint(toReturn, u);
|
|
||||||
}
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! 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_view string, const size_t size) {
|
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t size) {
|
||||||
const size_t newSize = MinSize(size, string);
|
size_t newSize = MinSize(size, string);
|
||||||
std::string ret;
|
std::string ret;
|
||||||
ret.reserve(newSize);
|
ret.reserve(newSize);
|
||||||
|
|
||||||
for (size_t i = 0; i < newSize; ++i) {
|
for (size_t i = 0; i < newSize; i++) {
|
||||||
const auto u = string[i];
|
char16_t u = string[i];
|
||||||
if (IsLeadSurrogate(u) && (i + 1) < newSize) {
|
if (IsLeadSurrogate(u) && (i + 1) < newSize) {
|
||||||
const auto next = string[i + 1];
|
char16_t next = string[i + 1];
|
||||||
if (IsTrailSurrogate(next)) {
|
if (IsTrailSurrogate(next)) {
|
||||||
i += 1;
|
i += 1;
|
||||||
const char32_t cp = 0x10000
|
char32_t cp = 0x10000
|
||||||
+ ((static_cast<char32_t>(u) - 0xD800) << 10)
|
+ ((static_cast<char32_t>(u) - 0xD800) << 10)
|
||||||
+ (static_cast<char32_t>(next) - 0xDC00);
|
+ (static_cast<char32_t>(next) - 0xDC00);
|
||||||
PushUTF8CodePoint(ret, cp);
|
PushUTF8CodePoint(ret, cp);
|
||||||
@@ -204,40 +195,40 @@ std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view string, const si
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string_view a, const std::string_view 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
|
||||||
|
|
||||||
//! Sets a specific bit in a signed 64-bit integer
|
//! Sets a specific bit in a signed 64-bit integer
|
||||||
int64_t GeneralUtils::SetBit(int64_t value, const uint32_t index) {
|
int64_t GeneralUtils::SetBit(int64_t value, uint32_t index) {
|
||||||
return value |= 1ULL << index;
|
return value |= 1ULL << index;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Clears a specific bit in a signed 64-bit integer
|
//! Clears a specific bit in a signed 64-bit integer
|
||||||
int64_t GeneralUtils::ClearBit(int64_t value, const uint32_t index) {
|
int64_t GeneralUtils::ClearBit(int64_t value, uint32_t index) {
|
||||||
return value &= ~(1ULL << index);
|
return value &= ~(1ULL << index);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Checks a specific bit in a signed 64-bit integer
|
//! Checks a specific bit in a signed 64-bit integer
|
||||||
bool GeneralUtils::CheckBit(int64_t value, const uint32_t index) {
|
bool GeneralUtils::CheckBit(int64_t value, uint32_t index) {
|
||||||
return value & (1ULL << index);
|
return value & (1ULL << index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneralUtils::ReplaceInString(std::string& str, const std::string_view from, const std::string_view to) {
|
bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, const std::string& to) {
|
||||||
const 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(const std::wstring_view str, const 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;
|
||||||
|
|
||||||
for (const wchar_t c : str) {
|
for (const auto& c : str) {
|
||||||
if (c == delimiter) {
|
if (c == delimiter) {
|
||||||
vector.push_back(current);
|
vector.push_back(current);
|
||||||
current = L"";
|
current = L"";
|
||||||
@@ -246,15 +237,15 @@ std::vector<std::wstring> GeneralUtils::SplitString(const std::wstring_view str,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector.push_back(std::move(current));
|
vector.push_back(current);
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string_view str, const char16_t delimiter) {
|
std::vector<std::u16string> GeneralUtils::SplitString(const 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;
|
||||||
|
|
||||||
for (const char16_t c : str) {
|
for (const auto& c : str) {
|
||||||
if (c == delimiter) {
|
if (c == delimiter) {
|
||||||
vector.push_back(current);
|
vector.push_back(current);
|
||||||
current = u"";
|
current = u"";
|
||||||
@@ -263,15 +254,17 @@ std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string_view
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector.push_back(std::move(current));
|
vector.push_back(current);
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GeneralUtils::SplitString(const std::string_view str, const 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 (const char c : str) {
|
for (size_t i = 0; i < str.length(); i++) {
|
||||||
|
char c = str[i];
|
||||||
|
|
||||||
if (c == delimiter) {
|
if (c == delimiter) {
|
||||||
vector.push_back(current);
|
vector.push_back(current);
|
||||||
current = "";
|
current = "";
|
||||||
@@ -280,7 +273,8 @@ std::vector<std::string> GeneralUtils::SplitString(const std::string_view str, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector.push_back(std::move(current));
|
vector.push_back(current);
|
||||||
|
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +283,7 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
|
|||||||
inStream.Read<uint32_t>(length);
|
inStream.Read<uint32_t>(length);
|
||||||
|
|
||||||
std::u16string string;
|
std::u16string string;
|
||||||
for (uint32_t i = 0; i < length; ++i) {
|
for (auto i = 0; i < length; i++) {
|
||||||
uint16_t c;
|
uint16_t c;
|
||||||
inStream.Read(c);
|
inStream.Read(c);
|
||||||
string.push_back(c);
|
string.push_back(c);
|
||||||
@@ -298,36 +292,35 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
|
|||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string_view folder) {
|
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string& folder) {
|
||||||
// Because we dont know how large the initial number before the first _ is we need to make it a map like so.
|
// Because we dont know how large the initial number before the first _ is we need to make it a map like so.
|
||||||
std::map<uint32_t, std::string> filenames{};
|
std::map<uint32_t, std::string> filenames{};
|
||||||
for (const auto& t : std::filesystem::directory_iterator(folder)) {
|
for (auto& t : std::filesystem::directory_iterator(folder)) {
|
||||||
if (t.is_directory() || t.is_symlink()) continue;
|
|
||||||
auto filename = t.path().filename().string();
|
auto filename = t.path().filename().string();
|
||||||
const auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
|
auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
|
||||||
filenames.emplace(index, std::move(filename));
|
filenames.insert(std::make_pair(index, filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now sort the map by the oldest migration.
|
// Now sort the map by the oldest migration.
|
||||||
std::vector<std::string> sortedFiles{};
|
std::vector<std::string> sortedFiles{};
|
||||||
auto fileIterator = filenames.cbegin();
|
auto fileIterator = filenames.begin();
|
||||||
auto oldest = filenames.cbegin();
|
std::map<uint32_t, std::string>::iterator oldest = filenames.begin();
|
||||||
while (!filenames.empty()) {
|
while (!filenames.empty()) {
|
||||||
if (fileIterator == filenames.cend()) {
|
if (fileIterator == filenames.end()) {
|
||||||
sortedFiles.push_back(oldest->second);
|
sortedFiles.push_back(oldest->second);
|
||||||
filenames.erase(oldest);
|
filenames.erase(oldest);
|
||||||
fileIterator = filenames.cbegin();
|
fileIterator = filenames.begin();
|
||||||
oldest = filenames.cbegin();
|
oldest = filenames.begin();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (oldest->first > fileIterator->first) oldest = fileIterator;
|
if (oldest->first > fileIterator->first) oldest = fileIterator;
|
||||||
++fileIterator;
|
fileIterator++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sortedFiles;
|
return sortedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
|
#ifdef DARKFLAME_PLATFORM_MACOS
|
||||||
|
|
||||||
// MacOS floating-point parse function specializations
|
// MacOS floating-point parse function specializations
|
||||||
namespace GeneralUtils::details {
|
namespace GeneralUtils::details {
|
||||||
|
|||||||
@@ -3,18 +3,17 @@
|
|||||||
// C++
|
// C++
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ctime>
|
|
||||||
#include <functional>
|
|
||||||
#include <optional>
|
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <span>
|
#include <ctime>
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <optional>
|
||||||
|
#include <functional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <stdexcept>
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
|
|
||||||
#include "dPlatforms.h"
|
#include "dPlatforms.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
@@ -33,39 +32,29 @@ namespace GeneralUtils {
|
|||||||
//! Converts a plain ASCII string to a UTF-16 string
|
//! Converts a plain ASCII string to a UTF-16 string
|
||||||
/*!
|
/*!
|
||||||
\param string The string to convert
|
\param string The string to convert
|
||||||
\param size A size to trim the string to. Default is SIZE_MAX (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_view string, const size_t size = SIZE_MAX);
|
std::u16string ASCIIToUTF16(const std::string_view& string, size_t size = -1);
|
||||||
|
|
||||||
//! Converts a UTF-8 String to a UTF-16 string
|
//! Converts a UTF-8 String to a UTF-16 string
|
||||||
/*!
|
/*!
|
||||||
\param string The string to convert
|
\param string The string to convert
|
||||||
\param size A size to trim the string to. Default is SIZE_MAX (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 UTF8ToUTF16(const std::string_view string, const size_t size = SIZE_MAX);
|
std::u16string UTF8ToUTF16(const std::string_view& string, size_t size = -1);
|
||||||
|
|
||||||
namespace details {
|
//! Internal, do not use
|
||||||
//! Internal, do not use
|
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
|
||||||
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Converts a Latin1 string to a UTF-8 string
|
|
||||||
/*!
|
|
||||||
\param string The string to convert
|
|
||||||
\param size A size to trim the string to. Default is SIZE_MAX (No trimming)
|
|
||||||
\return An UTF-8 representation of the string
|
|
||||||
*/
|
|
||||||
std::string Latin1ToUTF8(const std::u8string_view string, const size_t size = SIZE_MAX);
|
|
||||||
|
|
||||||
//! Converts a UTF-16 string to a UTF-8 string
|
//! Converts a UTF-16 string to a UTF-8 string
|
||||||
/*!
|
/*!
|
||||||
\param string The string to convert
|
\param string The string to convert
|
||||||
\param size A size to trim the string to. Default is SIZE_MAX (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_view string, const size_t size = SIZE_MAX);
|
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
|
||||||
@@ -73,7 +62,7 @@ namespace GeneralUtils {
|
|||||||
* \param b the second string to compare against the first string
|
* \param b the second string to compare against the first string
|
||||||
* @return if the two strings are equal
|
* @return if the two strings are equal
|
||||||
*/
|
*/
|
||||||
bool CaseInsensitiveStringCompare(const std::string_view a, const std::string_view b);
|
bool CaseInsensitiveStringCompare(const std::string& a, const std::string& b);
|
||||||
|
|
||||||
// MARK: Bits
|
// MARK: Bits
|
||||||
|
|
||||||
@@ -81,9 +70,9 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
//! Sets a bit on a numerical value
|
//! Sets a bit on a numerical value
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void SetBit(T& value, const eObjectBits bits) {
|
inline void SetBit(T& value, eObjectBits bits) {
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
const auto index = static_cast<size_t>(bits);
|
auto index = static_cast<size_t>(bits);
|
||||||
if (index > (sizeof(T) * 8) - 1) {
|
if (index > (sizeof(T) * 8) - 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -93,9 +82,9 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
//! Clears a bit on a numerical value
|
//! Clears a bit on a numerical value
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void ClearBit(T& value, const eObjectBits bits) {
|
inline void ClearBit(T& value, eObjectBits bits) {
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
const auto index = static_cast<size_t>(bits);
|
auto index = static_cast<size_t>(bits);
|
||||||
if (index > (sizeof(T) * 8 - 1)) {
|
if (index > (sizeof(T) * 8 - 1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -108,14 +97,14 @@ namespace GeneralUtils {
|
|||||||
\param value The value to set the bit for
|
\param value The value to set the bit for
|
||||||
\param index The index of the bit
|
\param index The index of the bit
|
||||||
*/
|
*/
|
||||||
int64_t SetBit(int64_t value, const uint32_t index);
|
int64_t SetBit(int64_t value, uint32_t index);
|
||||||
|
|
||||||
//! Clears a specific bit in a signed 64-bit integer
|
//! Clears a specific bit in a signed 64-bit integer
|
||||||
/*!
|
/*!
|
||||||
\param value The value to clear the bit from
|
\param value The value to clear the bit from
|
||||||
\param index The index of the bit
|
\param index The index of the bit
|
||||||
*/
|
*/
|
||||||
int64_t ClearBit(int64_t value, const uint32_t index);
|
int64_t ClearBit(int64_t value, uint32_t index);
|
||||||
|
|
||||||
//! Checks a specific bit in a signed 64-bit integer
|
//! Checks a specific bit in a signed 64-bit integer
|
||||||
/*!
|
/*!
|
||||||
@@ -123,42 +112,19 @@ namespace GeneralUtils {
|
|||||||
\param index The index of the bit
|
\param index The index of the bit
|
||||||
\return Whether or not the bit is set
|
\return Whether or not the bit is set
|
||||||
*/
|
*/
|
||||||
bool CheckBit(int64_t value, const uint32_t index);
|
bool CheckBit(int64_t value, uint32_t index);
|
||||||
|
|
||||||
bool ReplaceInString(std::string& str, const std::string_view from, const std::string_view 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(const std::wstring_view str, const wchar_t delimiter);
|
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
|
||||||
|
|
||||||
std::vector<std::u16string> SplitString(const std::u16string_view str, const char16_t delimiter);
|
std::vector<std::u16string> SplitString(const std::u16string& str, char16_t delimiter);
|
||||||
|
|
||||||
std::vector<std::string> SplitString(const std::string_view str, const char delimiter);
|
std::vector<std::string> SplitString(const std::string& str, char delimiter);
|
||||||
|
|
||||||
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string_view folder);
|
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
|
||||||
|
|
||||||
/**
|
|
||||||
* Transparent string hasher - used to allow string_view key lookups for maps storing std::string keys
|
|
||||||
* https://www.reddit.com/r/cpp_questions/comments/12xw3sn/find_stdstring_view_in_unordered_map_with/jhki225/
|
|
||||||
* https://godbolt.org/z/789xv8Eeq
|
|
||||||
*/
|
|
||||||
template <typename... Bases>
|
|
||||||
struct overload : Bases... {
|
|
||||||
using is_transparent = void;
|
|
||||||
using Bases::operator() ... ;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct char_pointer_hash {
|
|
||||||
auto operator()(const char* const ptr) const noexcept {
|
|
||||||
return std::hash<std::string_view>{}(ptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using transparent_string_hash = overload<
|
|
||||||
std::hash<std::string>,
|
|
||||||
std::hash<std::string_view>,
|
|
||||||
char_pointer_hash
|
|
||||||
>;
|
|
||||||
|
|
||||||
// Concept constraining to enum types
|
// Concept constraining to enum types
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -178,7 +144,7 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
// If a boolean, present an alias to an intermediate integral type for parsing
|
// If a boolean, present an alias to an intermediate integral type for parsing
|
||||||
template <Numeric T> requires std::same_as<T, bool>
|
template <Numeric T> requires std::same_as<T, bool>
|
||||||
struct numeric_parse<T> { using type = uint8_t; };
|
struct numeric_parse<T> { using type = uint32_t; };
|
||||||
|
|
||||||
// Shorthand type alias
|
// Shorthand type alias
|
||||||
template <Numeric T>
|
template <Numeric T>
|
||||||
@@ -190,9 +156,8 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired value if it is equivalent to the string
|
* @returns An std::optional containing the desired value if it is equivalent to the string
|
||||||
*/
|
*/
|
||||||
template <Numeric T>
|
template <Numeric T>
|
||||||
[[nodiscard]] std::optional<T> TryParse(std::string_view str) {
|
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) {
|
||||||
numeric_parse_t<T> result;
|
numeric_parse_t<T> result;
|
||||||
while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1);
|
|
||||||
|
|
||||||
const char* const strEnd = str.data() + str.size();
|
const char* const strEnd = str.data() + str.size();
|
||||||
const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
|
const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
|
||||||
@@ -201,7 +166,7 @@ namespace GeneralUtils {
|
|||||||
return isParsed ? static_cast<T>(result) : std::optional<T>{};
|
return isParsed ? static_cast<T>(result) : std::optional<T>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
|
#ifdef DARKFLAME_PLATFORM_MACOS
|
||||||
|
|
||||||
// MacOS floating-point parse helper function specializations
|
// MacOS floating-point parse helper function specializations
|
||||||
namespace details {
|
namespace details {
|
||||||
@@ -216,10 +181,8 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired value if it is equivalent to the string
|
* @returns An std::optional containing the desired value if it is equivalent to the string
|
||||||
*/
|
*/
|
||||||
template <std::floating_point T>
|
template <std::floating_point T>
|
||||||
[[nodiscard]] std::optional<T> TryParse(std::string_view str) noexcept
|
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept
|
||||||
try {
|
try {
|
||||||
while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1);
|
|
||||||
|
|
||||||
size_t parseNum;
|
size_t parseNum;
|
||||||
const T result = details::_parse<T>(str, parseNum);
|
const T result = details::_parse<T>(str, parseNum);
|
||||||
const bool isParsed = str.length() == parseNum;
|
const bool isParsed = str.length() == parseNum;
|
||||||
@@ -239,7 +202,7 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
|
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string& strX, const std::string& strY, const std::string& strZ) {
|
||||||
const auto x = TryParse<float>(strX);
|
const auto x = TryParse<float>(strX);
|
||||||
if (!x) return std::nullopt;
|
if (!x) return std::nullopt;
|
||||||
|
|
||||||
@@ -251,17 +214,17 @@ namespace GeneralUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TryParse overload for handling NiPoint3 by passing a span of three strings
|
* The TryParse overload for handling NiPoint3 by passingn a reference to a vector of three strings
|
||||||
* @param str The string vector representing the X, Y, and Z coordinates
|
* @param str The string vector representing the X, Y, and Xcoordinates
|
||||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::span<const std::string> str) {
|
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::vector<std::string>& str) {
|
||||||
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
|
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::u16string to_u16string(const T value) {
|
std::u16string to_u16string(T value) {
|
||||||
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +243,7 @@ namespace GeneralUtils {
|
|||||||
\param max The maximum to generate to
|
\param max The maximum to generate to
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T GenerateRandomNumber(const std::size_t min, const std::size_t max) {
|
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
||||||
// Make sure it is a numeric type
|
// Make sure it is a numeric type
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
|
|
||||||
@@ -307,10 +270,10 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
// on Windows we need to undef these or else they conflict with our numeric limits calls
|
// on Windows we need to undef these or else they conflict with our numeric limits calls
|
||||||
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
|
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T GenerateRandomNumber() {
|
inline T GenerateRandomNumber() {
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
#ifndef __IMPLEMENTATION_H__
|
|
||||||
#define __IMPLEMENTATION_H__
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A way to defer the implementation of an action.
|
|
||||||
*
|
|
||||||
* @tparam R The result of the action.
|
|
||||||
* @tparam T The types of the arguments that the implementation requires.
|
|
||||||
*/
|
|
||||||
template <typename R, typename... T>
|
|
||||||
class Implementation {
|
|
||||||
public:
|
|
||||||
typedef std::function<std::optional<R>(T...)> ImplementationFunction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets the implementation of the action.
|
|
||||||
*
|
|
||||||
* @param implementation The implementation of the action.
|
|
||||||
*/
|
|
||||||
void SetImplementation(const ImplementationFunction& implementation) {
|
|
||||||
this->implementation = implementation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clears the implementation of the action.
|
|
||||||
*/
|
|
||||||
void ClearImplementation() {
|
|
||||||
implementation.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if the implementation is set.
|
|
||||||
*
|
|
||||||
* @return true If the implementation is set.
|
|
||||||
* @return false If the implementation is not set.
|
|
||||||
*/
|
|
||||||
bool IsSet() const {
|
|
||||||
return implementation.has_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Executes the implementation if it is set.
|
|
||||||
*
|
|
||||||
* @param args The arguments to pass to the implementation.
|
|
||||||
* @return std::optional<R> The optional result of the implementation. If the result is not set, it indicates that the default action should be taken.
|
|
||||||
*/
|
|
||||||
std::optional<R> Execute(T... args) const {
|
|
||||||
return IsSet() ? implementation.value()(args...) : std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Exectues the implementation if it is set, otherwise returns a default value.
|
|
||||||
*
|
|
||||||
* @param args The arguments to pass to the implementation.
|
|
||||||
* @param defaultValue The default value to return if the implementation is not set or should not be deferred.
|
|
||||||
*/
|
|
||||||
R ExecuteWithDefault(T... args, const R& defaultValue) const {
|
|
||||||
return Execute(args...).value_or(defaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* = operator overload.
|
|
||||||
*/
|
|
||||||
Implementation& operator=(const Implementation& other) {
|
|
||||||
implementation = other.implementation;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* = operator overload.
|
|
||||||
*/
|
|
||||||
Implementation& operator=(const ImplementationFunction& implementation) {
|
|
||||||
this->implementation = implementation;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* () operator overload.
|
|
||||||
*/
|
|
||||||
std::optional<R> operator()(T... args) {
|
|
||||||
return !IsSet() ? std::nullopt : implementation(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::optional<ImplementationFunction> implementation;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__IMPLEMENTATION_H__
|
|
||||||
@@ -31,22 +31,22 @@ public:
|
|||||||
|
|
||||||
virtual ~LDFBaseData() {}
|
virtual ~LDFBaseData() {}
|
||||||
|
|
||||||
virtual void WriteToPacket(RakNet::BitStream& packet) const = 0;
|
virtual void WriteToPacket(RakNet::BitStream& packet) = 0;
|
||||||
|
|
||||||
virtual const std::u16string& GetKey() const = 0;
|
virtual const std::u16string& GetKey() = 0;
|
||||||
|
|
||||||
virtual eLDFType GetValueType() const = 0;
|
virtual eLDFType GetValueType() = 0;
|
||||||
|
|
||||||
/** Gets a string from the key/value pair
|
/** Gets a string from the key/value pair
|
||||||
* @param includeKey Whether or not to include the key in the data
|
* @param includeKey Whether or not to include the key in the data
|
||||||
* @param includeTypeId Whether or not to include the type id in the data
|
* @param includeTypeId Whether or not to include the type id in the data
|
||||||
* @return The string representation of the data
|
* @return The string representation of the data
|
||||||
*/
|
*/
|
||||||
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) const = 0;
|
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0;
|
||||||
|
|
||||||
virtual std::string GetValueAsString() const = 0;
|
virtual std::string GetValueAsString() = 0;
|
||||||
|
|
||||||
virtual LDFBaseData* Copy() const = 0;
|
virtual LDFBaseData* Copy() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an input string, return the data as a LDF key.
|
* Given an input string, return the data as a LDF key.
|
||||||
@@ -62,7 +62,7 @@ private:
|
|||||||
T value;
|
T value;
|
||||||
|
|
||||||
//! Writes the key to the packet
|
//! Writes the key to the packet
|
||||||
void WriteKey(RakNet::BitStream& packet) const {
|
void WriteKey(RakNet::BitStream& packet) {
|
||||||
packet.Write<uint8_t>(this->key.length() * sizeof(uint16_t));
|
packet.Write<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<uint16_t>(this->key[i]);
|
packet.Write<uint16_t>(this->key[i]);
|
||||||
@@ -70,7 +70,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Writes the value to the packet
|
//! Writes the value to the packet
|
||||||
void WriteValue(RakNet::BitStream& packet) const {
|
void WriteValue(RakNet::BitStream& packet) {
|
||||||
packet.Write<uint8_t>(this->GetValueType());
|
packet.Write<uint8_t>(this->GetValueType());
|
||||||
packet.Write(this->value);
|
packet.Write(this->value);
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\return The value
|
\return The value
|
||||||
*/
|
*/
|
||||||
const T& GetValue(void) const { return this->value; }
|
const T& GetValue(void) { return this->value; }
|
||||||
|
|
||||||
//! Sets the value
|
//! Sets the value
|
||||||
/*!
|
/*!
|
||||||
@@ -102,13 +102,13 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\return The value string
|
\return The value string
|
||||||
*/
|
*/
|
||||||
std::string GetValueString(void) const { return ""; }
|
std::string GetValueString(void) { return ""; }
|
||||||
|
|
||||||
//! Writes the data to a packet
|
//! Writes the data to a packet
|
||||||
/*!
|
/*!
|
||||||
\param packet The packet
|
\param packet The packet
|
||||||
*/
|
*/
|
||||||
void WriteToPacket(RakNet::BitStream& packet) const override {
|
void WriteToPacket(RakNet::BitStream& packet) override {
|
||||||
this->WriteKey(packet);
|
this->WriteKey(packet);
|
||||||
this->WriteValue(packet);
|
this->WriteValue(packet);
|
||||||
}
|
}
|
||||||
@@ -117,13 +117,13 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\return The key
|
\return The key
|
||||||
*/
|
*/
|
||||||
const std::u16string& GetKey(void) const override { return this->key; }
|
const std::u16string& GetKey(void) override { return this->key; }
|
||||||
|
|
||||||
//! Gets the LDF Type
|
//! Gets the LDF Type
|
||||||
/*!
|
/*!
|
||||||
\return The LDF value type
|
\return The LDF value type
|
||||||
*/
|
*/
|
||||||
eLDFType GetValueType(void) const override { return LDF_TYPE_UNKNOWN; }
|
eLDFType GetValueType(void) override { return LDF_TYPE_UNKNOWN; }
|
||||||
|
|
||||||
//! Gets the string data
|
//! Gets the string data
|
||||||
/*!
|
/*!
|
||||||
@@ -131,7 +131,7 @@ public:
|
|||||||
\param includeTypeId Whether or not to include the type id in the data
|
\param includeTypeId Whether or not to include the type id in the data
|
||||||
\return The string representation of the data
|
\return The string representation of the data
|
||||||
*/
|
*/
|
||||||
std::string GetString(const bool includeKey = true, const bool includeTypeId = true) const override {
|
std::string GetString(const bool includeKey = true, const bool includeTypeId = true) override {
|
||||||
if (GetValueType() == -1) {
|
if (GetValueType() == -1) {
|
||||||
return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>";
|
return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>";
|
||||||
}
|
}
|
||||||
@@ -154,11 +154,11 @@ public:
|
|||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetValueAsString() const override {
|
std::string GetValueAsString() override {
|
||||||
return this->GetValueString();
|
return this->GetValueString();
|
||||||
}
|
}
|
||||||
|
|
||||||
LDFBaseData* Copy() const override {
|
LDFBaseData* Copy() override {
|
||||||
return new LDFData<T>(key, value);
|
return new LDFData<T>(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,19 +166,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// LDF Types
|
// LDF Types
|
||||||
template<> inline eLDFType LDFData<std::u16string>::GetValueType(void) const { return LDF_TYPE_UTF_16; };
|
template<> inline eLDFType LDFData<std::u16string>::GetValueType(void) { return LDF_TYPE_UTF_16; };
|
||||||
template<> inline eLDFType LDFData<int32_t>::GetValueType(void) const { return LDF_TYPE_S32; };
|
template<> inline eLDFType LDFData<int32_t>::GetValueType(void) { return LDF_TYPE_S32; };
|
||||||
template<> inline eLDFType LDFData<float>::GetValueType(void) const { return LDF_TYPE_FLOAT; };
|
template<> inline eLDFType LDFData<float>::GetValueType(void) { return LDF_TYPE_FLOAT; };
|
||||||
template<> inline eLDFType LDFData<double>::GetValueType(void) const { return LDF_TYPE_DOUBLE; };
|
template<> inline eLDFType LDFData<double>::GetValueType(void) { return LDF_TYPE_DOUBLE; };
|
||||||
template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) const { return LDF_TYPE_U32; };
|
template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) { return LDF_TYPE_U32; };
|
||||||
template<> inline eLDFType LDFData<bool>::GetValueType(void) const { return LDF_TYPE_BOOLEAN; };
|
template<> inline eLDFType LDFData<bool>::GetValueType(void) { return LDF_TYPE_BOOLEAN; };
|
||||||
template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) const { return LDF_TYPE_U64; };
|
template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) { return LDF_TYPE_U64; };
|
||||||
template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) const { return LDF_TYPE_OBJID; };
|
template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) { return LDF_TYPE_OBJID; };
|
||||||
template<> inline eLDFType LDFData<std::string>::GetValueType(void) const { return LDF_TYPE_UTF_8; };
|
template<> inline eLDFType LDFData<std::string>::GetValueType(void) { return LDF_TYPE_UTF_8; };
|
||||||
|
|
||||||
// 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) const {
|
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) {
|
||||||
packet.Write<uint8_t>(this->GetValueType());
|
packet.Write<uint8_t>(this->GetValueType());
|
||||||
|
|
||||||
packet.Write<uint32_t>(this->value.length());
|
packet.Write<uint32_t>(this->value.length());
|
||||||
@@ -189,7 +189,7 @@ inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) const
|
|||||||
|
|
||||||
// The specialized version for bool
|
// The specialized version for bool
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) const {
|
inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) {
|
||||||
packet.Write<uint8_t>(this->GetValueType());
|
packet.Write<uint8_t>(this->GetValueType());
|
||||||
|
|
||||||
packet.Write<uint8_t>(this->value);
|
packet.Write<uint8_t>(this->value);
|
||||||
@@ -197,7 +197,7 @@ inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) const {
|
|||||||
|
|
||||||
// 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) const {
|
inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) {
|
||||||
packet.Write<uint8_t>(this->GetValueType());
|
packet.Write<uint8_t>(this->GetValueType());
|
||||||
|
|
||||||
packet.Write<uint32_t>(this->value.length());
|
packet.Write<uint32_t>(this->value.length());
|
||||||
@@ -206,18 +206,18 @@ inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline std::string LDFData<std::u16string>::GetValueString() const {
|
template<> inline std::string LDFData<std::u16string>::GetValueString() {
|
||||||
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline std::string LDFData<int32_t>::GetValueString() const { return std::to_string(this->value); }
|
template<> inline std::string LDFData<int32_t>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<float>::GetValueString() const { return std::to_string(this->value); }
|
template<> inline std::string LDFData<float>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<double>::GetValueString() const { return std::to_string(this->value); }
|
template<> inline std::string LDFData<double>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<uint32_t>::GetValueString() const { return std::to_string(this->value); }
|
template<> inline std::string LDFData<uint32_t>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<bool>::GetValueString() const { return std::to_string(this->value); }
|
template<> inline std::string LDFData<bool>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<uint64_t>::GetValueString() const { return std::to_string(this->value); }
|
template<> inline std::string LDFData<uint64_t>::GetValueString() { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<LWOOBJID>::GetValueString() const { return std::to_string(this->value); }
|
template<> inline std::string LDFData<LWOOBJID>::GetValueString() { return std::to_string(this->value); }
|
||||||
|
|
||||||
template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; }
|
template<> inline std::string LDFData<std::string>::GetValueString() { return this->value; }
|
||||||
|
|
||||||
#endif //!__LDFFORMAT__H__
|
#endif //!__LDFFORMAT__H__
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
#ifndef __OBSERVABLE_H__
|
|
||||||
#define __OBSERVABLE_H__
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief An event which can be observed by multiple observers.
|
|
||||||
*
|
|
||||||
* @tparam T The types of the arguments to be passed to the observers.
|
|
||||||
*/
|
|
||||||
template <typename... T>
|
|
||||||
class Observable {
|
|
||||||
public:
|
|
||||||
typedef std::function<void(T...)> Observer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Adds an observer to the event.
|
|
||||||
*
|
|
||||||
* @param observer The observer to add.
|
|
||||||
*/
|
|
||||||
void AddObserver(const Observer& observer) {
|
|
||||||
observers.push_back(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Removes an observer from the event.
|
|
||||||
*
|
|
||||||
* @param observer The observer to remove.
|
|
||||||
*/
|
|
||||||
void RemoveObserver(const Observer& observer) {
|
|
||||||
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Notifies all observers of the event.
|
|
||||||
*
|
|
||||||
* @param args The arguments to pass to the observers.
|
|
||||||
*/
|
|
||||||
void Notify(T... args) {
|
|
||||||
for (const auto& observer : observers) {
|
|
||||||
observer(args...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* += operator overload.
|
|
||||||
*/
|
|
||||||
Observable& operator+=(const Observer& observer) {
|
|
||||||
AddObserver(observer);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -= operator overload.
|
|
||||||
*/
|
|
||||||
Observable& operator-=(const Observer& observer) {
|
|
||||||
RemoveObserver(observer);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* () operator overload.
|
|
||||||
*/
|
|
||||||
void operator()(T... args) {
|
|
||||||
Notify(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<Observer> observers;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__OBSERVABLE_H__
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "BinaryPathFinder.h"
|
#include "BinaryPathFinder.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace MessageType {
|
|
||||||
enum class Auth : uint32_t {
|
|
||||||
LOGIN_REQUEST = 0,
|
|
||||||
LOGOUT_REQUEST,
|
|
||||||
CREATE_NEW_ACCOUNT_REQUEST,
|
|
||||||
LEGOINTERFACE_AUTH_RESPONSE,
|
|
||||||
SESSIONKEY_RECEIVED_CONFIRM,
|
|
||||||
RUNTIME_CONFIG
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace MessageType {
|
|
||||||
//! The Internal Chat Packet Identifiers
|
|
||||||
enum class Chat : uint32_t {
|
|
||||||
LOGIN_SESSION_NOTIFY = 0,
|
|
||||||
GENERAL_CHAT_MESSAGE,
|
|
||||||
PRIVATE_CHAT_MESSAGE,
|
|
||||||
USER_CHANNEL_CHAT_MESSAGE,
|
|
||||||
WORLD_DISCONNECT_REQUEST,
|
|
||||||
WORLD_PROXIMITY_RESPONSE,
|
|
||||||
WORLD_PARCEL_RESPONSE,
|
|
||||||
ADD_FRIEND_REQUEST,
|
|
||||||
ADD_FRIEND_RESPONSE,
|
|
||||||
REMOVE_FRIEND,
|
|
||||||
GET_FRIENDS_LIST,
|
|
||||||
ADD_IGNORE,
|
|
||||||
REMOVE_IGNORE,
|
|
||||||
GET_IGNORE_LIST,
|
|
||||||
TEAM_MISSED_INVITE_CHECK,
|
|
||||||
TEAM_INVITE,
|
|
||||||
TEAM_INVITE_RESPONSE,
|
|
||||||
TEAM_KICK,
|
|
||||||
TEAM_LEAVE,
|
|
||||||
TEAM_SET_LOOT,
|
|
||||||
TEAM_SET_LEADER,
|
|
||||||
TEAM_GET_STATUS,
|
|
||||||
GUILD_CREATE,
|
|
||||||
GUILD_INVITE,
|
|
||||||
GUILD_INVITE_RESPONSE,
|
|
||||||
GUILD_LEAVE,
|
|
||||||
GUILD_KICK,
|
|
||||||
GUILD_GET_STATUS,
|
|
||||||
GUILD_GET_ALL,
|
|
||||||
SHOW_ALL,
|
|
||||||
BLUEPRINT_MODERATED,
|
|
||||||
BLUEPRINT_MODEL_READY,
|
|
||||||
PROPERTY_READY_FOR_APPROVAL,
|
|
||||||
PROPERTY_MODERATION_CHANGED,
|
|
||||||
PROPERTY_BUILDMODE_CHANGED,
|
|
||||||
PROPERTY_BUILDMODE_CHANGED_REPORT,
|
|
||||||
MAIL,
|
|
||||||
WORLD_INSTANCE_LOCATION_REQUEST,
|
|
||||||
REPUTATION_UPDATE,
|
|
||||||
SEND_CANNED_TEXT,
|
|
||||||
GMLEVEL_UPDATE,
|
|
||||||
CHARACTER_NAME_CHANGE_REQUEST,
|
|
||||||
CSR_REQUEST,
|
|
||||||
CSR_REPLY,
|
|
||||||
GM_KICK,
|
|
||||||
GM_ANNOUNCE,
|
|
||||||
GM_MUTE,
|
|
||||||
ACTIVITY_UPDATE,
|
|
||||||
WORLD_ROUTE_PACKET,
|
|
||||||
GET_ZONE_POPULATIONS,
|
|
||||||
REQUEST_MINIMUM_CHAT_MODE,
|
|
||||||
REQUEST_MINIMUM_CHAT_MODE_PRIVATE,
|
|
||||||
MATCH_REQUEST,
|
|
||||||
UGCMANIFEST_REPORT_MISSING_FILE,
|
|
||||||
UGCMANIFEST_REPORT_DONE_FILE,
|
|
||||||
UGCMANIFEST_REPORT_DONE_BLUEPRINT,
|
|
||||||
UGCC_REQUEST,
|
|
||||||
WHO,
|
|
||||||
WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE,
|
|
||||||
ACHIEVEMENT_NOTIFY,
|
|
||||||
GM_CLOSE_PRIVATE_CHAT_WINDOW,
|
|
||||||
UNEXPECTED_DISCONNECT,
|
|
||||||
PLAYER_READY,
|
|
||||||
GET_DONATION_TOTAL,
|
|
||||||
UPDATE_DONATION,
|
|
||||||
PRG_CSR_COMMAND,
|
|
||||||
HEARTBEAT_REQUEST_FROM_WORLD,
|
|
||||||
UPDATE_FREE_TRIAL_STATUS,
|
|
||||||
// CUSTOM DLU MESSAGE ID FOR INTERNAL USE
|
|
||||||
CREATE_TEAM,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace MessageType {
|
|
||||||
enum class Client : uint32_t {
|
|
||||||
LOGIN_RESPONSE = 0,
|
|
||||||
LOGOUT_RESPONSE,
|
|
||||||
LOAD_STATIC_ZONE,
|
|
||||||
CREATE_OBJECT,
|
|
||||||
CREATE_CHARACTER,
|
|
||||||
CREATE_CHARACTER_EXTENDED,
|
|
||||||
CHARACTER_LIST_RESPONSE,
|
|
||||||
CHARACTER_CREATE_RESPONSE,
|
|
||||||
CHARACTER_RENAME_RESPONSE,
|
|
||||||
CHAT_CONNECT_RESPONSE,
|
|
||||||
AUTH_ACCOUNT_CREATE_RESPONSE,
|
|
||||||
DELETE_CHARACTER_RESPONSE,
|
|
||||||
GAME_MSG,
|
|
||||||
CONNECT_CHAT,
|
|
||||||
TRANSFER_TO_WORLD,
|
|
||||||
IMPENDING_RELOAD_NOTIFY,
|
|
||||||
MAKE_GM_RESPONSE,
|
|
||||||
HTTP_MONITOR_INFO_RESPONSE,
|
|
||||||
SLASH_PUSH_MAP_RESPONSE,
|
|
||||||
SLASH_PULL_MAP_RESPONSE,
|
|
||||||
SLASH_LOCK_MAP_RESPONSE,
|
|
||||||
BLUEPRINT_SAVE_RESPONSE,
|
|
||||||
BLUEPRINT_LUP_SAVE_RESPONSE,
|
|
||||||
BLUEPRINT_LOAD_RESPONSE_ITEMID,
|
|
||||||
BLUEPRINT_GET_ALL_DATA_RESPONSE,
|
|
||||||
MODEL_INSTANTIATE_RESPONSE,
|
|
||||||
DEBUG_OUTPUT,
|
|
||||||
ADD_FRIEND_REQUEST,
|
|
||||||
ADD_FRIEND_RESPONSE,
|
|
||||||
REMOVE_FRIEND_RESPONSE,
|
|
||||||
GET_FRIENDS_LIST_RESPONSE,
|
|
||||||
UPDATE_FRIEND_NOTIFY,
|
|
||||||
ADD_IGNORE_RESPONSE,
|
|
||||||
REMOVE_IGNORE_RESPONSE,
|
|
||||||
GET_IGNORE_LIST_RESPONSE,
|
|
||||||
TEAM_INVITE,
|
|
||||||
TEAM_INVITE_INITIAL_RESPONSE,
|
|
||||||
GUILD_CREATE_RESPONSE,
|
|
||||||
GUILD_GET_STATUS_RESPONSE,
|
|
||||||
GUILD_INVITE,
|
|
||||||
GUILD_INVITE_INITIAL_RESPONSE,
|
|
||||||
GUILD_INVITE_FINAL_RESPONSE,
|
|
||||||
GUILD_INVITE_CONFIRM,
|
|
||||||
GUILD_ADD_PLAYER,
|
|
||||||
GUILD_REMOVE_PLAYER,
|
|
||||||
GUILD_LOGIN_LOGOUT,
|
|
||||||
GUILD_RANK_CHANGE,
|
|
||||||
GUILD_DATA,
|
|
||||||
GUILD_STATUS,
|
|
||||||
MAIL,
|
|
||||||
DB_PROXY_RESULT,
|
|
||||||
SHOW_ALL_RESPONSE,
|
|
||||||
WHO_RESPONSE,
|
|
||||||
SEND_CANNED_TEXT,
|
|
||||||
UPDATE_CHARACTER_NAME,
|
|
||||||
SET_NETWORK_SIMULATOR,
|
|
||||||
INVALID_CHAT_MESSAGE,
|
|
||||||
MINIMUM_CHAT_MODE_RESPONSE,
|
|
||||||
MINIMUM_CHAT_MODE_RESPONSE_PRIVATE,
|
|
||||||
CHAT_MODERATION_STRING,
|
|
||||||
UGC_MANIFEST_RESPONSE,
|
|
||||||
IN_LOGIN_QUEUE,
|
|
||||||
SERVER_STATES,
|
|
||||||
GM_CLOSE_TARGET_CHAT_WINDOW,
|
|
||||||
GENERAL_TEXT_FOR_LOCALIZATION,
|
|
||||||
UPDATE_FREE_TRIAL_STATUS,
|
|
||||||
UGC_DOWNLOAD_FAILED = 120
|
|
||||||
};
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace MessageType {
|
|
||||||
enum class Master : uint32_t {
|
|
||||||
REQUEST_PERSISTENT_ID = 1,
|
|
||||||
REQUEST_PERSISTENT_ID_RESPONSE,
|
|
||||||
REQUEST_ZONE_TRANSFER,
|
|
||||||
REQUEST_ZONE_TRANSFER_RESPONSE,
|
|
||||||
SERVER_INFO,
|
|
||||||
REQUEST_SESSION_KEY,
|
|
||||||
SET_SESSION_KEY,
|
|
||||||
SESSION_KEY_RESPONSE,
|
|
||||||
PLAYER_ADDED,
|
|
||||||
PLAYER_REMOVED,
|
|
||||||
|
|
||||||
CREATE_PRIVATE_ZONE,
|
|
||||||
REQUEST_PRIVATE_ZONE,
|
|
||||||
|
|
||||||
WORLD_READY,
|
|
||||||
PREP_ZONE,
|
|
||||||
|
|
||||||
SHUTDOWN,
|
|
||||||
SHUTDOWN_RESPONSE,
|
|
||||||
SHUTDOWN_IMMEDIATE,
|
|
||||||
|
|
||||||
SHUTDOWN_UNIVERSE,
|
|
||||||
|
|
||||||
AFFIRM_TRANSFER_REQUEST,
|
|
||||||
AFFIRM_TRANSFER_RESPONSE,
|
|
||||||
|
|
||||||
NEW_SESSION_ALERT
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace MessageType {
|
|
||||||
//! The Internal Server Packet Identifiers
|
|
||||||
enum class Server : uint32_t {
|
|
||||||
VERSION_CONFIRM = 0,
|
|
||||||
DISCONNECT_NOTIFY,
|
|
||||||
GENERAL_NOTIFY
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include "magic_enum.hpp"
|
|
||||||
|
|
||||||
namespace MessageType {
|
|
||||||
enum class World : uint32_t {
|
|
||||||
VALIDATION = 1, // Session info
|
|
||||||
CHARACTER_LIST_REQUEST,
|
|
||||||
CHARACTER_CREATE_REQUEST,
|
|
||||||
LOGIN_REQUEST, // Character selected
|
|
||||||
GAME_MSG,
|
|
||||||
CHARACTER_DELETE_REQUEST,
|
|
||||||
CHARACTER_RENAME_REQUEST,
|
|
||||||
HAPPY_FLOWER_MODE_NOTIFY,
|
|
||||||
SLASH_RELOAD_MAP, // Reload map cmp
|
|
||||||
SLASH_PUSH_MAP_REQUEST, // Push map req cmd
|
|
||||||
SLASH_PUSH_MAP, // Push map cmd
|
|
||||||
SLASH_PULL_MAP, // Pull map cmd
|
|
||||||
LOCK_MAP_REQUEST,
|
|
||||||
GENERAL_CHAT_MESSAGE, // General chat message
|
|
||||||
HTTP_MONITOR_INFO_REQUEST,
|
|
||||||
SLASH_DEBUG_SCRIPTS, // Debug scripts cmd
|
|
||||||
MODELS_CLEAR,
|
|
||||||
EXHIBIT_INSERT_MODEL,
|
|
||||||
LEVEL_LOAD_COMPLETE, // Character data request
|
|
||||||
TMP_GUILD_CREATE,
|
|
||||||
ROUTE_PACKET, // Social?
|
|
||||||
POSITION_UPDATE,
|
|
||||||
MAIL,
|
|
||||||
WORD_CHECK, // AllowList word check
|
|
||||||
STRING_CHECK, // AllowList string check
|
|
||||||
GET_PLAYERS_IN_ZONE,
|
|
||||||
REQUEST_UGC_MANIFEST_INFO,
|
|
||||||
BLUEPRINT_GET_ALL_DATA_REQUEST,
|
|
||||||
CANCEL_MAP_QUEUE,
|
|
||||||
HANDLE_FUNNESS,
|
|
||||||
FAKE_PRG_CSR_MESSAGE,
|
|
||||||
REQUEST_FREE_TRIAL_REFRESH,
|
|
||||||
GM_SET_FREE_TRIAL_STATUS,
|
|
||||||
UI_HELP_TOP_5 = 91
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct magic_enum::customize::enum_range<MessageType::World> {
|
|
||||||
static constexpr int min = 0;
|
|
||||||
static constexpr int max = 91;
|
|
||||||
};
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "MessageType/Client.h"
|
#include "eClientMessageType.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
|
|
||||||
#pragma warning (disable:4251) //Disables SQL warnings
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
@@ -33,7 +33,7 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
|
|||||||
#define CBITSTREAM RakNet::BitStream bitStream;
|
#define CBITSTREAM RakNet::BitStream bitStream;
|
||||||
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
||||||
#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::GAME_MSG);
|
#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||||
#define SEND_PACKET Game::server->Send(bitStream, sysAddr, false);
|
#define SEND_PACKET Game::server->Send(bitStream, sysAddr, false);
|
||||||
#define SEND_PACKET_BROADCAST Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
#define SEND_PACKET_BROADCAST Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||||
|
|
||||||
|
|||||||
15
dCommon/dEnums/eAuthMessageType.h
Normal file
15
dCommon/dEnums/eAuthMessageType.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __EAUTHMESSAGETYPE__H__
|
||||||
|
#define __EAUTHMESSAGETYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum class eAuthMessageType : uint32_t {
|
||||||
|
LOGIN_REQUEST = 0,
|
||||||
|
LOGOUT_REQUEST,
|
||||||
|
CREATE_NEW_ACCOUNT_REQUEST,
|
||||||
|
LEGOINTERFACE_AUTH_RESPONSE,
|
||||||
|
SESSIONKEY_RECEIVED_CONFIRM,
|
||||||
|
RUNTIME_CONFIG
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__EAUTHMESSAGETYPE__H__
|
||||||
@@ -15,8 +15,7 @@ enum class eCharacterVersion : uint32_t {
|
|||||||
// Fixes vault size value
|
// Fixes vault size value
|
||||||
VAULT_SIZE,
|
VAULT_SIZE,
|
||||||
// Fixes speed base value in level component
|
// Fixes speed base value in level component
|
||||||
SPEED_BASE,
|
UP_TO_DATE, // will become SPEED_BASE
|
||||||
UP_TO_DATE, // will become NJ_JAYMISSIONS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ECHARACTERVERSION__H__
|
#endif //!__ECHARACTERVERSION__H__
|
||||||
|
|||||||
31
dCommon/dEnums/eChatInternalMessageType.h
Normal file
31
dCommon/dEnums/eChatInternalMessageType.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef __ECHATINTERNALMESSAGETYPE__H__
|
||||||
|
#define __ECHATINTERNALMESSAGETYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum eChatInternalMessageType : uint32_t {
|
||||||
|
PLAYER_ADDED_NOTIFICATION = 0,
|
||||||
|
PLAYER_REMOVED_NOTIFICATION,
|
||||||
|
ADD_FRIEND,
|
||||||
|
ADD_BEST_FRIEND,
|
||||||
|
ADD_TO_TEAM,
|
||||||
|
ADD_BLOCK,
|
||||||
|
REMOVE_FRIEND,
|
||||||
|
REMOVE_BLOCK,
|
||||||
|
REMOVE_FROM_TEAM,
|
||||||
|
DELETE_TEAM,
|
||||||
|
REPORT,
|
||||||
|
PRIVATE_CHAT,
|
||||||
|
PRIVATE_CHAT_RESPONSE,
|
||||||
|
ANNOUNCEMENT,
|
||||||
|
MAIL_COUNT_UPDATE,
|
||||||
|
MAIL_SEND_NOTIFY,
|
||||||
|
REQUEST_USER_LIST,
|
||||||
|
FRIEND_LIST,
|
||||||
|
ROUTE_TO_PLAYER,
|
||||||
|
TEAM_UPDATE,
|
||||||
|
MUTE_UPDATE,
|
||||||
|
CREATE_TEAM,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__ECHATINTERNALMESSAGETYPE__H__
|
||||||
78
dCommon/dEnums/eChatMessageType.h
Normal file
78
dCommon/dEnums/eChatMessageType.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#ifndef __ECHATMESSAGETYPE__H__
|
||||||
|
#define __ECHATMESSAGETYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
//! The Internal Chat Packet Identifiers
|
||||||
|
enum class eChatMessageType :uint32_t {
|
||||||
|
LOGIN_SESSION_NOTIFY = 0,
|
||||||
|
GENERAL_CHAT_MESSAGE,
|
||||||
|
PRIVATE_CHAT_MESSAGE,
|
||||||
|
USER_CHANNEL_CHAT_MESSAGE,
|
||||||
|
WORLD_DISCONNECT_REQUEST,
|
||||||
|
WORLD_PROXIMITY_RESPONSE,
|
||||||
|
WORLD_PARCEL_RESPONSE,
|
||||||
|
ADD_FRIEND_REQUEST,
|
||||||
|
ADD_FRIEND_RESPONSE,
|
||||||
|
REMOVE_FRIEND,
|
||||||
|
GET_FRIENDS_LIST,
|
||||||
|
ADD_IGNORE,
|
||||||
|
REMOVE_IGNORE,
|
||||||
|
GET_IGNORE_LIST,
|
||||||
|
TEAM_MISSED_INVITE_CHECK,
|
||||||
|
TEAM_INVITE,
|
||||||
|
TEAM_INVITE_RESPONSE,
|
||||||
|
TEAM_KICK,
|
||||||
|
TEAM_LEAVE,
|
||||||
|
TEAM_SET_LOOT,
|
||||||
|
TEAM_SET_LEADER,
|
||||||
|
TEAM_GET_STATUS,
|
||||||
|
GUILD_CREATE,
|
||||||
|
GUILD_INVITE,
|
||||||
|
GUILD_INVITE_RESPONSE,
|
||||||
|
GUILD_LEAVE,
|
||||||
|
GUILD_KICK,
|
||||||
|
GUILD_GET_STATUS,
|
||||||
|
GUILD_GET_ALL,
|
||||||
|
SHOW_ALL,
|
||||||
|
BLUEPRINT_MODERATED,
|
||||||
|
BLUEPRINT_MODEL_READY,
|
||||||
|
PROPERTY_READY_FOR_APPROVAL,
|
||||||
|
PROPERTY_MODERATION_CHANGED,
|
||||||
|
PROPERTY_BUILDMODE_CHANGED,
|
||||||
|
PROPERTY_BUILDMODE_CHANGED_REPORT,
|
||||||
|
MAIL,
|
||||||
|
WORLD_INSTANCE_LOCATION_REQUEST,
|
||||||
|
REPUTATION_UPDATE,
|
||||||
|
SEND_CANNED_TEXT,
|
||||||
|
GMLEVEL_UPDATE,
|
||||||
|
CHARACTER_NAME_CHANGE_REQUEST,
|
||||||
|
CSR_REQUEST,
|
||||||
|
CSR_REPLY,
|
||||||
|
GM_KICK,
|
||||||
|
GM_ANNOUNCE,
|
||||||
|
GM_MUTE,
|
||||||
|
ACTIVITY_UPDATE,
|
||||||
|
WORLD_ROUTE_PACKET,
|
||||||
|
GET_ZONE_POPULATIONS,
|
||||||
|
REQUEST_MINIMUM_CHAT_MODE,
|
||||||
|
REQUEST_MINIMUM_CHAT_MODE_PRIVATE,
|
||||||
|
MATCH_REQUEST,
|
||||||
|
UGCMANIFEST_REPORT_MISSING_FILE,
|
||||||
|
UGCMANIFEST_REPORT_DONE_FILE,
|
||||||
|
UGCMANIFEST_REPORT_DONE_BLUEPRINT,
|
||||||
|
UGCC_REQUEST,
|
||||||
|
WHO,
|
||||||
|
WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE,
|
||||||
|
ACHIEVEMENT_NOTIFY,
|
||||||
|
GM_CLOSE_PRIVATE_CHAT_WINDOW,
|
||||||
|
UNEXPECTED_DISCONNECT,
|
||||||
|
PLAYER_READY,
|
||||||
|
GET_DONATION_TOTAL,
|
||||||
|
UPDATE_DONATION,
|
||||||
|
PRG_CSR_COMMAND,
|
||||||
|
HEARTBEAT_REQUEST_FROM_WORLD,
|
||||||
|
UPDATE_FREE_TRIAL_STATUS
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__ECHATMESSAGETYPE__H__
|
||||||
76
dCommon/dEnums/eClientMessageType.h
Normal file
76
dCommon/dEnums/eClientMessageType.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#ifndef __ECLIENTMESSAGETYPE__H__
|
||||||
|
#define __ECLIENTMESSAGETYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum class eClientMessageType : uint32_t {
|
||||||
|
LOGIN_RESPONSE = 0,
|
||||||
|
LOGOUT_RESPONSE,
|
||||||
|
LOAD_STATIC_ZONE,
|
||||||
|
CREATE_OBJECT,
|
||||||
|
CREATE_CHARACTER,
|
||||||
|
CREATE_CHARACTER_EXTENDED,
|
||||||
|
CHARACTER_LIST_RESPONSE,
|
||||||
|
CHARACTER_CREATE_RESPONSE,
|
||||||
|
CHARACTER_RENAME_RESPONSE,
|
||||||
|
CHAT_CONNECT_RESPONSE,
|
||||||
|
AUTH_ACCOUNT_CREATE_RESPONSE,
|
||||||
|
DELETE_CHARACTER_RESPONSE,
|
||||||
|
GAME_MSG,
|
||||||
|
CONNECT_CHAT,
|
||||||
|
TRANSFER_TO_WORLD,
|
||||||
|
IMPENDING_RELOAD_NOTIFY,
|
||||||
|
MAKE_GM_RESPONSE,
|
||||||
|
HTTP_MONITOR_INFO_RESPONSE,
|
||||||
|
SLASH_PUSH_MAP_RESPONSE,
|
||||||
|
SLASH_PULL_MAP_RESPONSE,
|
||||||
|
SLASH_LOCK_MAP_RESPONSE,
|
||||||
|
BLUEPRINT_SAVE_RESPONSE,
|
||||||
|
BLUEPRINT_LUP_SAVE_RESPONSE,
|
||||||
|
BLUEPRINT_LOAD_RESPONSE_ITEMID,
|
||||||
|
BLUEPRINT_GET_ALL_DATA_RESPONSE,
|
||||||
|
MODEL_INSTANTIATE_RESPONSE,
|
||||||
|
DEBUG_OUTPUT,
|
||||||
|
ADD_FRIEND_REQUEST,
|
||||||
|
ADD_FRIEND_RESPONSE,
|
||||||
|
REMOVE_FRIEND_RESPONSE,
|
||||||
|
GET_FRIENDS_LIST_RESPONSE,
|
||||||
|
UPDATE_FRIEND_NOTIFY,
|
||||||
|
ADD_IGNORE_RESPONSE,
|
||||||
|
REMOVE_IGNORE_RESPONSE,
|
||||||
|
GET_IGNORE_LIST_RESPONSE,
|
||||||
|
TEAM_INVITE,
|
||||||
|
TEAM_INVITE_INITIAL_RESPONSE,
|
||||||
|
GUILD_CREATE_RESPONSE,
|
||||||
|
GUILD_GET_STATUS_RESPONSE,
|
||||||
|
GUILD_INVITE,
|
||||||
|
GUILD_INVITE_INITIAL_RESPONSE,
|
||||||
|
GUILD_INVITE_FINAL_RESPONSE,
|
||||||
|
GUILD_INVITE_CONFIRM,
|
||||||
|
GUILD_ADD_PLAYER,
|
||||||
|
GUILD_REMOVE_PLAYER,
|
||||||
|
GUILD_LOGIN_LOGOUT,
|
||||||
|
GUILD_RANK_CHANGE,
|
||||||
|
GUILD_DATA,
|
||||||
|
GUILD_STATUS,
|
||||||
|
MAIL,
|
||||||
|
DB_PROXY_RESULT,
|
||||||
|
SHOW_ALL_RESPONSE,
|
||||||
|
WHO_RESPONSE,
|
||||||
|
SEND_CANNED_TEXT,
|
||||||
|
UPDATE_CHARACTER_NAME,
|
||||||
|
SET_NETWORK_SIMULATOR,
|
||||||
|
INVALID_CHAT_MESSAGE,
|
||||||
|
MINIMUM_CHAT_MODE_RESPONSE,
|
||||||
|
MINIMUM_CHAT_MODE_RESPONSE_PRIVATE,
|
||||||
|
CHAT_MODERATION_STRING,
|
||||||
|
UGC_MANIFEST_RESPONSE,
|
||||||
|
IN_LOGIN_QUEUE,
|
||||||
|
SERVER_STATES,
|
||||||
|
GM_CLOSE_TARGET_CHAT_WINDOW,
|
||||||
|
GENERAL_TEXT_FOR_LOCALIZATION,
|
||||||
|
UPDATE_FREE_TRIAL_STATUS,
|
||||||
|
UGC_DOWNLOAD_FAILED = 120
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__ECLIENTMESSAGETYPE__H__
|
||||||
@@ -5,7 +5,8 @@ enum class eConnectionType : uint16_t {
|
|||||||
SERVER = 0,
|
SERVER = 0,
|
||||||
AUTH,
|
AUTH,
|
||||||
CHAT,
|
CHAT,
|
||||||
WORLD = 4,
|
CHAT_INTERNAL,
|
||||||
|
WORLD,
|
||||||
CLIENT,
|
CLIENT,
|
||||||
MASTER
|
MASTER
|
||||||
};
|
};
|
||||||
|
|||||||
1613
dCommon/dEnums/eGameMessageType.h
Normal file
1613
dCommon/dEnums/eGameMessageType.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,6 @@
|
|||||||
#define __EINVENTORYTYPE__H__
|
#define __EINVENTORYTYPE__H__
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "magic_enum.hpp"
|
|
||||||
|
|
||||||
static const uint8_t NUMBER_OF_INVENTORIES = 17;
|
static const uint8_t NUMBER_OF_INVENTORIES = 17;
|
||||||
/**
|
/**
|
||||||
* Represents the different types of inventories an entity may have
|
* Represents the different types of inventories an entity may have
|
||||||
@@ -59,10 +56,4 @@ public:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct magic_enum::customize::enum_range<eInventoryType> {
|
|
||||||
static constexpr int min = 0;
|
|
||||||
static constexpr int max = 16;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__EINVENTORYTYPE__H__
|
#endif //!__EINVENTORYTYPE__H__
|
||||||
|
|||||||
36
dCommon/dEnums/eMasterMessageType.h
Normal file
36
dCommon/dEnums/eMasterMessageType.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef __EMASTERMESSAGETYPE__H__
|
||||||
|
#define __EMASTERMESSAGETYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum class eMasterMessageType : uint32_t {
|
||||||
|
REQUEST_PERSISTENT_ID = 1,
|
||||||
|
REQUEST_PERSISTENT_ID_RESPONSE,
|
||||||
|
REQUEST_ZONE_TRANSFER,
|
||||||
|
REQUEST_ZONE_TRANSFER_RESPONSE,
|
||||||
|
SERVER_INFO,
|
||||||
|
REQUEST_SESSION_KEY,
|
||||||
|
SET_SESSION_KEY,
|
||||||
|
SESSION_KEY_RESPONSE,
|
||||||
|
PLAYER_ADDED,
|
||||||
|
PLAYER_REMOVED,
|
||||||
|
|
||||||
|
CREATE_PRIVATE_ZONE,
|
||||||
|
REQUEST_PRIVATE_ZONE,
|
||||||
|
|
||||||
|
WORLD_READY,
|
||||||
|
PREP_ZONE,
|
||||||
|
|
||||||
|
SHUTDOWN,
|
||||||
|
SHUTDOWN_RESPONSE,
|
||||||
|
SHUTDOWN_IMMEDIATE,
|
||||||
|
|
||||||
|
SHUTDOWN_UNIVERSE,
|
||||||
|
|
||||||
|
AFFIRM_TRANSFER_REQUEST,
|
||||||
|
AFFIRM_TRANSFER_RESPONSE,
|
||||||
|
|
||||||
|
NEW_SESSION_ALERT
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__EMASTERMESSAGETYPE__H__
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#ifndef EPROPERTYSORTTYPE_H
|
|
||||||
#define EPROPERTYSORTTYPE_H
|
|
||||||
|
|
||||||
enum ePropertySortType : int32_t {
|
|
||||||
SORT_TYPE_FRIENDS = 0,
|
|
||||||
SORT_TYPE_REPUTATION = 1,
|
|
||||||
SORT_TYPE_RECENT = 3,
|
|
||||||
SORT_TYPE_FEATURED = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!EPROPERTYSORTTYPE_H
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef __EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
|
||||||
#define __EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
enum class eReponseMoveItemBetweenInventoryTypeCode : int32_t {
|
|
||||||
SUCCESS,
|
|
||||||
FAIL_GENERIC,
|
|
||||||
FAIL_INV_FULL,
|
|
||||||
FAIL_ITEM_NOT_FOUND,
|
|
||||||
FAIL_CANT_MOVE_TO_THAT_INV_TYPE,
|
|
||||||
FAIL_NOT_NEAR_BANK,
|
|
||||||
FAIL_CANT_SWAP_ITEMS,
|
|
||||||
FAIL_SOURCE_TYPE,
|
|
||||||
FAIL_WRONG_DEST_TYPE,
|
|
||||||
FAIL_SWAP_DEST_TYPE,
|
|
||||||
FAIL_CANT_MOVE_THINKING_HAT,
|
|
||||||
FAIL_DISMOUNT_BEFORE_MOVING
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
|
||||||
12
dCommon/dEnums/eServerMessageType.h
Normal file
12
dCommon/dEnums/eServerMessageType.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef __ESERVERMESSAGETYPE__H__
|
||||||
|
#define __ESERVERMESSAGETYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
//! The Internal Server Packet Identifiers
|
||||||
|
enum class eServerMessageType : uint32_t {
|
||||||
|
VERSION_CONFIRM = 0,
|
||||||
|
DISCONNECT_NOTIFY,
|
||||||
|
GENERAL_NOTIFY
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__ESERVERMESSAGETYPE__H__
|
||||||
51
dCommon/dEnums/eWorldMessageType.h
Normal file
51
dCommon/dEnums/eWorldMessageType.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef __EWORLDMESSAGETYPE__H__
|
||||||
|
#define __EWORLDMESSAGETYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "magic_enum.hpp"
|
||||||
|
|
||||||
|
enum class eWorldMessageType : uint32_t {
|
||||||
|
VALIDATION = 1, // Session info
|
||||||
|
CHARACTER_LIST_REQUEST,
|
||||||
|
CHARACTER_CREATE_REQUEST,
|
||||||
|
LOGIN_REQUEST, // Character selected
|
||||||
|
GAME_MSG,
|
||||||
|
CHARACTER_DELETE_REQUEST,
|
||||||
|
CHARACTER_RENAME_REQUEST,
|
||||||
|
HAPPY_FLOWER_MODE_NOTIFY,
|
||||||
|
SLASH_RELOAD_MAP, // Reload map cmp
|
||||||
|
SLASH_PUSH_MAP_REQUEST, // Push map req cmd
|
||||||
|
SLASH_PUSH_MAP, // Push map cmd
|
||||||
|
SLASH_PULL_MAP, // Pull map cmd
|
||||||
|
LOCK_MAP_REQUEST,
|
||||||
|
GENERAL_CHAT_MESSAGE, // General chat message
|
||||||
|
HTTP_MONITOR_INFO_REQUEST,
|
||||||
|
SLASH_DEBUG_SCRIPTS, // Debug scripts cmd
|
||||||
|
MODELS_CLEAR,
|
||||||
|
EXHIBIT_INSERT_MODEL,
|
||||||
|
LEVEL_LOAD_COMPLETE, // Character data request
|
||||||
|
TMP_GUILD_CREATE,
|
||||||
|
ROUTE_PACKET, // Social?
|
||||||
|
POSITION_UPDATE,
|
||||||
|
MAIL,
|
||||||
|
WORD_CHECK, // Whitelist word check
|
||||||
|
STRING_CHECK, // Whitelist string check
|
||||||
|
GET_PLAYERS_IN_ZONE,
|
||||||
|
REQUEST_UGC_MANIFEST_INFO,
|
||||||
|
BLUEPRINT_GET_ALL_DATA_REQUEST,
|
||||||
|
CANCEL_MAP_QUEUE,
|
||||||
|
HANDLE_FUNNESS,
|
||||||
|
FAKE_PRG_CSR_MESSAGE,
|
||||||
|
REQUEST_FREE_TRIAL_REFRESH,
|
||||||
|
GM_SET_FREE_TRIAL_STATUS,
|
||||||
|
UI_HELP_TOP_5 = 91
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct magic_enum::customize::enum_range<eWorldMessageType> {
|
||||||
|
static constexpr int min = 0;
|
||||||
|
static constexpr int max = 91;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__EWORLDMESSAGETYPE__H__
|
||||||
@@ -25,7 +25,6 @@
|
|||||||
#include "CDScriptComponentTable.h"
|
#include "CDScriptComponentTable.h"
|
||||||
#include "CDSkillBehaviorTable.h"
|
#include "CDSkillBehaviorTable.h"
|
||||||
#include "CDZoneTableTable.h"
|
#include "CDZoneTableTable.h"
|
||||||
#include "CDTamingBuildPuzzleTable.h"
|
|
||||||
#include "CDVendorComponentTable.h"
|
#include "CDVendorComponentTable.h"
|
||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
#include "CDPackageComponentTable.h"
|
#include "CDPackageComponentTable.h"
|
||||||
@@ -42,6 +41,8 @@
|
|||||||
#include "CDRewardCodesTable.h"
|
#include "CDRewardCodesTable.h"
|
||||||
#include "CDPetComponentTable.h"
|
#include "CDPetComponentTable.h"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
#ifndef CDCLIENT_CACHE_ALL
|
#ifndef CDCLIENT_CACHE_ALL
|
||||||
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
||||||
// A vanilla CDClient takes about 46MB of memory + the regular world data.
|
// A vanilla CDClient takes about 46MB of memory + the regular world data.
|
||||||
@@ -54,6 +55,13 @@
|
|||||||
#define CDCLIENT_DONT_CACHE_TABLE(x)
|
#define CDCLIENT_DONT_CACHE_TABLE(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class CDClientConnectionException : public std::exception {
|
||||||
|
public:
|
||||||
|
virtual const char* what() const throw() {
|
||||||
|
return "CDClientDatabase is not connected!";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Using a macro to reduce repetitive code and issues from copy and paste.
|
// Using a macro to reduce repetitive code and issues from copy and paste.
|
||||||
// As a note, ## in a macro is used to concatenate two tokens together.
|
// As a note, ## in a macro is used to concatenate two tokens together.
|
||||||
|
|
||||||
@@ -100,14 +108,11 @@ DEFINE_TABLE_STORAGE(CDRewardCodesTable);
|
|||||||
DEFINE_TABLE_STORAGE(CDRewardsTable);
|
DEFINE_TABLE_STORAGE(CDRewardsTable);
|
||||||
DEFINE_TABLE_STORAGE(CDScriptComponentTable);
|
DEFINE_TABLE_STORAGE(CDScriptComponentTable);
|
||||||
DEFINE_TABLE_STORAGE(CDSkillBehaviorTable);
|
DEFINE_TABLE_STORAGE(CDSkillBehaviorTable);
|
||||||
DEFINE_TABLE_STORAGE(CDTamingBuildPuzzleTable);
|
|
||||||
DEFINE_TABLE_STORAGE(CDVendorComponentTable);
|
DEFINE_TABLE_STORAGE(CDVendorComponentTable);
|
||||||
DEFINE_TABLE_STORAGE(CDZoneTableTable);
|
DEFINE_TABLE_STORAGE(CDZoneTableTable);
|
||||||
|
|
||||||
void CDClientManager::LoadValuesFromDatabase() {
|
void CDClientManager::LoadValuesFromDatabase() {
|
||||||
if (!CDClientDatabase::isConnected) {
|
if (!CDClientDatabase::isConnected) throw CDClientConnectionException();
|
||||||
throw std::runtime_error{ "CDClientDatabase is not connected!" };
|
|
||||||
}
|
|
||||||
|
|
||||||
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
|
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDActivitiesTable::Instance().LoadValuesFromDatabase();
|
CDActivitiesTable::Instance().LoadValuesFromDatabase();
|
||||||
@@ -147,7 +152,6 @@ void CDClientManager::LoadValuesFromDatabase() {
|
|||||||
CDRewardsTable::Instance().LoadValuesFromDatabase();
|
CDRewardsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
|
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
|
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
|
||||||
CDTamingBuildPuzzleTable::Instance().LoadValuesFromDatabase();
|
|
||||||
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
|
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDZoneTableTable::Instance().LoadValuesFromDatabase();
|
CDZoneTableTable::Instance().LoadValuesFromDatabase();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ void CDPetComponentTable::LoadValuesFromDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CDPetComponentTable::LoadValuesFromDefaults() {
|
void CDPetComponentTable::LoadValuesFromDefaults() {
|
||||||
GetEntriesMutable().emplace(defaultEntry.id, defaultEntry);
|
GetEntriesMutable().insert(std::make_pair(defaultEntry.id, defaultEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) {
|
CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) {
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
#include "CDTamingBuildPuzzleTable.h"
|
|
||||||
|
|
||||||
void CDTamingBuildPuzzleTable::LoadValuesFromDatabase() {
|
|
||||||
// First, get the size of the table
|
|
||||||
uint32_t size = 0;
|
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM TamingBuildPuzzles");
|
|
||||||
while (!tableSize.eof()) {
|
|
||||||
size = tableSize.getIntField(0, 0);
|
|
||||||
tableSize.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserve the size
|
|
||||||
auto& entries = GetEntriesMutable();
|
|
||||||
entries.reserve(size);
|
|
||||||
|
|
||||||
// Now get the data
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM TamingBuildPuzzles");
|
|
||||||
while (!tableData.eof()) {
|
|
||||||
const auto lot = static_cast<LOT>(tableData.getIntField("NPCLot", LOT_NULL));
|
|
||||||
entries.emplace(lot, CDTamingBuildPuzzle{
|
|
||||||
.puzzleModelLot = lot,
|
|
||||||
.validPieces{ tableData.getStringField("ValidPiecesLXF") },
|
|
||||||
.timeLimit = static_cast<float>(tableData.getFloatField("Timelimit", 30.0f)),
|
|
||||||
.numValidPieces = tableData.getIntField("NumValidPieces", 6),
|
|
||||||
.imaginationCost = tableData.getIntField("imagCostPerBuild", 10)
|
|
||||||
});
|
|
||||||
tableData.nextRow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const CDTamingBuildPuzzle* CDTamingBuildPuzzleTable::GetByLOT(const LOT lot) const {
|
|
||||||
const auto& entries = GetEntries();
|
|
||||||
const auto itr = entries.find(lot);
|
|
||||||
return itr != entries.cend() ? &itr->second : nullptr;
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "CDTable.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information for the minigame to be completed
|
|
||||||
*/
|
|
||||||
struct CDTamingBuildPuzzle {
|
|
||||||
UNUSED_COLUMN(uint32_t id = 0;)
|
|
||||||
|
|
||||||
// The LOT of the object that is to be created
|
|
||||||
LOT puzzleModelLot = LOT_NULL;
|
|
||||||
|
|
||||||
// The LOT of the NPC
|
|
||||||
UNUSED_COLUMN(LOT npcLot = LOT_NULL;)
|
|
||||||
|
|
||||||
// The .lxfml file that contains the bricks required to build the model
|
|
||||||
std::string validPieces{};
|
|
||||||
|
|
||||||
// The .lxfml file that contains the bricks NOT required to build the model
|
|
||||||
UNUSED_COLUMN(std::string invalidPieces{};)
|
|
||||||
|
|
||||||
// Difficulty value
|
|
||||||
UNUSED_COLUMN(int32_t difficulty = 1;)
|
|
||||||
|
|
||||||
// The time limit to complete the build
|
|
||||||
float timeLimit = 30.0f;
|
|
||||||
|
|
||||||
// The number of pieces required to complete the minigame
|
|
||||||
int32_t numValidPieces = 6;
|
|
||||||
|
|
||||||
// Number of valid pieces
|
|
||||||
UNUSED_COLUMN(int32_t totalNumPieces = 16;)
|
|
||||||
|
|
||||||
// Model name
|
|
||||||
UNUSED_COLUMN(std::string modelName{};)
|
|
||||||
|
|
||||||
// The .lxfml file that contains the full model
|
|
||||||
UNUSED_COLUMN(std::string fullModel{};)
|
|
||||||
|
|
||||||
// The duration of the pet taming minigame
|
|
||||||
UNUSED_COLUMN(float duration = 45.0f;)
|
|
||||||
|
|
||||||
// The imagination cost for the tamer to start the minigame
|
|
||||||
int32_t imaginationCost = 10;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CDTamingBuildPuzzleTable : public CDTable<CDTamingBuildPuzzleTable, std::unordered_map<LOT, CDTamingBuildPuzzle>> {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Load values from the CD client database
|
|
||||||
*/
|
|
||||||
void LoadValuesFromDatabase();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the pet ability table corresponding to the pet LOT
|
|
||||||
* @returns A pointer to the corresponding table, or nullptr if one cannot be found
|
|
||||||
*/
|
|
||||||
[[nodiscard]]
|
|
||||||
const CDTamingBuildPuzzle* GetByLOT(const LOT lot) const;
|
|
||||||
};
|
|
||||||
@@ -36,6 +36,5 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
|
|||||||
"CDRewardsTable.cpp"
|
"CDRewardsTable.cpp"
|
||||||
"CDScriptComponentTable.cpp"
|
"CDScriptComponentTable.cpp"
|
||||||
"CDSkillBehaviorTable.cpp"
|
"CDSkillBehaviorTable.cpp"
|
||||||
"CDTamingBuildPuzzleTable.cpp"
|
|
||||||
"CDVendorComponentTable.cpp"
|
"CDVendorComponentTable.cpp"
|
||||||
"CDZoneTableTable.cpp" PARENT_SCOPE)
|
"CDZoneTableTable.cpp" PARENT_SCOPE)
|
||||||
|
|||||||
@@ -2,12 +2,6 @@ add_subdirectory(CDClientDatabase)
|
|||||||
add_subdirectory(GameDatabase)
|
add_subdirectory(GameDatabase)
|
||||||
|
|
||||||
add_library(dDatabase STATIC "MigrationRunner.cpp")
|
add_library(dDatabase STATIC "MigrationRunner.cpp")
|
||||||
|
|
||||||
add_custom_target(conncpp_dylib
|
|
||||||
${CMAKE_COMMAND} -E copy $<TARGET_FILE:MariaDB::ConnCpp> ${PROJECT_BINARY_DIR})
|
|
||||||
|
|
||||||
add_dependencies(dDatabase conncpp_dylib)
|
|
||||||
|
|
||||||
target_include_directories(dDatabase PUBLIC ".")
|
target_include_directories(dDatabase PUBLIC ".")
|
||||||
target_link_libraries(dDatabase
|
target_link_libraries(dDatabase
|
||||||
PUBLIC dDatabaseCDClient dDatabaseGame)
|
PUBLIC dDatabaseCDClient dDatabaseGame)
|
||||||
|
|||||||
@@ -8,28 +8,15 @@ foreach(file ${DDATABSE_DATABSES_MYSQL_SOURCES})
|
|||||||
set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "MySQL/${file}")
|
set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "MySQL/${file}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_subdirectory(SQLite)
|
|
||||||
|
|
||||||
foreach(file ${DDATABSE_DATABSES_SQLITE_SOURCES})
|
|
||||||
set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "SQLite/${file}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
add_subdirectory(TestSQL)
|
|
||||||
|
|
||||||
foreach(file ${DDATABSE_DATABSES_TEST_SQL_SOURCES})
|
|
||||||
set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "TestSQL/${file}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
add_library(dDatabaseGame STATIC ${DDATABASE_GAMEDATABASE_SOURCES})
|
add_library(dDatabaseGame STATIC ${DDATABASE_GAMEDATABASE_SOURCES})
|
||||||
target_include_directories(dDatabaseGame PUBLIC "."
|
target_include_directories(dDatabaseGame PUBLIC "."
|
||||||
"ITables" PRIVATE "MySQL" "SQLite" "TestSQL"
|
"ITables" PRIVATE "MySQL"
|
||||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(dDatabaseGame
|
target_link_libraries(dDatabaseGame
|
||||||
INTERFACE dCommon
|
PUBLIC MariaDB::ConnCpp
|
||||||
PRIVATE sqlite3 MariaDB::ConnCpp)
|
INTERFACE dCommon)
|
||||||
|
|
||||||
# Glob together all headers that need to be precompiled
|
# Glob together all headers that need to be precompiled
|
||||||
file(
|
file(
|
||||||
|
|||||||
@@ -2,12 +2,8 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "DluAssert.h"
|
|
||||||
|
|
||||||
#include "SQLiteDatabase.h"
|
|
||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
#include "DluAssert.h"
|
||||||
#include <ranges>
|
|
||||||
|
|
||||||
#pragma warning (disable:4251) //Disables SQL warnings
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
|
|
||||||
@@ -15,33 +11,13 @@ namespace {
|
|||||||
GameDatabase* database = nullptr;
|
GameDatabase* database = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Database::GetMigrationFolder() {
|
|
||||||
const std::set<std::string> validMysqlTypes = { "mysql", "mariadb", "maria" };
|
|
||||||
auto databaseType = Game::config->GetValue("database_type");
|
|
||||||
std::ranges::transform(databaseType, databaseType.begin(), ::tolower);
|
|
||||||
if (databaseType == "sqlite") return "sqlite";
|
|
||||||
else if (validMysqlTypes.contains(databaseType)) return "mysql";
|
|
||||||
else {
|
|
||||||
LOG("No database specified, using MySQL");
|
|
||||||
return "mysql";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Database::Connect() {
|
void Database::Connect() {
|
||||||
if (database) {
|
if (database) {
|
||||||
LOG("Tried to connect to database when it's already connected!");
|
LOG("Tried to connect to database when it's already connected!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto databaseType = GetMigrationFolder();
|
database = new MySQLDatabase();
|
||||||
|
|
||||||
if (databaseType == "sqlite") database = new SQLiteDatabase();
|
|
||||||
else if (databaseType == "mysql") database = new MySQLDatabase();
|
|
||||||
else {
|
|
||||||
LOG("Invalid database type specified in config, using MySQL");
|
|
||||||
database = new MySQLDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
database->Connect();
|
database->Connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +38,3 @@ void Database::Destroy(std::string source) {
|
|||||||
LOG("Trying to destroy database when it's not connected!");
|
LOG("Trying to destroy database when it's not connected!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::_setDatabase(GameDatabase* const db) {
|
|
||||||
if (database) delete database;
|
|
||||||
database = db;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <conncpp.hpp>
|
||||||
|
|
||||||
#include "GameDatabase.h"
|
#include "GameDatabase.h"
|
||||||
|
|
||||||
@@ -8,10 +9,4 @@ namespace Database {
|
|||||||
void Connect();
|
void Connect();
|
||||||
GameDatabase* Get();
|
GameDatabase* Get();
|
||||||
void Destroy(std::string source = "");
|
void Destroy(std::string source = "");
|
||||||
|
|
||||||
// Used for assigning a test database as the handler for database logic.
|
|
||||||
// Do not use in production code.
|
|
||||||
void _setDatabase(GameDatabase* const db);
|
|
||||||
|
|
||||||
std::string GetMigrationFolder();
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,11 +23,14 @@
|
|||||||
#include "IActivityLog.h"
|
#include "IActivityLog.h"
|
||||||
#include "IIgnoreList.h"
|
#include "IIgnoreList.h"
|
||||||
#include "IAccountsRewardCodes.h"
|
#include "IAccountsRewardCodes.h"
|
||||||
#include "IBehaviors.h"
|
|
||||||
#include "IUgcModularBuild.h"
|
namespace sql {
|
||||||
|
class Statement;
|
||||||
|
class PreparedStatement;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (std::exception& ex) { LOG("SQL Error: %s", ex.what()); throw; } } while(0)
|
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (sql::SQLException& ex) { LOG("SQL Error: %s", ex.what()); throw; } } while(0)
|
||||||
#else
|
#else
|
||||||
# define DLU_SQL_TRY_CATCH_RETHROW(x) x
|
# define DLU_SQL_TRY_CATCH_RETHROW(x) x
|
||||||
#endif // _DEBUG
|
#endif // _DEBUG
|
||||||
@@ -37,14 +40,14 @@ class GameDatabase :
|
|||||||
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
|
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
|
||||||
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
||||||
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
||||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList,
|
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList {
|
||||||
public IBehaviors, public IUgcModularBuild {
|
|
||||||
public:
|
public:
|
||||||
virtual ~GameDatabase() = default;
|
virtual ~GameDatabase() = default;
|
||||||
// TODO: These should be made private.
|
// TODO: These should be made private.
|
||||||
virtual void Connect() = 0;
|
virtual void Connect() = 0;
|
||||||
virtual void Destroy(std::string source = "") = 0;
|
virtual void Destroy(std::string source = "") = 0;
|
||||||
virtual void ExecuteCustomQuery(const std::string_view query) = 0;
|
virtual void ExecuteCustomQuery(const std::string_view query) = 0;
|
||||||
|
virtual sql::PreparedStatement* CreatePreppedStmt(const std::string& query) = 0;
|
||||||
virtual void Commit() = 0;
|
virtual void Commit() = 0;
|
||||||
virtual bool GetAutoCommit() = 0;
|
virtual bool GetAutoCommit() = 0;
|
||||||
virtual void SetAutoCommit(bool value) = 0;
|
virtual void SetAutoCommit(bool value) = 0;
|
||||||
|
|||||||
@@ -33,11 +33,6 @@ public:
|
|||||||
|
|
||||||
// Add a new account to the database.
|
// Add a new account to the database.
|
||||||
virtual void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) = 0;
|
virtual void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) = 0;
|
||||||
|
|
||||||
// Update the GameMaster level of an account.
|
|
||||||
virtual void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) = 0;
|
|
||||||
|
|
||||||
virtual uint32_t GetAccountCount() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IACCOUNTS__H__
|
#endif //!__IACCOUNTS__H__
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
#ifndef IBEHAVIORS_H
|
|
||||||
#define IBEHAVIORS_H
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
|
||||||
|
|
||||||
class IBehaviors {
|
|
||||||
public:
|
|
||||||
struct Info {
|
|
||||||
int32_t behaviorId{};
|
|
||||||
uint32_t characterId{};
|
|
||||||
std::string behaviorInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This Add also takes care of updating if it exists.
|
|
||||||
virtual void AddBehavior(const Info& info) = 0;
|
|
||||||
virtual std::string GetBehavior(const int32_t behaviorId) = 0;
|
|
||||||
virtual void RemoveBehavior(const int32_t behaviorId) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!IBEHAVIORS_H
|
|
||||||
@@ -3,45 +3,12 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class ILeaderboard {
|
class ILeaderboard {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Entry {
|
|
||||||
uint32_t charId{};
|
|
||||||
uint32_t lastPlayedTimestamp{};
|
|
||||||
float primaryScore{};
|
|
||||||
float secondaryScore{};
|
|
||||||
uint32_t tertiaryScore{};
|
|
||||||
uint32_t numWins{};
|
|
||||||
uint32_t numTimesPlayed{};
|
|
||||||
uint32_t ranking{};
|
|
||||||
std::string name{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Score {
|
|
||||||
auto operator<=>(const Score& rhs) const = default;
|
|
||||||
|
|
||||||
float primaryScore{ 0.0f };
|
|
||||||
float secondaryScore{ 0.0f };
|
|
||||||
float tertiaryScore{ 0.0f };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the donation total for the given activity id.
|
// Get the donation total for the given activity id.
|
||||||
virtual std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) = 0;
|
virtual std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) = 0;
|
||||||
|
|
||||||
virtual std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) = 0;
|
|
||||||
virtual std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) = 0;
|
|
||||||
virtual std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) = 0;
|
|
||||||
virtual std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) = 0;
|
|
||||||
virtual std::optional<Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) = 0;
|
|
||||||
|
|
||||||
virtual void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
|
|
||||||
virtual void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
|
|
||||||
virtual void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) = 0;
|
|
||||||
virtual void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ILEADERBOARD__H__
|
#endif //!__ILEADERBOARD__H__
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
enum ePropertySortType : int32_t;
|
|
||||||
|
|
||||||
class IProperty {
|
class IProperty {
|
||||||
public:
|
public:
|
||||||
struct Info {
|
struct Info {
|
||||||
@@ -20,33 +18,11 @@ public:
|
|||||||
uint32_t lastUpdatedTime{};
|
uint32_t lastUpdatedTime{};
|
||||||
uint32_t claimedTime{};
|
uint32_t claimedTime{};
|
||||||
uint32_t reputation{};
|
uint32_t reputation{};
|
||||||
float performanceCost{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PropertyLookup {
|
|
||||||
uint32_t mapId{};
|
|
||||||
std::string searchString;
|
|
||||||
ePropertySortType sortChoice{};
|
|
||||||
uint32_t playerId{};
|
|
||||||
uint32_t numResults{};
|
|
||||||
uint32_t startIndex{};
|
|
||||||
uint32_t playerSort{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PropertyEntranceResult {
|
|
||||||
int32_t totalEntriesMatchingQuery{};
|
|
||||||
// The entries that match the query. This should only contain up to 12 entries.
|
|
||||||
std::vector<IProperty::Info> entries;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the property info for the given property id.
|
// Get the property info for the given property id.
|
||||||
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
||||||
|
|
||||||
// Get the properties for the given property lookup params.
|
|
||||||
// This is expected to return a result set of up to 12 properties
|
|
||||||
// so as not to transfer too much data at once.
|
|
||||||
virtual std::optional<IProperty::PropertyEntranceResult> GetProperties(const PropertyLookup& params) = 0;
|
|
||||||
|
|
||||||
// Update the property moderation info for the given property id.
|
// Update the property moderation info for the given property id.
|
||||||
virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0;
|
virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef __IPROPERTIESCONTENTS__H__
|
#ifndef __IPROPERTIESCONTENTS__H__
|
||||||
#define __IPROPERTIESCONTENTS__H__
|
#define __IPROPERTIESCONTENTS__H__
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
@@ -17,7 +16,6 @@ public:
|
|||||||
LWOOBJID id{};
|
LWOOBJID id{};
|
||||||
LOT lot{};
|
LOT lot{};
|
||||||
uint32_t ugcId{};
|
uint32_t ugcId{};
|
||||||
std::array<int32_t, 5> behaviors{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inserts a new UGC model into the database.
|
// Inserts a new UGC model into the database.
|
||||||
@@ -34,7 +32,7 @@ public:
|
|||||||
virtual void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) = 0;
|
virtual void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) = 0;
|
||||||
|
|
||||||
// Update the model position and rotation for the given property id.
|
// Update the model position and rotation for the given property id.
|
||||||
virtual void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) = 0;
|
virtual void UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) = 0;
|
||||||
|
|
||||||
// Remove the model for the given property id.
|
// Remove the model for the given property id.
|
||||||
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
#ifndef IUGCMODULARBUILD_H
|
|
||||||
#define IUGCMODULARBUILD_H
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class IUgcModularBuild {
|
|
||||||
public:
|
|
||||||
virtual void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) = 0;
|
|
||||||
virtual void DeleteUgcBuild(const LWOOBJID bigId) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!IUGCMODULARBUILD_H
|
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "dPlatforms.h"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string databaseName;
|
std::string databaseName;
|
||||||
@@ -14,7 +13,6 @@ namespace {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void MySQLDatabase::Connect() {
|
void MySQLDatabase::Connect() {
|
||||||
LOG("Using MySQL database");
|
|
||||||
driver = sql::mariadb::get_driver_instance();
|
driver = sql::mariadb::get_driver_instance();
|
||||||
|
|
||||||
// The mariadb connector is *supposed* to handle unix:// and pipe:// prefixes to hostName, but there are bugs where
|
// The mariadb connector is *supposed* to handle unix:// and pipe:// prefixes to hostName, but there are bugs where
|
||||||
@@ -41,13 +39,14 @@ void MySQLDatabase::Connect() {
|
|||||||
properties["autoReconnect"] = "true";
|
properties["autoReconnect"] = "true";
|
||||||
|
|
||||||
databaseName = Game::config->GetValue("mysql_database").c_str();
|
databaseName = Game::config->GetValue("mysql_database").c_str();
|
||||||
|
|
||||||
// `connect(const Properties& props)` segfaults in windows debug, but
|
// `connect(const Properties& props)` segfaults in windows debug, but
|
||||||
// `connect(const SQLString& host, const SQLString& user, const SQLString& pwd)` doesn't handle pipes/unix sockets correctly
|
// `connect(const SQLString& host, const SQLString& user, const SQLString& pwd)` doesn't handle pipes/unix sockets correctly
|
||||||
#if defined(DARKFLAME_PLATFORM_WIN32) && defined(_DEBUG)
|
if (properties.find("localSocket") != properties.end() || properties.find("pipe") != properties.end()) {
|
||||||
con = driver->connect(properties["hostName"].c_str(), properties["user"].c_str(), properties["password"].c_str());
|
|
||||||
#else
|
|
||||||
con = driver->connect(properties);
|
con = driver->connect(properties);
|
||||||
#endif
|
} else {
|
||||||
|
con = driver->connect(properties["hostName"].c_str(), properties["user"].c_str(), properties["password"].c_str());
|
||||||
|
}
|
||||||
con->setSchema(databaseName.c_str());
|
con->setSchema(databaseName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ void MySQLDatabase::ExecuteCustomQuery(const std::string_view query) {
|
|||||||
|
|
||||||
sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& query) {
|
sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& query) {
|
||||||
if (!con) {
|
if (!con) {
|
||||||
Database::Get()->Connect();
|
Connect();
|
||||||
LOG("Trying to reconnect to MySQL");
|
LOG("Trying to reconnect to MySQL");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@ sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& quer
|
|||||||
|
|
||||||
con = nullptr;
|
con = nullptr;
|
||||||
|
|
||||||
Database::Get()->Connect();
|
Connect();
|
||||||
LOG("Trying to reconnect to MySQL from invalid or closed connection");
|
LOG("Trying to reconnect to MySQL from invalid or closed connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include "GameDatabase.h"
|
#include "GameDatabase.h"
|
||||||
|
|
||||||
typedef std::unique_ptr<sql::PreparedStatement>& UniquePreppedStmtRef;
|
typedef std::unique_ptr<sql::PreparedStatement>& UniquePreppedStmtRef;
|
||||||
typedef std::unique_ptr<sql::ResultSet> UniqueResultSet;
|
|
||||||
|
|
||||||
// Purposefully no definition for this to provide linker errors in the case someone tries to
|
// Purposefully no definition for this to provide linker errors in the case someone tries to
|
||||||
// bind a parameter to a type that isn't defined.
|
// bind a parameter to a type that isn't defined.
|
||||||
@@ -30,6 +29,7 @@ public:
|
|||||||
void Connect() override;
|
void Connect() override;
|
||||||
void Destroy(std::string source = "") override;
|
void Destroy(std::string source = "") override;
|
||||||
|
|
||||||
|
sql::PreparedStatement* CreatePreppedStmt(const std::string& query) override;
|
||||||
void Commit() override;
|
void Commit() override;
|
||||||
bool GetAutoCommit() override;
|
bool GetAutoCommit() override;
|
||||||
void SetAutoCommit(bool value) override;
|
void SetAutoCommit(bool value) override;
|
||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) override;
|
std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) override;
|
||||||
void RemoveUnreferencedUgcModels() override;
|
void RemoveUnreferencedUgcModels() override;
|
||||||
void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) override;
|
void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) override;
|
||||||
void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) override;
|
void UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) override;
|
||||||
void RemoveModel(const LWOOBJID& modelId) override;
|
void RemoveModel(const LWOOBJID& modelId) override;
|
||||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||||
@@ -108,24 +108,6 @@ public:
|
|||||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
||||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||||
void AddBehavior(const IBehaviors::Info& info) override;
|
|
||||||
std::string GetBehavior(const int32_t behaviorId) override;
|
|
||||||
void RemoveBehavior(const int32_t characterId) override;
|
|
||||||
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
|
||||||
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override;
|
|
||||||
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override;
|
|
||||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
|
||||||
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
|
||||||
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
|
||||||
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
|
||||||
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
|
||||||
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
|
||||||
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
|
||||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
|
||||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
|
||||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
|
||||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
|
||||||
uint32_t GetAccountCount() override;
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Generic query functions that can be used for any query.
|
// Generic query functions that can be used for any query.
|
||||||
|
|||||||
@@ -35,12 +35,3 @@ void MySQLDatabase::UpdateAccountPassword(const uint32_t accountId, const std::s
|
|||||||
void MySQLDatabase::InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) {
|
void MySQLDatabase::InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) {
|
||||||
ExecuteInsert("INSERT INTO accounts (name, password, gm_level) VALUES (?, ?, ?);", username, bcryptpassword, static_cast<int32_t>(eGameMasterLevel::OPERATOR));
|
ExecuteInsert("INSERT INTO accounts (name, password, gm_level) VALUES (?, ?, ?);", username, bcryptpassword, static_cast<int32_t>(eGameMasterLevel::OPERATOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) {
|
|
||||||
ExecuteUpdate("UPDATE accounts SET gm_level = ? WHERE id = ?;", static_cast<int32_t>(gmLevel), accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MySQLDatabase::GetAccountCount() {
|
|
||||||
auto res = ExecuteSelect("SELECT COUNT(*) as count FROM accounts;");
|
|
||||||
return res->next() ? res->getUInt("count") : 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
#include "IBehaviors.h"
|
|
||||||
|
|
||||||
#include "MySQLDatabase.h"
|
|
||||||
|
|
||||||
void MySQLDatabase::AddBehavior(const IBehaviors::Info& info) {
|
|
||||||
ExecuteInsert(
|
|
||||||
"INSERT INTO behaviors (behavior_info, character_id, behavior_id) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE behavior_info = ?",
|
|
||||||
info.behaviorInfo, info.characterId, info.behaviorId, info.behaviorInfo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::RemoveBehavior(const int32_t behaviorId) {
|
|
||||||
ExecuteDelete("DELETE FROM behaviors WHERE behavior_id = ?", behaviorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MySQLDatabase::GetBehavior(const int32_t behaviorId) {
|
|
||||||
auto result = ExecuteSelect("SELECT behavior_info FROM behaviors WHERE behavior_id = ?", behaviorId);
|
|
||||||
return result->next() ? result->getString("behavior_info").c_str() : "";
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
|||||||
"Accounts.cpp"
|
"Accounts.cpp"
|
||||||
"AccountsRewardCodes.cpp"
|
"AccountsRewardCodes.cpp"
|
||||||
"ActivityLog.cpp"
|
"ActivityLog.cpp"
|
||||||
"Behaviors.cpp"
|
|
||||||
"BugReports.cpp"
|
"BugReports.cpp"
|
||||||
"CharInfo.cpp"
|
"CharInfo.cpp"
|
||||||
"CharXml.cpp"
|
"CharXml.cpp"
|
||||||
@@ -20,7 +19,6 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
|||||||
"PropertyContents.cpp"
|
"PropertyContents.cpp"
|
||||||
"Servers.cpp"
|
"Servers.cpp"
|
||||||
"Ugc.cpp"
|
"Ugc.cpp"
|
||||||
"UgcModularBuild.cpp"
|
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
#include "Game.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "dConfig.h"
|
|
||||||
|
|
||||||
std::optional<uint32_t> MySQLDatabase::GetDonationTotal(const uint32_t activityId) {
|
std::optional<uint32_t> MySQLDatabase::GetDonationTotal(const uint32_t activityId) {
|
||||||
auto donation_total = ExecuteSelect("SELECT SUM(primaryScore) as donation_total FROM leaderboard WHERE game_id = ?;", activityId);
|
auto donation_total = ExecuteSelect("SELECT SUM(primaryScore) as donation_total FROM leaderboard WHERE game_id = ?;", activityId);
|
||||||
|
|
||||||
@@ -13,79 +9,3 @@ std::optional<uint32_t> MySQLDatabase::GetDonationTotal(const uint32_t activityI
|
|||||||
|
|
||||||
return donation_total->getUInt("donation_total");
|
return donation_total->getUInt("donation_total");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> ProcessQuery(UniqueResultSet& rows) {
|
|
||||||
std::vector<ILeaderboard::Entry> entries;
|
|
||||||
entries.reserve(rows->rowsCount());
|
|
||||||
|
|
||||||
while (rows->next()) {
|
|
||||||
auto& entry = entries.emplace_back();
|
|
||||||
|
|
||||||
entry.charId = rows->getUInt("character_id");
|
|
||||||
entry.lastPlayedTimestamp = rows->getUInt("lp_unix");
|
|
||||||
entry.primaryScore = rows->getFloat("primaryScore");
|
|
||||||
entry.secondaryScore = rows->getFloat("secondaryScore");
|
|
||||||
entry.tertiaryScore = rows->getFloat("tertiaryScore");
|
|
||||||
entry.numWins = rows->getUInt("numWins");
|
|
||||||
entry.numTimesPlayed = rows->getUInt("timesPlayed");
|
|
||||||
entry.name = rows->getString("char_name");
|
|
||||||
// entry.ranking is never set because its calculated in leaderboard in code.
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> MySQLDatabase::GetDescendingLeaderboard(const uint32_t activityId) {
|
|
||||||
auto leaderboard = ExecuteSelect("SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore DESC, tertiaryScore DESC, last_played ASC;", activityId);
|
|
||||||
return ProcessQuery(leaderboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> MySQLDatabase::GetAscendingLeaderboard(const uint32_t activityId) {
|
|
||||||
auto leaderboard = ExecuteSelect("SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore ASC, secondaryscore ASC, tertiaryScore ASC, last_played ASC;", activityId);
|
|
||||||
return ProcessQuery(leaderboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> MySQLDatabase::GetAgsLeaderboard(const uint32_t activityId) {
|
|
||||||
auto query = Game::config->GetValue("classic_survival_scoring") != "1" ?
|
|
||||||
"SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore DESC, tertiaryScore DESC, last_played ASC;" :
|
|
||||||
"SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY secondaryscore DESC, primaryscore DESC, tertiaryScore DESC, last_played ASC;";
|
|
||||||
auto leaderboard = ExecuteSelect(query, activityId);
|
|
||||||
return ProcessQuery(leaderboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> MySQLDatabase::GetNsLeaderboard(const uint32_t activityId) {
|
|
||||||
auto leaderboard = ExecuteSelect("SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore ASC, tertiaryScore DESC, last_played ASC;", activityId);
|
|
||||||
return ProcessQuery(leaderboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
|
||||||
ExecuteInsert("INSERT leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, character_id = ?, game_id = ?;",
|
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
|
||||||
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;",
|
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) {
|
|
||||||
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
|
|
||||||
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
|
||||||
auto res = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
|
||||||
if (res->next()) {
|
|
||||||
toReturn = ILeaderboard::Score{
|
|
||||||
.primaryScore = res->getFloat("primaryScore"),
|
|
||||||
.secondaryScore = res->getFloat("secondaryScore"),
|
|
||||||
.tertiaryScore = res->getFloat("tertiaryScore")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t gameId) {
|
|
||||||
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,140 +1,8 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
#include "ePropertySortType.h"
|
|
||||||
|
|
||||||
std::optional<IProperty::PropertyEntranceResult> MySQLDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
|
||||||
std::optional<IProperty::PropertyEntranceResult> result;
|
|
||||||
std::string query;
|
|
||||||
std::unique_ptr<sql::ResultSet> properties;
|
|
||||||
|
|
||||||
if (params.sortChoice == SORT_TYPE_FEATURED || params.sortChoice == SORT_TYPE_FRIENDS) {
|
|
||||||
query = R"QUERY(
|
|
||||||
FROM properties as p
|
|
||||||
JOIN charinfo as ci
|
|
||||||
ON ci.prop_clone_id = p.clone_id
|
|
||||||
where p.zone_id = ?
|
|
||||||
AND (
|
|
||||||
p.description LIKE ?
|
|
||||||
OR p.name LIKE ?
|
|
||||||
OR ci.name LIKE ?
|
|
||||||
)
|
|
||||||
AND p.privacy_option >= ?
|
|
||||||
AND p.owner_id IN (
|
|
||||||
SELECT fr.requested_player AS player FROM (
|
|
||||||
SELECT CASE
|
|
||||||
WHEN player_id = ? THEN friend_id
|
|
||||||
WHEN friend_id = ? THEN player_id
|
|
||||||
END AS requested_player FROM friends
|
|
||||||
) AS fr
|
|
||||||
JOIN charinfo AS ci ON ci.id = fr.requested_player
|
|
||||||
WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?
|
|
||||||
) ORDER BY ci.name ASC
|
|
||||||
)QUERY";
|
|
||||||
const auto completeQuery = "SELECT p.* " + query + " LIMIT ? OFFSET ?;";
|
|
||||||
properties = ExecuteSelect(
|
|
||||||
completeQuery,
|
|
||||||
params.mapId,
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
params.playerSort,
|
|
||||||
params.playerId,
|
|
||||||
params.playerId,
|
|
||||||
params.playerId,
|
|
||||||
params.numResults,
|
|
||||||
params.startIndex
|
|
||||||
);
|
|
||||||
const auto countQuery = "SELECT COUNT(*) as count" + query + ";";
|
|
||||||
auto count = ExecuteSelect(
|
|
||||||
countQuery,
|
|
||||||
params.mapId,
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
params.playerSort,
|
|
||||||
params.playerId,
|
|
||||||
params.playerId,
|
|
||||||
params.playerId
|
|
||||||
);
|
|
||||||
if (count->next()) {
|
|
||||||
result->totalEntriesMatchingQuery = count->getUInt("count");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (params.sortChoice == SORT_TYPE_REPUTATION) {
|
|
||||||
query = R"QUERY(
|
|
||||||
FROM properties as p
|
|
||||||
JOIN charinfo as ci
|
|
||||||
ON ci.prop_clone_id = p.clone_id
|
|
||||||
where p.zone_id = ?
|
|
||||||
AND (
|
|
||||||
p.description LIKE ?
|
|
||||||
OR p.name LIKE ?
|
|
||||||
OR ci.name LIKE ?
|
|
||||||
)
|
|
||||||
AND p.privacy_option >= ?
|
|
||||||
ORDER BY p.reputation DESC, p.last_updated DESC
|
|
||||||
)QUERY";
|
|
||||||
} else {
|
|
||||||
query = R"QUERY(
|
|
||||||
FROM properties as p
|
|
||||||
JOIN charinfo as ci
|
|
||||||
ON ci.prop_clone_id = p.clone_id
|
|
||||||
where p.zone_id = ?
|
|
||||||
AND (
|
|
||||||
p.description LIKE ?
|
|
||||||
OR p.name LIKE ?
|
|
||||||
OR ci.name LIKE ?
|
|
||||||
)
|
|
||||||
AND p.privacy_option >= ?
|
|
||||||
ORDER BY p.last_updated DESC
|
|
||||||
)QUERY";
|
|
||||||
}
|
|
||||||
const auto completeQuery = "SELECT p.* " + query + " LIMIT ? OFFSET ?;";
|
|
||||||
properties = ExecuteSelect(
|
|
||||||
completeQuery,
|
|
||||||
params.mapId,
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
params.playerSort,
|
|
||||||
params.numResults,
|
|
||||||
params.startIndex
|
|
||||||
);
|
|
||||||
const auto countQuery = "SELECT COUNT(*) as count" + query + ";";
|
|
||||||
auto count = ExecuteSelect(
|
|
||||||
countQuery,
|
|
||||||
params.mapId,
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
"%" + params.searchString + "%",
|
|
||||||
params.playerSort
|
|
||||||
);
|
|
||||||
if (count->next()) {
|
|
||||||
result->totalEntriesMatchingQuery = count->getUInt("count");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (properties->next()) {
|
|
||||||
auto& entry = result->entries.emplace_back();
|
|
||||||
entry.id = properties->getUInt64("id");
|
|
||||||
entry.ownerId = properties->getUInt64("owner_id");
|
|
||||||
entry.cloneId = properties->getUInt64("clone_id");
|
|
||||||
entry.name = properties->getString("name").c_str();
|
|
||||||
entry.description = properties->getString("description").c_str();
|
|
||||||
entry.privacyOption = properties->getInt("privacy_option");
|
|
||||||
entry.rejectionReason = properties->getString("rejection_reason").c_str();
|
|
||||||
entry.lastUpdatedTime = properties->getUInt("last_updated");
|
|
||||||
entry.claimedTime = properties->getUInt("time_claimed");
|
|
||||||
entry.reputation = properties->getUInt("reputation");
|
|
||||||
entry.modApproved = properties->getUInt("mod_approved");
|
|
||||||
entry.performanceCost = properties->getFloat("performance_cost");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) {
|
std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) {
|
||||||
auto propertyEntry = ExecuteSelect(
|
auto propertyEntry = ExecuteSelect(
|
||||||
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved "
|
||||||
"FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId);
|
"FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId);
|
||||||
|
|
||||||
if (!propertyEntry->next()) {
|
if (!propertyEntry->next()) {
|
||||||
@@ -153,7 +21,6 @@ std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID map
|
|||||||
toReturn.claimedTime = propertyEntry->getUInt("time_claimed");
|
toReturn.claimedTime = propertyEntry->getUInt("time_claimed");
|
||||||
toReturn.reputation = propertyEntry->getUInt("reputation");
|
toReturn.reputation = propertyEntry->getUInt("reputation");
|
||||||
toReturn.modApproved = propertyEntry->getUInt("mod_approved");
|
toReturn.modApproved = propertyEntry->getUInt("mod_approved");
|
||||||
toReturn.performanceCost = propertyEntry->getFloat("performance_cost");
|
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::vector<IPropertyContents::Model> MySQLDatabase::GetPropertyModels(const LWOOBJID& propertyId) {
|
std::vector<IPropertyContents::Model> MySQLDatabase::GetPropertyModels(const LWOOBJID& propertyId) {
|
||||||
auto result = ExecuteSelect(
|
auto result = ExecuteSelect("SELECT id, lot, x, y, z, rx, ry, rz, rw, ugc_id FROM properties_contents WHERE property_id = ?;", propertyId);
|
||||||
"SELECT id, lot, x, y, z, rx, ry, rz, rw, ugc_id, "
|
|
||||||
"behavior_1, behavior_2, behavior_3, behavior_4, behavior_5 "
|
|
||||||
"FROM properties_contents WHERE property_id = ?;", propertyId);
|
|
||||||
|
|
||||||
std::vector<IPropertyContents::Model> toReturn;
|
std::vector<IPropertyContents::Model> toReturn;
|
||||||
toReturn.reserve(result->rowsCount());
|
toReturn.reserve(result->rowsCount());
|
||||||
@@ -20,12 +17,6 @@ std::vector<IPropertyContents::Model> MySQLDatabase::GetPropertyModels(const LWO
|
|||||||
model.rotation.y = result->getFloat("ry");
|
model.rotation.y = result->getFloat("ry");
|
||||||
model.rotation.z = result->getFloat("rz");
|
model.rotation.z = result->getFloat("rz");
|
||||||
model.ugcId = result->getUInt64("ugc_id");
|
model.ugcId = result->getUInt64("ugc_id");
|
||||||
model.behaviors[0] = result->getInt("behavior_1");
|
|
||||||
model.behaviors[1] = result->getInt("behavior_2");
|
|
||||||
model.behaviors[2] = result->getInt("behavior_3");
|
|
||||||
model.behaviors[3] = result->getInt("behavior_4");
|
|
||||||
model.behaviors[4] = result->getInt("behavior_5");
|
|
||||||
|
|
||||||
toReturn.push_back(std::move(model));
|
toReturn.push_back(std::move(model));
|
||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
@@ -41,23 +32,21 @@ void MySQLDatabase::InsertNewPropertyModel(const LWOOBJID& propertyId, const IPr
|
|||||||
model.id, propertyId, model.ugcId == 0 ? std::nullopt : std::optional(model.ugcId), static_cast<uint32_t>(model.lot),
|
model.id, propertyId, model.ugcId == 0 ? std::nullopt : std::optional(model.ugcId), static_cast<uint32_t>(model.lot),
|
||||||
model.position.x, model.position.y, model.position.z, model.rotation.x, model.rotation.y, model.rotation.z, model.rotation.w,
|
model.position.x, model.position.y, model.position.z, model.rotation.x, model.rotation.y, model.rotation.z, model.rotation.w,
|
||||||
name, "", // Model description. TODO implement this.
|
name, "", // Model description. TODO implement this.
|
||||||
model.behaviors[0], // behavior 1
|
0, // behavior 1. TODO implement this.
|
||||||
model.behaviors[1], // behavior 2
|
0, // behavior 2. TODO implement this.
|
||||||
model.behaviors[2], // behavior 3
|
0, // behavior 3. TODO implement this.
|
||||||
model.behaviors[3], // behavior 4
|
0, // behavior 4. TODO implement this.
|
||||||
model.behaviors[4] // behavior 5
|
0 // behavior 5. TODO implement this.
|
||||||
);
|
);
|
||||||
} catch (sql::SQLException& e) {
|
} catch (sql::SQLException& e) {
|
||||||
LOG("Error inserting new property model: %s", e.what());
|
LOG("Error inserting new property model: %s", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) {
|
void MySQLDatabase::UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) {
|
||||||
ExecuteUpdate(
|
ExecuteUpdate(
|
||||||
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ?, "
|
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ? WHERE id = ?;",
|
||||||
"behavior_1 = ?, behavior_2 = ?, behavior_3 = ?, behavior_4 = ?, behavior_5 = ? WHERE id = ?;",
|
position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w, propertyId);
|
||||||
position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w,
|
|
||||||
behaviors[0].first, behaviors[1].first, behaviors[2].first, behaviors[3].first, behaviors[4].first, propertyId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::RemoveModel(const LWOOBJID& modelId) {
|
void MySQLDatabase::RemoveModel(const LWOOBJID& modelId) {
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
#include "MySQLDatabase.h"
|
|
||||||
|
|
||||||
void MySQLDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) {
|
|
||||||
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::DeleteUgcBuild(const LWOOBJID bigId) {
|
|
||||||
ExecuteDelete("DELETE FROM ugc_modular_build WHERE ugc_id = ?;", bigId);
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
SET(DDATABSE_DATABSES_SQLITE_SOURCES
|
|
||||||
"SQLiteDatabase.cpp"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(Tables)
|
|
||||||
|
|
||||||
foreach(file ${DDATABASES_DATABASES_SQLITE_TABLES_SOURCES})
|
|
||||||
set(DDATABSE_DATABSES_SQLITE_SOURCES ${DDATABSE_DATABSES_SQLITE_SOURCES} "Tables/${file}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
set(DDATABSE_DATABSES_SQLITE_SOURCES ${DDATABSE_DATABSES_SQLITE_SOURCES} PARENT_SCOPE)
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
#include "Database.h"
|
|
||||||
#include "Game.h"
|
|
||||||
#include "dConfig.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "dPlatforms.h"
|
|
||||||
#include "BinaryPathFinder.h"
|
|
||||||
|
|
||||||
// Static Variables
|
|
||||||
|
|
||||||
// Status Variables
|
|
||||||
namespace {
|
|
||||||
CppSQLite3DB* con = nullptr;
|
|
||||||
bool isConnected = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
void SQLiteDatabase::Connect() {
|
|
||||||
LOG("Using SQLite database");
|
|
||||||
con = new CppSQLite3DB();
|
|
||||||
const auto path = BinaryPathFinder::GetBinaryDir() / Game::config->GetValue("sqlite_database_path");
|
|
||||||
|
|
||||||
if (!std::filesystem::exists(path)) {
|
|
||||||
LOG("Creating sqlite path %s", path.string().c_str());
|
|
||||||
std::filesystem::create_directories(path.parent_path());
|
|
||||||
}
|
|
||||||
|
|
||||||
con->open(path.string().c_str());
|
|
||||||
isConnected = true;
|
|
||||||
|
|
||||||
// Make sure wal is enabled for the database.
|
|
||||||
con->execQuery("PRAGMA journal_mode = WAL;");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::Destroy(std::string source) {
|
|
||||||
if (!con) return;
|
|
||||||
|
|
||||||
if (source.empty()) LOG("Destroying SQLite connection!");
|
|
||||||
else LOG("Destroying SQLite connection from %s!", source.c_str());
|
|
||||||
|
|
||||||
con->close();
|
|
||||||
delete con;
|
|
||||||
con = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::ExecuteCustomQuery(const std::string_view query) {
|
|
||||||
con->compileStatement(query.data()).execDML();
|
|
||||||
}
|
|
||||||
|
|
||||||
CppSQLite3Statement SQLiteDatabase::CreatePreppedStmt(const std::string& query) {
|
|
||||||
return con->compileStatement(query.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::Commit() {
|
|
||||||
if (!con->IsAutoCommitOn()) con->compileStatement("COMMIT;").execDML();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SQLiteDatabase::GetAutoCommit() {
|
|
||||||
return con->IsAutoCommitOn();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::SetAutoCommit(bool value) {
|
|
||||||
if (value) {
|
|
||||||
if (GetAutoCommit()) con->compileStatement("BEGIN;").execDML();
|
|
||||||
} else {
|
|
||||||
if (!GetAutoCommit()) con->compileStatement("COMMIT;").execDML();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::DeleteCharacter(const uint32_t characterId) {
|
|
||||||
ExecuteDelete("DELETE FROM charxml WHERE id=?;", characterId);
|
|
||||||
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
|
||||||
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
|
||||||
ExecuteDelete("DELETE FROM leaderboard WHERE character_id=?;", characterId);
|
|
||||||
ExecuteDelete("DELETE FROM properties_contents WHERE property_id IN (SELECT id FROM properties WHERE owner_id=?);", characterId);
|
|
||||||
ExecuteDelete("DELETE FROM properties WHERE owner_id=?;", characterId);
|
|
||||||
ExecuteDelete("DELETE FROM ugc WHERE character_id=?;", characterId);
|
|
||||||
ExecuteDelete("DELETE FROM activity_log WHERE character_id=?;", characterId);
|
|
||||||
ExecuteDelete("DELETE FROM mail WHERE receiver_id=?;", characterId);
|
|
||||||
ExecuteDelete("DELETE FROM charinfo WHERE id=?;", characterId);
|
|
||||||
}
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
#ifndef SQLITEDATABASE_H
|
|
||||||
#define SQLITEDATABASE_H
|
|
||||||
|
|
||||||
#include "CppSQLite3.h"
|
|
||||||
|
|
||||||
#include "GameDatabase.h"
|
|
||||||
|
|
||||||
using PreppedStmtRef = CppSQLite3Statement&;
|
|
||||||
|
|
||||||
// Purposefully no definition for this to provide linker errors in the case someone tries to
|
|
||||||
// bind a parameter to a type that isn't defined.
|
|
||||||
template<typename ParamType>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const ParamType param);
|
|
||||||
|
|
||||||
// This is a function to set each parameter in a prepared statement.
|
|
||||||
// This is accomplished with a combination of parameter packing and Fold Expressions.
|
|
||||||
// The constexpr if statement is used to prevent the compiler from trying to call SetParam with 0 arguments.
|
|
||||||
template<typename... Args>
|
|
||||||
void SetParams(PreppedStmtRef stmt, Args&&... args) {
|
|
||||||
if constexpr (sizeof...(args) != 0) {
|
|
||||||
int i = 1;
|
|
||||||
(SetParam(stmt, i++, args), ...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SQLiteDatabase : public GameDatabase {
|
|
||||||
public:
|
|
||||||
void Connect() override;
|
|
||||||
void Destroy(std::string source = "") override;
|
|
||||||
|
|
||||||
void Commit() override;
|
|
||||||
bool GetAutoCommit() override;
|
|
||||||
void SetAutoCommit(bool value) override;
|
|
||||||
void ExecuteCustomQuery(const std::string_view query) override;
|
|
||||||
|
|
||||||
// Overloaded queries
|
|
||||||
std::optional<IServers::MasterInfo> GetMasterInfo() override;
|
|
||||||
|
|
||||||
std::vector<std::string> GetApprovedCharacterNames() override;
|
|
||||||
|
|
||||||
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
|
||||||
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
|
||||||
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
|
||||||
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
|
||||||
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
|
||||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
|
||||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::istringstream& lxfml) override;
|
|
||||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
|
||||||
void CreateMigrationHistoryTable() override;
|
|
||||||
bool IsMigrationRun(const std::string_view str) override;
|
|
||||||
void InsertMigration(const std::string_view str) override;
|
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
|
||||||
std::string GetCharacterXml(const uint32_t accountId) override;
|
|
||||||
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
|
||||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
|
||||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
|
||||||
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
|
||||||
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
|
||||||
void DeleteCharacter(const uint32_t characterId) override;
|
|
||||||
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
|
||||||
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
|
||||||
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
|
||||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
|
||||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
|
||||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
|
||||||
void UpdatePropertyModerationInfo(const IProperty::Info& info) override;
|
|
||||||
void UpdatePropertyDetails(const IProperty::Info& info) override;
|
|
||||||
void InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) override;
|
|
||||||
std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) override;
|
|
||||||
void RemoveUnreferencedUgcModels() override;
|
|
||||||
void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) override;
|
|
||||||
void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) override;
|
|
||||||
void RemoveModel(const LWOOBJID& modelId) override;
|
|
||||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
|
||||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
|
||||||
void InsertCheatDetection(const IPlayerCheatDetections::Info& info) override;
|
|
||||||
void InsertNewMail(const IMail::MailInfo& mail) override;
|
|
||||||
void InsertNewUgcModel(
|
|
||||||
std::istringstream& sd0Data,
|
|
||||||
const uint32_t blueprintId,
|
|
||||||
const uint32_t accountId,
|
|
||||||
const uint32_t characterId) override;
|
|
||||||
std::vector<IMail::MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
|
||||||
std::optional<IMail::MailInfo> GetMail(const uint64_t mailId) override;
|
|
||||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
|
||||||
void MarkMailRead(const uint64_t mailId) override;
|
|
||||||
void DeleteMail(const uint64_t mailId) override;
|
|
||||||
void ClaimMailItem(const uint64_t mailId) override;
|
|
||||||
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
|
||||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
|
||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
|
||||||
void SetMasterIp(const std::string_view ip, const uint32_t port) override;
|
|
||||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
|
||||||
void InsertDefaultPersistentId() override;
|
|
||||||
void UpdatePersistentId(const uint32_t id) override;
|
|
||||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
|
||||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
|
||||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
|
||||||
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
|
||||||
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
|
||||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
|
||||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
|
||||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
|
||||||
void AddBehavior(const IBehaviors::Info& info) override;
|
|
||||||
std::string GetBehavior(const int32_t behaviorId) override;
|
|
||||||
void RemoveBehavior(const int32_t characterId) override;
|
|
||||||
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
|
||||||
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override;
|
|
||||||
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override;
|
|
||||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
|
||||||
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
|
||||||
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
|
||||||
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
|
||||||
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
|
||||||
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
|
||||||
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
|
||||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
|
||||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
|
||||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
|
||||||
uint32_t GetAccountCount() override;
|
|
||||||
private:
|
|
||||||
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
|
|
||||||
|
|
||||||
// Generic query functions that can be used for any query.
|
|
||||||
// Return type may be different depending on the query, so it is up to the caller to check the return type.
|
|
||||||
// The first argument is the query string, and the rest are the parameters to bind to the query.
|
|
||||||
// The return type is a unique_ptr to the result set, which is deleted automatically when it goes out of scope
|
|
||||||
template<typename... Args>
|
|
||||||
inline std::pair<CppSQLite3Statement, CppSQLite3Query> ExecuteSelect(const std::string& query, Args&&... args) {
|
|
||||||
std::pair<CppSQLite3Statement, CppSQLite3Query> toReturn;
|
|
||||||
toReturn.first = CreatePreppedStmt(query);
|
|
||||||
SetParams(toReturn.first, std::forward<Args>(args)...);
|
|
||||||
DLU_SQL_TRY_CATCH_RETHROW(toReturn.second = toReturn.first.execQuery());
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
inline void ExecuteDelete(const std::string& query, Args&&... args) {
|
|
||||||
auto preppedStmt = CreatePreppedStmt(query);
|
|
||||||
SetParams(preppedStmt, std::forward<Args>(args)...);
|
|
||||||
DLU_SQL_TRY_CATCH_RETHROW(preppedStmt.execDML());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
inline int32_t ExecuteUpdate(const std::string& query, Args&&... args) {
|
|
||||||
auto preppedStmt = CreatePreppedStmt(query);
|
|
||||||
SetParams(preppedStmt, std::forward<Args>(args)...);
|
|
||||||
DLU_SQL_TRY_CATCH_RETHROW(return preppedStmt.execDML());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
inline int ExecuteInsert(const std::string& query, Args&&... args) {
|
|
||||||
auto preppedStmt = CreatePreppedStmt(query);
|
|
||||||
SetParams(preppedStmt, std::forward<Args>(args)...);
|
|
||||||
DLU_SQL_TRY_CATCH_RETHROW(return preppedStmt.execDML());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Below are each of the definitions of SetParam for each supported type.
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::string_view param) {
|
|
||||||
LOG("%s", param.data());
|
|
||||||
stmt.bind(index, param.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const char* param) {
|
|
||||||
LOG("%s", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::string param) {
|
|
||||||
LOG("%s", param.c_str());
|
|
||||||
stmt.bind(index, param.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int8_t param) {
|
|
||||||
LOG("%u", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint8_t param) {
|
|
||||||
LOG("%d", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int16_t param) {
|
|
||||||
LOG("%u", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint16_t param) {
|
|
||||||
LOG("%d", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint32_t param) {
|
|
||||||
LOG("%u", param);
|
|
||||||
stmt.bind(index, static_cast<int32_t>(param));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int32_t param) {
|
|
||||||
LOG("%d", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int64_t param) {
|
|
||||||
LOG("%llu", param);
|
|
||||||
stmt.bind(index, static_cast<sqlite_int64>(param));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint64_t param) {
|
|
||||||
LOG("%llu", param);
|
|
||||||
stmt.bind(index, static_cast<sqlite_int64>(param));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const float param) {
|
|
||||||
LOG("%f", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const double param) {
|
|
||||||
LOG("%f", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const bool param) {
|
|
||||||
LOG("%d", param);
|
|
||||||
stmt.bind(index, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::istream* param) {
|
|
||||||
LOG("Blob");
|
|
||||||
// This is the one time you will ever see me use const_cast.
|
|
||||||
std::stringstream stream;
|
|
||||||
stream << param->rdbuf();
|
|
||||||
stmt.bind(index, reinterpret_cast<const unsigned char*>(stream.str().c_str()), stream.str().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
|
||||||
if (param) {
|
|
||||||
LOG("%d", param.value());
|
|
||||||
stmt.bind(index, static_cast<int>(param.value()));
|
|
||||||
} else {
|
|
||||||
LOG("Null");
|
|
||||||
stmt.bindNull(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //!SQLITEDATABASE_H
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
#include "eGameMasterLevel.h"
|
|
||||||
#include "Database.h"
|
|
||||||
|
|
||||||
std::optional<IAccounts::Info> SQLiteDatabase::GetAccountInfo(const std::string_view username) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT * FROM accounts WHERE name = ? LIMIT 1", username);
|
|
||||||
|
|
||||||
if (result.eof()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
IAccounts::Info toReturn;
|
|
||||||
toReturn.id = result.getIntField("id");
|
|
||||||
toReturn.maxGmLevel = static_cast<eGameMasterLevel>(result.getIntField("gm_level"));
|
|
||||||
toReturn.bcryptPassword = result.getStringField("password");
|
|
||||||
toReturn.banned = result.getIntField("banned");
|
|
||||||
toReturn.locked = result.getIntField("locked");
|
|
||||||
toReturn.playKeyId = result.getIntField("play_key_id");
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) {
|
|
||||||
ExecuteUpdate("UPDATE accounts SET mute_expire = ? WHERE id = ?;", timeToUnmute, accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateAccountBan(const uint32_t accountId, const bool banned) {
|
|
||||||
ExecuteUpdate("UPDATE accounts SET banned = ? WHERE id = ?;", banned, accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) {
|
|
||||||
ExecuteUpdate("UPDATE accounts SET password = ? WHERE id = ?;", bcryptpassword, accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) {
|
|
||||||
ExecuteInsert("INSERT INTO accounts (name, password, gm_level) VALUES (?, ?, ?);", username, bcryptpassword, static_cast<int32_t>(eGameMasterLevel::OPERATOR));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) {
|
|
||||||
ExecuteUpdate("UPDATE accounts SET gm_level = ? WHERE id = ?;", static_cast<int32_t>(gmLevel), accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SQLiteDatabase::GetAccountCount() {
|
|
||||||
auto [_, res] = ExecuteSelect("SELECT COUNT(*) as count FROM accounts;");
|
|
||||||
if (res.eof()) return 0;
|
|
||||||
|
|
||||||
return res.getIntField("count");
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
void SQLiteDatabase::InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) {
|
|
||||||
ExecuteInsert("INSERT OR IGNORE INTO accounts_rewardcodes (account_id, rewardcode) VALUES (?, ?);", account_id, reward_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint32_t> SQLiteDatabase::GetRewardCodesByAccountID(const uint32_t account_id) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT rewardcode FROM accounts_rewardcodes WHERE account_id = ?;", account_id);
|
|
||||||
|
|
||||||
std::vector<uint32_t> toReturn;
|
|
||||||
while (!result.eof()) {
|
|
||||||
toReturn.push_back(result.getIntField("rewardcode"));
|
|
||||||
result.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
|
||||||
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
|
||||||
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#include "IBehaviors.h"
|
|
||||||
|
|
||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
void SQLiteDatabase::AddBehavior(const IBehaviors::Info& info) {
|
|
||||||
ExecuteInsert(
|
|
||||||
"INSERT INTO behaviors (behavior_info, character_id, behavior_id) VALUES (?, ?, ?) ON CONFLICT(behavior_id) DO UPDATE SET behavior_info = ?",
|
|
||||||
info.behaviorInfo, info.characterId, info.behaviorId, info.behaviorInfo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::RemoveBehavior(const int32_t behaviorId) {
|
|
||||||
ExecuteDelete("DELETE FROM behaviors WHERE behavior_id = ?", behaviorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SQLiteDatabase::GetBehavior(const int32_t behaviorId) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT behavior_info FROM behaviors WHERE behavior_id = ?", behaviorId);
|
|
||||||
return !result.eof() ? result.getStringField("behavior_info") : "";
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
void SQLiteDatabase::InsertNewBugReport(const IBugReports::Info& info) {
|
|
||||||
ExecuteInsert("INSERT INTO `bug_reports`(body, client_version, other_player_id, selection, reporter_id) VALUES (?, ?, ?, ?, ?)",
|
|
||||||
info.body, info.clientVersion, info.otherPlayer, info.selection, info.characterId);
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
set(DDATABASES_DATABASES_SQLITE_TABLES_SOURCES
|
|
||||||
"Accounts.cpp"
|
|
||||||
"AccountsRewardCodes.cpp"
|
|
||||||
"ActivityLog.cpp"
|
|
||||||
"Behaviors.cpp"
|
|
||||||
"BugReports.cpp"
|
|
||||||
"CharInfo.cpp"
|
|
||||||
"CharXml.cpp"
|
|
||||||
"CommandLog.cpp"
|
|
||||||
"Friends.cpp"
|
|
||||||
"IgnoreList.cpp"
|
|
||||||
"Leaderboard.cpp"
|
|
||||||
"Mail.cpp"
|
|
||||||
"MigrationHistory.cpp"
|
|
||||||
"ObjectIdTracker.cpp"
|
|
||||||
"PetNames.cpp"
|
|
||||||
"PlayerCheatDetections.cpp"
|
|
||||||
"PlayKeys.cpp"
|
|
||||||
"Property.cpp"
|
|
||||||
"PropertyContents.cpp"
|
|
||||||
"Servers.cpp"
|
|
||||||
"Ugc.cpp"
|
|
||||||
"UgcModularBuild.cpp"
|
|
||||||
PARENT_SCOPE
|
|
||||||
)
|
|
||||||
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
std::vector<std::string> SQLiteDatabase::GetApprovedCharacterNames() {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT name FROM charinfo;");
|
|
||||||
|
|
||||||
std::vector<std::string> toReturn;
|
|
||||||
|
|
||||||
while (!result.eof()) {
|
|
||||||
toReturn.push_back(result.getStringField("name"));
|
|
||||||
result.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> CharInfoFromQueryResult(CppSQLite3Query stmt) {
|
|
||||||
if (stmt.eof()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
ICharInfo::Info toReturn;
|
|
||||||
|
|
||||||
toReturn.id = stmt.getIntField("id");
|
|
||||||
toReturn.name = stmt.getStringField("name");
|
|
||||||
toReturn.pendingName = stmt.getStringField("pending_name");
|
|
||||||
toReturn.needsRename = stmt.getIntField("needs_rename");
|
|
||||||
toReturn.cloneId = stmt.getInt64Field("prop_clone_id");
|
|
||||||
toReturn.accountId = stmt.getIntField("account_id");
|
|
||||||
toReturn.permissionMap = static_cast<ePermissionMap>(stmt.getIntField("permission_map"));
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const uint32_t charId) {
|
|
||||||
return CharInfoFromQueryResult(
|
|
||||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId).second
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const std::string_view name) {
|
|
||||||
return CharInfoFromQueryResult(
|
|
||||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE name = ? LIMIT 1;", name).second
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint32_t> SQLiteDatabase::GetAccountCharacterIds(const uint32_t accountId) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
|
||||||
|
|
||||||
std::vector<uint32_t> toReturn;
|
|
||||||
while (!result.eof()) {
|
|
||||||
toReturn.push_back(result.getIntField("id"));
|
|
||||||
result.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
|
||||||
ExecuteInsert(
|
|
||||||
"INSERT INTO `charinfo`(`id`, `account_id`, `name`, `pending_name`, `needs_rename`, `last_login`, `prop_clone_id`) VALUES (?,?,?,?,?,?,(SELECT IFNULL(MAX(`prop_clone_id`), 0) + 1 FROM `charinfo`))",
|
|
||||||
info.id,
|
|
||||||
info.accountId,
|
|
||||||
info.name,
|
|
||||||
info.pendingName,
|
|
||||||
false,
|
|
||||||
static_cast<uint32_t>(time(NULL)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
|
||||||
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
|
||||||
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
|
||||||
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ?;", static_cast<uint32_t>(time(NULL)), characterId);
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
std::string SQLiteDatabase::GetCharacterXml(const uint32_t charId) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
|
||||||
|
|
||||||
if (result.eof()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.getStringField("xml_data");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) {
|
|
||||||
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
|
||||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
void SQLiteDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
|
||||||
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
std::vector<FriendData> SQLiteDatabase::GetFriendsList(const uint32_t charId) {
|
|
||||||
auto [_, friendsList] = ExecuteSelect(
|
|
||||||
R"QUERY(
|
|
||||||
SELECT fr.requested_player AS player, best_friend AS bff, ci.name AS name FROM
|
|
||||||
(
|
|
||||||
SELECT CASE
|
|
||||||
WHEN player_id = ? THEN friend_id
|
|
||||||
WHEN friend_id = ? THEN player_id
|
|
||||||
END AS requested_player, best_friend FROM friends
|
|
||||||
) AS fr
|
|
||||||
JOIN charinfo AS ci ON ci.id = fr.requested_player
|
|
||||||
WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?;
|
|
||||||
)QUERY", charId, charId, charId);
|
|
||||||
|
|
||||||
std::vector<FriendData> toReturn;
|
|
||||||
|
|
||||||
while (!friendsList.eof()) {
|
|
||||||
FriendData fd;
|
|
||||||
fd.friendID = friendsList.getIntField("player");
|
|
||||||
fd.isBestFriend = friendsList.getIntField("bff") == 3; // 0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
|
||||||
fd.friendName = friendsList.getStringField("name");
|
|
||||||
|
|
||||||
toReturn.push_back(fd);
|
|
||||||
friendsList.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> SQLiteDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
|
||||||
playerCharacterId,
|
|
||||||
friendCharacterId,
|
|
||||||
friendCharacterId,
|
|
||||||
playerCharacterId
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.eof()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
IFriends::BestFriendStatus toReturn;
|
|
||||||
toReturn.playerCharacterId = result.getIntField("player_id");
|
|
||||||
toReturn.friendCharacterId = result.getIntField("friend_id");
|
|
||||||
toReturn.bestFriendStatus = result.getIntField("best_friend");
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) {
|
|
||||||
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
|
||||||
bestFriendStatus,
|
|
||||||
playerCharacterId,
|
|
||||||
friendCharacterId,
|
|
||||||
friendCharacterId,
|
|
||||||
playerCharacterId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
|
||||||
ExecuteInsert("INSERT OR IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
|
||||||
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
|
||||||
playerCharacterId,
|
|
||||||
friendCharacterId,
|
|
||||||
friendCharacterId,
|
|
||||||
playerCharacterId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> SQLiteDatabase::GetIgnoreList(const uint32_t playerId) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> ignoreList;
|
|
||||||
|
|
||||||
while (!result.eof()) {
|
|
||||||
ignoreList.push_back(IIgnoreList::Info{ result.getStringField("name"), static_cast<uint32_t>(result.getIntField("ignore_id")) });
|
|
||||||
result.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ignoreList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
|
||||||
ExecuteInsert("INSERT OR IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
|
||||||
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
#include "Game.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "dConfig.h"
|
|
||||||
|
|
||||||
std::optional<uint32_t> SQLiteDatabase::GetDonationTotal(const uint32_t activityId) {
|
|
||||||
auto [_, donation_total] = ExecuteSelect("SELECT SUM(primaryScore) as donation_total FROM leaderboard WHERE game_id = ?;", activityId);
|
|
||||||
|
|
||||||
if (donation_total.eof()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return donation_total.getIntField("donation_total");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> ProcessQuery(CppSQLite3Query& rows) {
|
|
||||||
std::vector<ILeaderboard::Entry> entries;
|
|
||||||
|
|
||||||
while (!rows.eof()) {
|
|
||||||
auto& entry = entries.emplace_back();
|
|
||||||
|
|
||||||
entry.charId = rows.getIntField("character_id");
|
|
||||||
entry.lastPlayedTimestamp = rows.getIntField("lp_unix");
|
|
||||||
entry.primaryScore = rows.getFloatField("primaryScore");
|
|
||||||
entry.secondaryScore = rows.getFloatField("secondaryScore");
|
|
||||||
entry.tertiaryScore = rows.getFloatField("tertiaryScore");
|
|
||||||
entry.numWins = rows.getIntField("numWins");
|
|
||||||
entry.numTimesPlayed = rows.getIntField("timesPlayed");
|
|
||||||
entry.name = rows.getStringField("char_name");
|
|
||||||
// entry.ranking is never set because its calculated in leaderboard in code.
|
|
||||||
rows.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> SQLiteDatabase::GetDescendingLeaderboard(const uint32_t activityId) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore DESC, tertiaryScore DESC, last_played ASC;", activityId);
|
|
||||||
return ProcessQuery(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> SQLiteDatabase::GetAscendingLeaderboard(const uint32_t activityId) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore ASC, secondaryscore ASC, tertiaryScore ASC, last_played ASC;", activityId);
|
|
||||||
return ProcessQuery(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> SQLiteDatabase::GetAgsLeaderboard(const uint32_t activityId) {
|
|
||||||
auto query = Game::config->GetValue("classic_survival_scoring") != "1" ?
|
|
||||||
"SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore DESC, tertiaryScore DESC, last_played ASC;" :
|
|
||||||
"SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY secondaryscore DESC, primaryscore DESC, tertiaryScore DESC, last_played ASC;";
|
|
||||||
auto [_, result] = ExecuteSelect(query, activityId);
|
|
||||||
return ProcessQuery(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> SQLiteDatabase::GetNsLeaderboard(const uint32_t activityId) {
|
|
||||||
auto [_, result] = ExecuteSelect("SELECT *, CAST(strftime('%s', last_played) as INT) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore ASC, tertiaryScore DESC, last_played ASC;", activityId);
|
|
||||||
return ProcessQuery(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
|
||||||
ExecuteInsert("INSERT INTO leaderboard (primaryScore, secondaryScore, tertiaryScore, character_id, game_id, last_played) VALUES (?,?,?,?,?,CURRENT_TIMESTAMP) ;",
|
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
|
||||||
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;",
|
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ILeaderboard::Score> SQLiteDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
|
|
||||||
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
|
||||||
auto [_, res] = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
|
||||||
if (!res.eof()) {
|
|
||||||
toReturn = ILeaderboard::Score{
|
|
||||||
.primaryScore = static_cast<float>(res.getFloatField("primaryScore")),
|
|
||||||
.secondaryScore = static_cast<float>(res.getFloatField("secondaryScore")),
|
|
||||||
.tertiaryScore = static_cast<float>(res.getFloatField("tertiaryScore"))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t gameId) {
|
|
||||||
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) {
|
|
||||||
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
void SQLiteDatabase::InsertNewMail(const IMail::MailInfo& mail) {
|
|
||||||
ExecuteInsert(
|
|
||||||
"INSERT INTO `mail` "
|
|
||||||
"(`sender_id`, `sender_name`, `receiver_id`, `receiver_name`, `time_sent`, `subject`, `body`, `attachment_id`, `attachment_lot`, `attachment_subkey`, `attachment_count`, `was_read`)"
|
|
||||||
" VALUES (?,?,?,?,?,?,?,?,?,?,?,0)",
|
|
||||||
mail.senderId,
|
|
||||||
mail.senderUsername,
|
|
||||||
mail.receiverId,
|
|
||||||
mail.recipient,
|
|
||||||
static_cast<uint32_t>(time(NULL)),
|
|
||||||
mail.subject,
|
|
||||||
mail.body,
|
|
||||||
mail.itemID,
|
|
||||||
mail.itemLOT,
|
|
||||||
0,
|
|
||||||
mail.itemCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<IMail::MailInfo> SQLiteDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
|
||||||
auto [_, res] = ExecuteSelect(
|
|
||||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
|
||||||
" FROM mail WHERE receiver_id=? limit ?;",
|
|
||||||
characterId, numberOfMail);
|
|
||||||
|
|
||||||
std::vector<IMail::MailInfo> toReturn;
|
|
||||||
|
|
||||||
while (!res.eof()) {
|
|
||||||
IMail::MailInfo mail;
|
|
||||||
mail.id = res.getInt64Field("id");
|
|
||||||
mail.subject = res.getStringField("subject");
|
|
||||||
mail.body = res.getStringField("body");
|
|
||||||
mail.senderUsername = res.getStringField("sender_name");
|
|
||||||
mail.itemID = res.getIntField("attachment_id");
|
|
||||||
mail.itemLOT = res.getIntField("attachment_lot");
|
|
||||||
mail.itemSubkey = res.getIntField("attachment_subkey");
|
|
||||||
mail.itemCount = res.getIntField("attachment_count");
|
|
||||||
mail.timeSent = res.getInt64Field("time_sent");
|
|
||||||
mail.wasRead = res.getIntField("was_read");
|
|
||||||
|
|
||||||
toReturn.push_back(std::move(mail));
|
|
||||||
res.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<IMail::MailInfo> SQLiteDatabase::GetMail(const uint64_t mailId) {
|
|
||||||
auto [_, res] = ExecuteSelect("SELECT attachment_lot, attachment_count FROM mail WHERE id=? LIMIT 1;", mailId);
|
|
||||||
|
|
||||||
if (res.eof()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMail::MailInfo toReturn;
|
|
||||||
toReturn.itemLOT = res.getIntField("attachment_lot");
|
|
||||||
toReturn.itemCount = res.getIntField("attachment_count");
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SQLiteDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
|
||||||
auto [_, res] = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
|
||||||
|
|
||||||
if (res.eof()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.getIntField("number_unread");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::MarkMailRead(const uint64_t mailId) {
|
|
||||||
ExecuteUpdate("UPDATE mail SET was_read=1 WHERE id=?;", mailId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::ClaimMailItem(const uint64_t mailId) {
|
|
||||||
ExecuteUpdate("UPDATE mail SET attachment_lot=0 WHERE id=?;", mailId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::DeleteMail(const uint64_t mailId) {
|
|
||||||
ExecuteDelete("DELETE FROM mail WHERE id=?;", mailId);
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#include "SQLiteDatabase.h"
|
|
||||||
|
|
||||||
void SQLiteDatabase::CreateMigrationHistoryTable() {
|
|
||||||
ExecuteInsert("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP);");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SQLiteDatabase::IsMigrationRun(const std::string_view str) {
|
|
||||||
return !ExecuteSelect("SELECT name FROM migration_history WHERE name = ?;", str).second.eof();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SQLiteDatabase::InsertMigration(const std::string_view str) {
|
|
||||||
ExecuteInsert("INSERT INTO migration_history (name) VALUES (?);", str);
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user