mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 03:37:08 -06:00
Compare commits
116 Commits
v2.3.0
...
unique-ptr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90e2b5c6b7 | ||
|
|
42367deeca | ||
|
|
fced6d753a | ||
|
|
15dc5feeb5 | ||
|
|
a60865cd19 | ||
|
|
77b42daca1 | ||
|
|
ba364800fe | ||
|
|
e1c20192f7 | ||
|
|
0f8c5b436d | ||
| 53242ad5d5 | |||
|
|
a8919c8c14 | ||
|
|
5ff121612e | ||
| 34618607c3 | |||
|
|
02b76adb7a | ||
|
|
3beb414b55 | ||
|
|
1dadeeb36f | ||
|
|
aa7c3b9061 | ||
|
|
1644d9448d | ||
|
|
8b56b0b7ba | ||
|
|
4a1c289fb1 | ||
|
|
32a1e5ece5 | ||
|
|
7fcbb9507b | ||
|
|
730533c690 | ||
|
|
129d9fd0b9 | ||
|
|
ec4ec2133b | ||
|
|
218a3f2d0d | ||
|
|
c37a0c86c1 | ||
|
|
9e7ef8c4ee | ||
|
|
ec501831e6 | ||
|
|
5b8d2b19a3 | ||
| 17f81d13a3 | |||
|
|
53877a0bc3 | ||
|
|
83f8646936 | ||
|
|
d8b86072d4 | ||
|
|
112c2367cc | ||
|
|
c7dd8205a4 | ||
|
|
652f42ccf2 | ||
|
|
fedd039e00 | ||
|
|
84d7c65717 | ||
|
|
adc9cd2876 | ||
|
|
008e2d4dce | ||
|
|
677e7c1097 | ||
|
|
628ac9807e | ||
|
|
de3fe93100 | ||
|
|
af943278fb | ||
|
|
bfe6900c26 | ||
|
|
0d218fc5c7 | ||
|
|
102e3556cf | ||
|
|
33a8efdd22 | ||
|
|
8d54db7851 | ||
|
|
6213aed8e5 | ||
|
|
d57c5101f4 | ||
|
|
6be65569de | ||
|
|
94b9731a2b | ||
|
|
aaf446fe6e | ||
|
|
2c70f1503c | ||
|
|
49b4748ed3 | ||
|
|
ffeb0108d0 | ||
|
|
c3f6ef5a1d | ||
|
|
999995b2fb | ||
|
|
84fff7c380 | ||
|
|
59c4b35479 | ||
|
|
f2d72e7ed5 | ||
|
|
b648b43c4d | ||
|
|
2628470482 | ||
|
|
f82a82f254 | ||
|
|
9400ee1dc0 | ||
|
|
54b8c25754 | ||
|
|
b984cd6a0b | ||
|
|
bcf1058759 | ||
|
|
6ad6e930c7 | ||
|
|
fee0238e79 | ||
|
|
1454fcd003 | ||
|
|
af651f0d63 | ||
| ff38503597 | |||
| 3f22bf5cc0 | |||
| 9d5d2a68ee | |||
| 1a14c29c39 | |||
| 2ef45bd7ee | |||
| b56d077892 | |||
|
|
a54600b41e | ||
|
|
342da927f5 | ||
|
|
01086d05c8 | ||
|
|
cce5755366 | ||
|
|
e966d3a644 | ||
|
|
9328021339 | ||
|
|
d1134fdd62 | ||
|
|
efa658bc31 | ||
|
|
e59525d2ae | ||
|
|
0348db72a5 | ||
|
|
debc2a96e2 | ||
| 86f335d64b | |||
| 8ca05241f2 | |||
|
|
8ae1a8ff7c | ||
|
|
f0960d48b2 | ||
|
|
dc430d9758 | ||
|
|
dea10c6d56 | ||
|
|
ed00551982 | ||
|
|
d6cac65a8d | ||
|
|
d8f079cb1b | ||
|
|
db2d4f02b5 | ||
|
|
00f36f3f28 | ||
|
|
a50b256689 | ||
|
|
b3548de7da | ||
|
|
387c37505c | ||
|
|
0c4108e730 | ||
|
|
fd1c6ab2ea | ||
|
|
f2bf9a2a28 | ||
|
|
c8e0bb0db0 | ||
|
|
d9d262d3f1 | ||
|
|
d0a5678290 | ||
|
|
35321b22d9 | ||
|
|
8837b110ab | ||
|
|
09a8c99f3e | ||
|
|
e3b108e00e | ||
|
|
9f382aca42 |
@@ -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=fasle
|
cpp_indent_comment=false
|
||||||
|
|||||||
10
.env.example
10
.env.example
@@ -3,12 +3,20 @@ 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
|
||||||
# grab a "SHA 256-bit Key" from here: https://keygen.io/
|
# generate a "SHA 256-bit Key" from here: https://gchq.github.io/CyberChef/#recipe=Pseudo-Random_Number_Generator(256,'Hex')
|
||||||
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@v3
|
- uses: actions/checkout@v4
|
||||||
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@v1.1
|
uses: microsoft/setup-msbuild@v2
|
||||||
with:
|
with:
|
||||||
vs-version: '[17,18)'
|
vs-version: '[17,18)'
|
||||||
msbuild-architecture: x64
|
msbuild-architecture: x64
|
||||||
@@ -33,21 +33,20 @@ jobs:
|
|||||||
- name: cmake
|
- name: cmake
|
||||||
uses: lukka/run-cmake@v10
|
uses: lukka/run-cmake@v10
|
||||||
with:
|
with:
|
||||||
configurePreset: "ci-${{matrix.os}}"
|
workflowPreset: "ci-${{matrix.os}}"
|
||||||
buildPreset: "ci-${{matrix.os}}"
|
|
||||||
testPreset: "ci-${{matrix.os}}"
|
|
||||||
- name: artifacts
|
- name: artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
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/vanity/
|
build/*/*.dylib
|
||||||
build/navmeshes/
|
build/*/vanity/
|
||||||
build/migrations/
|
build/*/navmeshes/
|
||||||
build/*.dcf
|
build/*/migrations/
|
||||||
!build/*.pdb
|
build/*/*.dcf
|
||||||
!build/d*/
|
!build/*/*.pdb
|
||||||
|
!build/*/d*/
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -6,7 +6,6 @@ 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/
|
||||||
@@ -95,6 +94,7 @@ ipch/
|
|||||||
|
|
||||||
# Exceptions:
|
# Exceptions:
|
||||||
CMakeSettings.json
|
CMakeSettings.json
|
||||||
|
CMakeUserPresets.json
|
||||||
*.vcxproj
|
*.vcxproj
|
||||||
*.filters
|
*.filters
|
||||||
*.cmake
|
*.cmake
|
||||||
@@ -122,4 +122,7 @@ docker/__pycache__
|
|||||||
docker-compose.override.yml
|
docker-compose.override.yml
|
||||||
|
|
||||||
!*Test.bin
|
!*Test.bin
|
||||||
|
|
||||||
|
# CMake scripts
|
||||||
!cmake/*
|
!cmake/*
|
||||||
|
!cmake/toolchains/*
|
||||||
|
|||||||
124
CMakeLists.txt
124
CMakeLists.txt
@@ -1,9 +1,20 @@
|
|||||||
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(CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
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_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
||||||
@@ -55,35 +66,37 @@ 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)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wuninitialized -fPIC")
|
add_link_options("-Wl,-rpath,$ORIGIN/")
|
||||||
|
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)
|
||||||
|
|
||||||
if(NOT APPLE)
|
# For all except Clang and Apple Clang
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -lstdc++fs")
|
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
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")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
|
add_link_options("-export-dynamic")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${GGDB})
|
if(${GGDB})
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
|
add_compile_options("-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
|
# Also disable non-portable MSVC volatile behavior
|
||||||
add_compile_options("/wd4267" "/utf-8" "/volatile:iso")
|
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})
|
||||||
@@ -103,31 +116,39 @@ 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" "blocklist.dcf")
|
||||||
message(STATUS "Checking resource file integrity")
|
message(STATUS "Checking resource file integrity")
|
||||||
|
|
||||||
include(Utils)
|
include(Utils)
|
||||||
UpdateConfigOption(${PROJECT_BINARY_DIR}/authconfig.ini "port" "auth_server_port")
|
UpdateConfigOption(${DLU_CONFIG_DIR}/authconfig.ini "port" "auth_server_port")
|
||||||
UpdateConfigOption(${PROJECT_BINARY_DIR}/chatconfig.ini "port" "chat_server_port")
|
UpdateConfigOption(${DLU_CONFIG_DIR}/chatconfig.ini "port" "chat_server_port")
|
||||||
UpdateConfigOption(${PROJECT_BINARY_DIR}/masterconfig.ini "port" "master_server_port")
|
UpdateConfigOption(${DLU_CONFIG_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 ${PROJECT_BINARY_DIR}/${resource_file})
|
if(EXISTS ${DLU_CONFIG_DIR}/${resource_file})
|
||||||
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
|
file(SIZE ${DLU_CONFIG_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} ${PROJECT_BINARY_DIR}/${resource_file}
|
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${DLU_CONFIG_DIR}/${resource_file}
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
message(STATUS "Moved " ${resource_file} " to project binary directory")
|
message(STATUS "Moved " ${resource_file} " to DLU config 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 ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
|
file(READ ${DLU_CONFIG_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 "")
|
||||||
@@ -154,16 +175,18 @@ 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})
|
||||||
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
# For backwards compatibility with older setup versions, dont add this option.
|
||||||
set(line_to_add ${line_to_add} ${line})
|
if(NOT ${variable_name} MATCHES "database_type")
|
||||||
|
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 ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
|
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n" ${line_to_append})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
|
file(APPEND ${DLU_CONFIG_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})
|
||||||
@@ -193,21 +216,8 @@ foreach(file ${VANITY_FILES})
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Move our migrations for MasterServer to run
|
# Move our migrations for MasterServer to run
|
||||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/dlu/)
|
file(REMOVE_RECURSE ${PROJECT_BINARY_DIR}/migrations)
|
||||||
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql)
|
file(COPY ${CMAKE_SOURCE_DIR}/migrations DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
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)
|
||||||
@@ -230,14 +240,15 @@ include_directories(
|
|||||||
"tests/dGameTests"
|
"tests/dGameTests"
|
||||||
"tests/dGameTests/dComponentsTests"
|
"tests/dGameTests/dComponentsTests"
|
||||||
|
|
||||||
SYSTEM "thirdparty/magic_enum/include/magic_enum"
|
SYSTEM
|
||||||
SYSTEM "thirdparty/raknet/Source"
|
"thirdparty/magic_enum/include/magic_enum"
|
||||||
SYSTEM "thirdparty/tinyxml2"
|
"thirdparty/raknet/Source"
|
||||||
SYSTEM "thirdparty/recastnavigation"
|
"thirdparty/tinyxml2"
|
||||||
SYSTEM "thirdparty/SQLite"
|
"thirdparty/recastnavigation"
|
||||||
SYSTEM "thirdparty/cpplinq"
|
"thirdparty/SQLite"
|
||||||
SYSTEM "thirdparty/cpp-httplib"
|
"thirdparty/cpplinq"
|
||||||
SYSTEM "thirdparty/MD5"
|
"thirdparty/cpp-httplib"
|
||||||
|
"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)
|
||||||
@@ -246,10 +257,17 @@ if(APPLE)
|
|||||||
include_directories("/usr/local/include/")
|
include_directories("/usr/local/include/")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Add linking directories:
|
# Set warning flags
|
||||||
if (UNIX)
|
if(MSVC)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast -Werror") # Warning flags
|
# 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()
|
endif()
|
||||||
|
|
||||||
|
# Add linking directories:
|
||||||
file(
|
file(
|
||||||
GLOB HEADERS_DZONEMANAGER
|
GLOB HEADERS_DZONEMANAGER
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
@@ -284,7 +302,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" "MariaDB::ConnCpp" "magic_enum")
|
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
|
||||||
|
|
||||||
# Add platform specific common libraries
|
# Add platform specific common libraries
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
|
|||||||
@@ -1,128 +1,638 @@
|
|||||||
{
|
{
|
||||||
"version": 3,
|
"version": 6,
|
||||||
"cmakeMinimumRequired": {
|
"cmakeMinimumRequired": {
|
||||||
"major": 3,
|
"major": 3,
|
||||||
"minor": 14,
|
"minor": 25,
|
||||||
"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": "ci-ubuntu-22.04",
|
|
||||||
"displayName": "CI configure step for Ubuntu",
|
|
||||||
"description": "Same as default, Used in GitHub actions workflow",
|
|
||||||
"inherits": "default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-macos-13",
|
|
||||||
"displayName": "CI configure step for MacOS",
|
|
||||||
"description": "Same as default, Used in GitHub actions workflow",
|
|
||||||
"inherits": "default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-windows-2022",
|
|
||||||
"displayName": "CI configure step for Windows",
|
|
||||||
"description": "Set architecture to 64-bit (b/c RakNet)",
|
|
||||||
"inherits": "default",
|
|
||||||
"generator": "Visual Studio 17 2022",
|
|
||||||
"architecture": {
|
|
||||||
"value": "x64"
|
|
||||||
},
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "windows-default",
|
|
||||||
"inherits": "ci-windows-2022",
|
|
||||||
"displayName": "Windows only Configure Settings",
|
|
||||||
"description": "Sets build and install directories",
|
|
||||||
"generator": "Ninja",
|
|
||||||
"architecture": {
|
|
||||||
"value": "x64",
|
|
||||||
"strategy": "external"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"buildPresets": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"configurePreset": "default",
|
|
||||||
"displayName": "Default Build",
|
|
||||||
"description": "Default Build",
|
|
||||||
"jobs": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-windows-2022",
|
|
||||||
"configurePreset": "ci-windows-2022",
|
|
||||||
"displayName": "Windows CI Build",
|
|
||||||
"description": "This preset is used by the CI build on windows",
|
|
||||||
"configuration": "RelWithDebInfo",
|
|
||||||
"jobs": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-ubuntu-22.04",
|
|
||||||
"configurePreset": "ci-ubuntu-22.04",
|
|
||||||
"displayName": "Linux CI Build",
|
|
||||||
"description": "This preset is used by the CI build on linux",
|
|
||||||
"jobs": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-macos-13",
|
|
||||||
"configurePreset": "ci-macos-13",
|
|
||||||
"displayName": "MacOS CI Build",
|
|
||||||
"description": "This preset is used by the CI build on MacOS",
|
|
||||||
"jobs": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"testPresets": [
|
|
||||||
{
|
|
||||||
"name": "ci-ubuntu-22.04",
|
|
||||||
"configurePreset": "ci-ubuntu-22.04",
|
|
||||||
"displayName": "CI Tests on Linux",
|
|
||||||
"description": "Runs all tests on a linux configuration",
|
|
||||||
"execution": {
|
|
||||||
"jobs": 2
|
|
||||||
},
|
},
|
||||||
"output": {
|
{
|
||||||
"outputOnFailure": true
|
"name": "debug-config",
|
||||||
}
|
"hidden": true,
|
||||||
},
|
"cacheVariables": {
|
||||||
{
|
"CMAKE_BUILD_TYPE": "Debug"
|
||||||
"name": "ci-macos-13",
|
|
||||||
"configurePreset": "ci-macos-13",
|
|
||||||
"displayName": "CI Tests on MacOS",
|
|
||||||
"description": "Runs all tests on a Mac configuration",
|
|
||||||
"execution": {
|
|
||||||
"jobs": 2
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"outputOnFailure": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ci-windows-2022",
|
|
||||||
"configurePreset": "ci-windows-2022",
|
|
||||||
"displayName": "CI Tests on windows",
|
|
||||||
"description": "Runs all tests on a windows configuration",
|
|
||||||
"configuration": "RelWithDebInfo",
|
|
||||||
"execution": {
|
|
||||||
"jobs": 2
|
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"outputOnFailure": true
|
|
||||||
},
|
|
||||||
"filter": {
|
|
||||||
"exclude": {
|
|
||||||
"name": "((example)|(minigzip))+"
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "relwithdebinfo-config",
|
||||||
|
"hidden": true,
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release-config",
|
||||||
|
"hidden": true,
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "clang-config",
|
||||||
|
"hidden": true,
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-clang.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gnu-config",
|
||||||
|
"hidden": true,
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-gnu.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-msvc",
|
||||||
|
"inherits": "default",
|
||||||
|
"displayName": "[Multi] Windows (MSVC)",
|
||||||
|
"description": "Set architecture to 64-bit (b/c RakNet)",
|
||||||
|
"generator": "Visual Studio 17 2022",
|
||||||
|
"binaryDir": "${sourceDir}/build/msvc",
|
||||||
|
"architecture": {
|
||||||
|
"value": "x64"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Windows"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-default",
|
||||||
|
"inherits": "windows-msvc",
|
||||||
|
"displayName": "Windows only Configure Settings",
|
||||||
|
"description": "Sets build and install directories",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Windows"
|
||||||
|
},
|
||||||
|
"architecture": {
|
||||||
|
"value": "x64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-config",
|
||||||
|
"inherits": "default",
|
||||||
|
"hidden": true,
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Linux"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-clang-debug",
|
||||||
|
"inherits": [
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-msvc-debug",
|
||||||
|
"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",
|
||||||
|
"configuration": "Debug"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-msvc-relwithdebinfo",
|
||||||
|
"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",
|
||||||
|
"configuration": "RelWithDebInfo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-msvc-release",
|
||||||
|
"inherits": "default",
|
||||||
|
"configurePreset": "windows-msvc",
|
||||||
|
"displayName": "[Release] Windows (MSVC)",
|
||||||
|
"description": "This preset is used to build in release mode using the MSVC toolchain on Windows",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
39
README.md
39
README.md
@@ -13,21 +13,33 @@ 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.
|
||||||
|
|
||||||
## Step by step walkthrough for a single-player server
|
## Setting up a single player server
|
||||||
If you would like a setup for a single player server only on a Windows machine, use the [Native Windows Setup Guide by HailStorm](https://gist.github.com/HailStorm32/169df65a47a104199b5cc57d10fa57de) and skip this README.
|
* If you don't know what WSL is, skip this warning.
|
||||||
|
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.
|
||||||
|
|
||||||
## Steps to setup server
|
<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>
|
||||||
|
|
||||||
|
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)
|
||||||
@@ -39,6 +51,13 @@ If you would like a setup for a single player server only on a Windows machine,
|
|||||||
* [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)
|
||||||
|
|
||||||
@@ -266,8 +285,8 @@ systemctl stop darkflame.service
|
|||||||
journalctl -xeu darkflame.service
|
journalctl -xeu darkflame.service
|
||||||
```
|
```
|
||||||
|
|
||||||
### First admin user
|
### First user or adding more 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!
|
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!
|
||||||
|
|
||||||
### 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**
|
||||||
@@ -371,7 +390,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 like <https://keygen.io>
|
- Use a password generator <https://gchq.github.io/CyberChef/#recipe=Pseudo-Random_Number_Generator(256,'Hex')>
|
||||||
- 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,8 +6,7 @@ mkdir -p build
|
|||||||
cd build
|
cd build
|
||||||
|
|
||||||
# Run cmake to generate make files
|
# Run cmake to generate make files
|
||||||
cmake ..
|
cmake -DCMAKE_BUILD_TYPE="Release" ..
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
|
|||||||
14
cmake/toolchains/linux-clang.cmake
Normal file
14
cmake/toolchains/linux-clang.cmake
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# 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")
|
||||||
11
cmake/toolchains/linux-gnu.cmake
Normal file
11
cmake/toolchains/linux-gnu.cmake
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# 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 "eServerMessageType.h"
|
#include "MessageType/Server.h"
|
||||||
#include "eAuthMessageType.h"
|
#include "MessageType/Auth.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 (sql::SQLException& ex) {
|
} catch (std::exception& 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<eServerMessageType>(packet->data[3]) == eServerMessageType::VERSION_CONFIRM) {
|
if (static_cast<MessageType::Server>(packet->data[3]) == MessageType::Server::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<eAuthMessageType>(packet->data[3]) == eAuthMessageType::LOGIN_REQUEST) {
|
if (static_cast<MessageType::Auth>(packet->data[3]) == MessageType::Auth::LOGIN_REQUEST) {
|
||||||
AuthPackets::HandleLoginRequest(Game::server, packet);
|
AuthPackets::HandleLoginRequest(Game::server, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "ChatIgnoreList.h"
|
#include "ChatIgnoreList.h"
|
||||||
#include "PlayerContainer.h"
|
#include "PlayerContainer.h"
|
||||||
#include "eChatMessageType.h"
|
#include "MessageType/Chat.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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receivingPlayer);
|
bitStream.Write(receivingPlayer);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatMessageType.h"
|
#include "MessageType/Chat.h"
|
||||||
#include "eClientMessageType.h"
|
#include "MessageType/Client.h"
|
||||||
#include "eGameMessageType.h"
|
#include "MessageType/Game.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "ChatPackets.h"
|
#include "ChatPackets.h"
|
||||||
@@ -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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(playerID);
|
bitStream.Write(playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::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());
|
||||||
@@ -368,10 +368,10 @@ void ChatPacketHandler::HandleWho(Packet* packet) {
|
|||||||
bool online = player;
|
bool online = player;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(request.requestor);
|
bitStream.Write(request.requestor);
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::WHO_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::WHO_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(online);
|
bitStream.Write<uint8_t>(online);
|
||||||
bitStream.Write(player.zoneID.GetMapID());
|
bitStream.Write(player.zoneID.GetMapID());
|
||||||
bitStream.Write(player.zoneID.GetInstanceID());
|
bitStream.Write(player.zoneID.GetInstanceID());
|
||||||
@@ -391,10 +391,10 @@ void ChatPacketHandler::HandleShowAll(Packet* packet) {
|
|||||||
if (!sender) return;
|
if (!sender) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(request.requestor);
|
bitStream.Write(request.requestor);
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::SHOW_ALL_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::SHOW_ALL_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(!request.displayZoneData && !request.displayIndividualPlayers);
|
bitStream.Write<uint8_t>(!request.displayZoneData && !request.displayIndividualPlayers);
|
||||||
bitStream.Write(Game::playerContainer.GetPlayerCount());
|
bitStream.Write(Game::playerContainer.GetPlayerCount());
|
||||||
bitStream.Write(Game::playerContainer.GetSimCount());
|
bitStream.Write(Game::playerContainer.GetSimCount());
|
||||||
@@ -416,7 +416,7 @@ void ChatPacketHandler::HandleShowAll(Packet* packet) {
|
|||||||
SEND_PACKET;
|
SEND_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::HandleChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
@@ -428,7 +428,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 +436,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 +457,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 +484,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 +515,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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(routeTo.playerID);
|
bitStream.Write(routeTo.playerID);
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::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 +757,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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::TEAM_INVITE);
|
||||||
|
|
||||||
bitStream.Write(LUWString(sender.playerName.c_str()));
|
bitStream.Write(LUWString(sender.playerName.c_str()));
|
||||||
bitStream.Write(sender.playerID);
|
bitStream.Write(sender.playerID);
|
||||||
@@ -772,14 +772,14 @@ void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerD
|
|||||||
|
|
||||||
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, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::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(eGameMessageType::TEAM_INVITE_CONFIRM);
|
bitStream.Write(MessageType::Game::TEAM_INVITE_CONFIRM);
|
||||||
|
|
||||||
bitStream.Write(bLeaderIsFreeTrial);
|
bitStream.Write(bLeaderIsFreeTrial);
|
||||||
bitStream.Write(i64LeaderID);
|
bitStream.Write(i64LeaderID);
|
||||||
@@ -799,14 +799,14 @@ void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool b
|
|||||||
|
|
||||||
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, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::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(eGameMessageType::TEAM_GET_STATUS_RESPONSE);
|
bitStream.Write(MessageType::Game::TEAM_GET_STATUS_RESPONSE);
|
||||||
|
|
||||||
bitStream.Write(i64LeaderID);
|
bitStream.Write(i64LeaderID);
|
||||||
bitStream.Write(i64LeaderZoneID);
|
bitStream.Write(i64LeaderZoneID);
|
||||||
@@ -824,14 +824,14 @@ void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64L
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
|
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::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(eGameMessageType::TEAM_SET_LEADER);
|
bitStream.Write(MessageType::Game::TEAM_SET_LEADER);
|
||||||
|
|
||||||
bitStream.Write(i64PlayerID);
|
bitStream.Write(i64PlayerID);
|
||||||
|
|
||||||
@@ -841,14 +841,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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::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(eGameMessageType::TEAM_ADD_PLAYER);
|
bitStream.Write(MessageType::Game::TEAM_ADD_PLAYER);
|
||||||
|
|
||||||
bitStream.Write(bIsFreeTrial);
|
bitStream.Write(bIsFreeTrial);
|
||||||
bitStream.Write(bLocal);
|
bitStream.Write(bLocal);
|
||||||
@@ -870,14 +870,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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::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(eGameMessageType::TEAM_REMOVE_PLAYER);
|
bitStream.Write(MessageType::Game::TEAM_REMOVE_PLAYER);
|
||||||
|
|
||||||
bitStream.Write(bDisband);
|
bitStream.Write(bDisband);
|
||||||
bitStream.Write(bIsKicked);
|
bitStream.Write(bIsKicked);
|
||||||
@@ -896,14 +896,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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::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(eGameMessageType::TEAM_SET_OFF_WORLD_FLAG);
|
bitStream.Write(MessageType::Game::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 +930,11 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
|
|||||||
[bool] - is FTP*/
|
[bool] - is FTP*/
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(friendData.playerID);
|
bitStream.Write(friendData.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::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 +967,11 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::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 +981,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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
// Portion that will get routed:
|
// Portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::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 +1004,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, eChatMessageType::WORLD_ROUTE_PACKET);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::REMOVE_FRIEND_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
||||||
bitStream.Write(LUWString(personToRemove));
|
bitStream.Write(LUWString(personToRemove));
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "PlayerContainer.h"
|
#include "PlayerContainer.h"
|
||||||
#include "ChatPacketHandler.h"
|
#include "ChatPacketHandler.h"
|
||||||
#include "eChatMessageType.h"
|
#include "MessageType/Chat.h"
|
||||||
#include "eWorldMessageType.h"
|
#include "MessageType/World.h"
|
||||||
#include "ChatIgnoreList.h"
|
#include "ChatIgnoreList.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ int main(int argc, char** argv) {
|
|||||||
//Connect to the MySQL Database
|
//Connect to the MySQL Database
|
||||||
try {
|
try {
|
||||||
Database::Connect();
|
Database::Connect();
|
||||||
} catch (sql::SQLException& ex) {
|
} catch (std::exception& 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 +108,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,6 +179,7 @@ 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) {
|
} else if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
||||||
@@ -189,154 +190,154 @@ void HandlePacket(Packet* packet) {
|
|||||||
inStream.SetReadOffset(BYTES_TO_BITS(1));
|
inStream.SetReadOffset(BYTES_TO_BITS(1));
|
||||||
|
|
||||||
eConnectionType connection;
|
eConnectionType connection;
|
||||||
eChatMessageType chatMessageID;
|
MessageType::Chat chatMessageID;
|
||||||
|
|
||||||
inStream.Read(connection);
|
inStream.Read(connection);
|
||||||
if (connection != eConnectionType::CHAT) return;
|
if (connection != eConnectionType::CHAT) return;
|
||||||
inStream.Read(chatMessageID);
|
inStream.Read(chatMessageID);
|
||||||
|
|
||||||
switch (chatMessageID) {
|
switch (chatMessageID) {
|
||||||
case eChatMessageType::GM_MUTE:
|
case MessageType::Chat::GM_MUTE:
|
||||||
Game::playerContainer.MuteUpdate(packet);
|
Game::playerContainer.MuteUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::CREATE_TEAM:
|
case MessageType::Chat::CREATE_TEAM:
|
||||||
Game::playerContainer.CreateTeamServer(packet);
|
Game::playerContainer.CreateTeamServer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::GET_FRIENDS_LIST:
|
case MessageType::Chat::GET_FRIENDS_LIST:
|
||||||
ChatPacketHandler::HandleFriendlistRequest(packet);
|
ChatPacketHandler::HandleFriendlistRequest(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::GET_IGNORE_LIST:
|
case MessageType::Chat::GET_IGNORE_LIST:
|
||||||
ChatIgnoreList::GetIgnoreList(packet);
|
ChatIgnoreList::GetIgnoreList(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::ADD_IGNORE:
|
case MessageType::Chat::ADD_IGNORE:
|
||||||
ChatIgnoreList::AddIgnore(packet);
|
ChatIgnoreList::AddIgnore(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::REMOVE_IGNORE:
|
case MessageType::Chat::REMOVE_IGNORE:
|
||||||
ChatIgnoreList::RemoveIgnore(packet);
|
ChatIgnoreList::RemoveIgnore(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::TEAM_GET_STATUS:
|
case MessageType::Chat::TEAM_GET_STATUS:
|
||||||
ChatPacketHandler::HandleTeamStatusRequest(packet);
|
ChatPacketHandler::HandleTeamStatusRequest(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::ADD_FRIEND_REQUEST:
|
case MessageType::Chat::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 eChatMessageType::ADD_FRIEND_RESPONSE:
|
case MessageType::Chat::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 eChatMessageType::REMOVE_FRIEND:
|
case MessageType::Chat::REMOVE_FRIEND:
|
||||||
ChatPacketHandler::HandleRemoveFriend(packet);
|
ChatPacketHandler::HandleRemoveFriend(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::GENERAL_CHAT_MESSAGE:
|
case MessageType::Chat::GENERAL_CHAT_MESSAGE:
|
||||||
ChatPacketHandler::HandleChatMessage(packet);
|
ChatPacketHandler::HandleChatMessage(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::PRIVATE_CHAT_MESSAGE:
|
case MessageType::Chat::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 eChatMessageType::TEAM_INVITE:
|
case MessageType::Chat::TEAM_INVITE:
|
||||||
ChatPacketHandler::HandleTeamInvite(packet);
|
ChatPacketHandler::HandleTeamInvite(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::TEAM_INVITE_RESPONSE:
|
case MessageType::Chat::TEAM_INVITE_RESPONSE:
|
||||||
ChatPacketHandler::HandleTeamInviteResponse(packet);
|
ChatPacketHandler::HandleTeamInviteResponse(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::TEAM_LEAVE:
|
case MessageType::Chat::TEAM_LEAVE:
|
||||||
ChatPacketHandler::HandleTeamLeave(packet);
|
ChatPacketHandler::HandleTeamLeave(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::TEAM_SET_LEADER:
|
case MessageType::Chat::TEAM_SET_LEADER:
|
||||||
ChatPacketHandler::HandleTeamPromote(packet);
|
ChatPacketHandler::HandleTeamPromote(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::TEAM_KICK:
|
case MessageType::Chat::TEAM_KICK:
|
||||||
ChatPacketHandler::HandleTeamKick(packet);
|
ChatPacketHandler::HandleTeamKick(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::TEAM_SET_LOOT:
|
case MessageType::Chat::TEAM_SET_LOOT:
|
||||||
ChatPacketHandler::HandleTeamLootOption(packet);
|
ChatPacketHandler::HandleTeamLootOption(packet);
|
||||||
break;
|
break;
|
||||||
case eChatMessageType::GMLEVEL_UPDATE:
|
case MessageType::Chat::GMLEVEL_UPDATE:
|
||||||
ChatPacketHandler::HandleGMLevelUpdate(packet);
|
ChatPacketHandler::HandleGMLevelUpdate(packet);
|
||||||
break;
|
break;
|
||||||
case eChatMessageType::LOGIN_SESSION_NOTIFY:
|
case MessageType::Chat::LOGIN_SESSION_NOTIFY:
|
||||||
Game::playerContainer.InsertPlayer(packet);
|
Game::playerContainer.InsertPlayer(packet);
|
||||||
break;
|
break;
|
||||||
case eChatMessageType::GM_ANNOUNCE:{
|
case MessageType::Chat::GM_ANNOUNCE:{
|
||||||
// we just forward this packet to every connected server
|
// we just forward this packet to every connected server
|
||||||
inStream.ResetReadPointer();
|
inStream.ResetReadPointer();
|
||||||
Game::server->Send(inStream, packet->systemAddress, true); // send to everyone except origin
|
Game::server->Send(inStream, packet->systemAddress, true); // send to everyone except origin
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case eChatMessageType::UNEXPECTED_DISCONNECT:
|
case MessageType::Chat::UNEXPECTED_DISCONNECT:
|
||||||
Game::playerContainer.RemovePlayer(packet);
|
Game::playerContainer.RemovePlayer(packet);
|
||||||
break;
|
break;
|
||||||
case eChatMessageType::WHO:
|
case MessageType::Chat::WHO:
|
||||||
ChatPacketHandler::HandleWho(packet);
|
ChatPacketHandler::HandleWho(packet);
|
||||||
break;
|
break;
|
||||||
case eChatMessageType::SHOW_ALL:
|
case MessageType::Chat::SHOW_ALL:
|
||||||
ChatPacketHandler::HandleShowAll(packet);
|
ChatPacketHandler::HandleShowAll(packet);
|
||||||
break;
|
break;
|
||||||
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
|
case MessageType::Chat::USER_CHANNEL_CHAT_MESSAGE:
|
||||||
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
|
case MessageType::Chat::WORLD_DISCONNECT_REQUEST:
|
||||||
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
|
case MessageType::Chat::WORLD_PROXIMITY_RESPONSE:
|
||||||
case eChatMessageType::WORLD_PARCEL_RESPONSE:
|
case MessageType::Chat::WORLD_PARCEL_RESPONSE:
|
||||||
case eChatMessageType::TEAM_MISSED_INVITE_CHECK:
|
case MessageType::Chat::TEAM_MISSED_INVITE_CHECK:
|
||||||
case eChatMessageType::GUILD_CREATE:
|
case MessageType::Chat::GUILD_CREATE:
|
||||||
case eChatMessageType::GUILD_INVITE:
|
case MessageType::Chat::GUILD_INVITE:
|
||||||
case eChatMessageType::GUILD_INVITE_RESPONSE:
|
case MessageType::Chat::GUILD_INVITE_RESPONSE:
|
||||||
case eChatMessageType::GUILD_LEAVE:
|
case MessageType::Chat::GUILD_LEAVE:
|
||||||
case eChatMessageType::GUILD_KICK:
|
case MessageType::Chat::GUILD_KICK:
|
||||||
case eChatMessageType::GUILD_GET_STATUS:
|
case MessageType::Chat::GUILD_GET_STATUS:
|
||||||
case eChatMessageType::GUILD_GET_ALL:
|
case MessageType::Chat::GUILD_GET_ALL:
|
||||||
case eChatMessageType::BLUEPRINT_MODERATED:
|
case MessageType::Chat::BLUEPRINT_MODERATED:
|
||||||
case eChatMessageType::BLUEPRINT_MODEL_READY:
|
case MessageType::Chat::BLUEPRINT_MODEL_READY:
|
||||||
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
|
case MessageType::Chat::PROPERTY_READY_FOR_APPROVAL:
|
||||||
case eChatMessageType::PROPERTY_MODERATION_CHANGED:
|
case MessageType::Chat::PROPERTY_MODERATION_CHANGED:
|
||||||
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED:
|
case MessageType::Chat::PROPERTY_BUILDMODE_CHANGED:
|
||||||
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED_REPORT:
|
case MessageType::Chat::PROPERTY_BUILDMODE_CHANGED_REPORT:
|
||||||
case eChatMessageType::MAIL:
|
case MessageType::Chat::MAIL:
|
||||||
case eChatMessageType::WORLD_INSTANCE_LOCATION_REQUEST:
|
case MessageType::Chat::WORLD_INSTANCE_LOCATION_REQUEST:
|
||||||
case eChatMessageType::REPUTATION_UPDATE:
|
case MessageType::Chat::REPUTATION_UPDATE:
|
||||||
case eChatMessageType::SEND_CANNED_TEXT:
|
case MessageType::Chat::SEND_CANNED_TEXT:
|
||||||
case eChatMessageType::CHARACTER_NAME_CHANGE_REQUEST:
|
case MessageType::Chat::CHARACTER_NAME_CHANGE_REQUEST:
|
||||||
case eChatMessageType::CSR_REQUEST:
|
case MessageType::Chat::CSR_REQUEST:
|
||||||
case eChatMessageType::CSR_REPLY:
|
case MessageType::Chat::CSR_REPLY:
|
||||||
case eChatMessageType::GM_KICK:
|
case MessageType::Chat::GM_KICK:
|
||||||
case eChatMessageType::WORLD_ROUTE_PACKET:
|
case MessageType::Chat::WORLD_ROUTE_PACKET:
|
||||||
case eChatMessageType::GET_ZONE_POPULATIONS:
|
case MessageType::Chat::GET_ZONE_POPULATIONS:
|
||||||
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
|
case MessageType::Chat::REQUEST_MINIMUM_CHAT_MODE:
|
||||||
case eChatMessageType::MATCH_REQUEST:
|
case MessageType::Chat::MATCH_REQUEST:
|
||||||
case eChatMessageType::UGCMANIFEST_REPORT_MISSING_FILE:
|
case MessageType::Chat::UGCMANIFEST_REPORT_MISSING_FILE:
|
||||||
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
|
case MessageType::Chat::UGCMANIFEST_REPORT_DONE_FILE:
|
||||||
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
case MessageType::Chat::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
||||||
case eChatMessageType::UGCC_REQUEST:
|
case MessageType::Chat::UGCC_REQUEST:
|
||||||
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
case MessageType::Chat::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
||||||
case eChatMessageType::ACHIEVEMENT_NOTIFY:
|
case MessageType::Chat::ACHIEVEMENT_NOTIFY:
|
||||||
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
case MessageType::Chat::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
||||||
case eChatMessageType::PLAYER_READY:
|
case MessageType::Chat::PLAYER_READY:
|
||||||
case eChatMessageType::GET_DONATION_TOTAL:
|
case MessageType::Chat::GET_DONATION_TOTAL:
|
||||||
case eChatMessageType::UPDATE_DONATION:
|
case MessageType::Chat::UPDATE_DONATION:
|
||||||
case eChatMessageType::PRG_CSR_COMMAND:
|
case MessageType::Chat::PRG_CSR_COMMAND:
|
||||||
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
|
case MessageType::Chat::HEARTBEAT_REQUEST_FROM_WORLD:
|
||||||
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
|
case MessageType::Chat::UPDATE_FREE_TRIAL_STATUS:
|
||||||
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
|
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "ChatPackets.h"
|
#include "ChatPackets.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "eChatMessageType.h"
|
#include "MessageType/Chat.h"
|
||||||
|
|
||||||
void PlayerContainer::Initialize() {
|
void PlayerContainer::Initialize() {
|
||||||
m_MaxNumberOfBestFriends =
|
m_MaxNumberOfBestFriends =
|
||||||
@@ -36,16 +36,19 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
data.playerID = playerId;
|
data.playerID = playerId;
|
||||||
|
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
inStream.Read<uint32_t>(len);
|
if (!inStream.Read<uint32_t>(len)) return;
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
if (len > 33) {
|
||||||
char character; inStream.Read<char>(character);
|
LOG("Received a really long player name, probably a fake packet %i.", len);
|
||||||
data.playerName += character;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
inStream.Read(data.zoneID);
|
data.playerName.resize(len);
|
||||||
inStream.Read(data.muteExpire);
|
inStream.ReadAlignedBytes(reinterpret_cast<unsigned char*>(data.playerName.data()), len);
|
||||||
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);
|
||||||
@@ -122,6 +125,11 @@ 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);
|
||||||
@@ -140,14 +148,13 @@ 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, eChatMessageType::GM_MUTE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::GM_MUTE);
|
||||||
|
|
||||||
bitStream.Write(player);
|
bitStream.Write(player);
|
||||||
bitStream.Write(time);
|
bitStream.Write(time);
|
||||||
@@ -354,7 +361,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, eChatMessageType::TEAM_GET_STATUS);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::TEAM_GET_STATUS);
|
||||||
|
|
||||||
bitStream.Write(team->teamID);
|
bitStream.Write(team->teamID);
|
||||||
bitStream.Write(deleteTeam);
|
bitStream.Write(deleteTeam);
|
||||||
|
|||||||
@@ -9,73 +9,54 @@
|
|||||||
* AMF3 Deserializer written by EmosewaMC
|
* AMF3 Deserializer written by EmosewaMC
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream& inStream) {
|
std::unique_ptr<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:
|
||||||
returnValue = new AMFBaseValue();
|
return std::make_unique<AMFBaseValue>();
|
||||||
break;
|
case eAmf::Null:
|
||||||
}
|
return std::make_unique<AMFNullValue>();
|
||||||
|
case eAmf::False:
|
||||||
case eAmf::Null: {
|
return std::make_unique<AMFBoolValue>(false);
|
||||||
returnValue = new AMFNullValue();
|
case eAmf::True:
|
||||||
break;
|
return std::make_unique<AMFBoolValue>(true);
|
||||||
}
|
case eAmf::Integer:
|
||||||
|
return ReadAmfInteger(inStream);
|
||||||
case eAmf::False: {
|
case eAmf::Double:
|
||||||
returnValue = new AMFBoolValue(false);
|
return ReadAmfDouble(inStream);
|
||||||
break;
|
case eAmf::String:
|
||||||
}
|
return ReadAmfString(inStream);
|
||||||
|
case eAmf::Array:
|
||||||
case eAmf::True: {
|
return ReadAmfArray(inStream);
|
||||||
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:
|
||||||
case eAmf::Dictionary: {
|
[[fallthrough]];
|
||||||
|
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) {
|
||||||
@@ -118,14 +99,14 @@ const std::string AMFDeserialize::ReadString(RakNet::BitStream& inStream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) {
|
std::unique_ptr<AMFDoubleValue> AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) {
|
||||||
double value;
|
double value;
|
||||||
inStream.Read<double>(value);
|
inStream.Read<double>(value);
|
||||||
return new AMFDoubleValue(value);
|
return std::make_unique<AMFDoubleValue>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) {
|
std::unique_ptr<AMFArrayValue> AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) {
|
||||||
auto arrayValue = new AMFArrayValue();
|
auto arrayValue = std::make_unique<AMFArrayValue>();
|
||||||
|
|
||||||
// Read size of dense array
|
// Read size of dense array
|
||||||
const auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
const auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
||||||
@@ -143,10 +124,10 @@ AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) {
|
|||||||
return arrayValue;
|
return arrayValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) {
|
std::unique_ptr<AMFStringValue> AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) {
|
||||||
return new AMFStringValue(ReadString(inStream));
|
return std::make_unique<AMFStringValue>(ReadString(inStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) {
|
std::unique_ptr<AMFIntValue> AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) {
|
||||||
return new AMFIntValue(ReadU29(inStream));
|
return std::make_unique<AMFIntValue>(ReadU29(inStream)); // NOTE: NARROWING CONVERSION FROM UINT TO INT. IS THIS INTENDED?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
AMFBaseValue* Read(RakNet::BitStream& inStream);
|
std::unique_ptr<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
|
||||||
*/
|
*/
|
||||||
AMFBaseValue* ReadAmfDouble(RakNet::BitStream& inStream);
|
static std::unique_ptr<AMFDoubleValue> 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
|
||||||
*/
|
*/
|
||||||
AMFBaseValue* ReadAmfArray(RakNet::BitStream& inStream);
|
std::unique_ptr<AMFArrayValue> 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
|
||||||
*/
|
*/
|
||||||
AMFBaseValue* ReadAmfString(RakNet::BitStream& inStream);
|
std::unique_ptr<AMFStringValue> 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
|
||||||
*/
|
*/
|
||||||
AMFBaseValue* ReadAmfInteger(RakNet::BitStream& inStream);
|
static std::unique_ptr<AMFIntValue> 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,27 +105,14 @@ 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 = std::unordered_map<std::string, AMFBaseValue*>;
|
using AMFAssociative =
|
||||||
using AMFDense = std::vector<AMFBaseValue*>;
|
std::unordered_map<std::string, std::unique_ptr<AMFBaseValue>, GeneralUtils::transparent_string_hash, std::equal_to<>>;
|
||||||
|
|
||||||
|
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
|
||||||
*/
|
*/
|
||||||
@@ -151,30 +138,32 @@ 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& key, const ValueType value) {
|
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string_view 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()) {
|
||||||
val = new AMFValue<ValueType>(value);
|
auto newVal = std::make_unique<AMFValue<ValueType>>(value);
|
||||||
m_Associative.emplace(key, val);
|
val = newVal.get();
|
||||||
|
m_Associative.emplace(key, std::move(newVal));
|
||||||
} else {
|
} else {
|
||||||
val = dynamic_cast<AMFValue<ValueType>*>(element->second);
|
val = dynamic_cast<AMFValue<ValueType>*>(element->second.get());
|
||||||
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& key) {
|
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string_view 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()) {
|
||||||
val = new AMFArrayValue();
|
auto newVal = std::make_unique<AMFArrayValue>();
|
||||||
m_Associative.emplace(key, val);
|
val = newVal.get();
|
||||||
|
m_Associative.emplace(key, std::move(newVal));
|
||||||
} else {
|
} else {
|
||||||
val = dynamic_cast<AMFArrayValue*>(element->second);
|
val = dynamic_cast<AMFArrayValue*>(element->second.get());
|
||||||
found = false;
|
found = false;
|
||||||
}
|
}
|
||||||
return std::make_pair(val, found);
|
return std::make_pair(val, found);
|
||||||
@@ -182,15 +171,13 @@ 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);
|
||||||
val = new AMFArrayValue();
|
m_Dense.at(index) = std::make_unique<AMFArrayValue>();
|
||||||
m_Dense.at(index) = val;
|
|
||||||
inserted = true;
|
inserted = true;
|
||||||
}
|
}
|
||||||
return std::make_pair(dynamic_cast<AMFArrayValue*>(m_Dense.at(index)), inserted);
|
return std::make_pair(dynamic_cast<AMFArrayValue*>(m_Dense.at(index).get()), inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -205,15 +192,13 @@ 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);
|
||||||
val = new AMFValue<ValueType>(value);
|
m_Dense.at(index) = std::make_unique<AMFValue<ValueType>>(value);
|
||||||
m_Dense.at(index) = val;
|
|
||||||
inserted = true;
|
inserted = true;
|
||||||
}
|
}
|
||||||
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(m_Dense.at(index)), inserted);
|
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(m_Dense.at(index).get()), inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,13 +210,12 @@ 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& key, AMFBaseValue* const value) {
|
void Insert(const std::string_view key, std::unique_ptr<AMFBaseValue> 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) {
|
||||||
delete element->second;
|
element->second = std::move(value);
|
||||||
element->second = value;
|
|
||||||
} else {
|
} else {
|
||||||
m_Associative.emplace(key, value);
|
m_Associative.emplace(key, std::move(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,14 +228,11 @@ 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, AMFBaseValue* const value) {
|
void Insert(const size_t index, std::unique_ptr<AMFBaseValue> 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) = value;
|
m_Dense.at(index) = std::move(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -279,8 +260,7 @@ 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) delete it->second;
|
if (deleteValue) m_Associative.erase(it);
|
||||||
m_Associative.erase(it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +270,6 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,16 +278,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& key) const {
|
[[nodiscard]] AMFArrayValue* GetArray(const std::string_view 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) : nullptr;
|
return it != m_Associative.cend() ? dynamic_cast<AMFArrayValue*>(it->second.get()) : 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)) : nullptr;
|
return index < m_Dense.size() ? dynamic_cast<AMFArrayValue*>(m_Dense.at(index).get()) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string& key) {
|
[[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string_view key) {
|
||||||
return static_cast<AMFArrayValue*>(Insert(key).first);
|
return static_cast<AMFArrayValue*>(Insert(key).first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,17 +309,17 @@ public:
|
|||||||
* @return The AMFValue
|
* @return The AMFValue
|
||||||
*/
|
*/
|
||||||
template <typename AmfType>
|
template <typename AmfType>
|
||||||
[[nodiscard]] AMFValue<AmfType>* Get(const std::string& key) const {
|
[[nodiscard]] AMFValue<AmfType>* Get(const std::string_view 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) :
|
dynamic_cast<AMFValue<AmfType>*>(it->second.get()) :
|
||||||
nullptr;
|
nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get from the array but dont cast it
|
// Get from the array but dont cast it
|
||||||
[[nodiscard]] AMFBaseValue* Get(const std::string& key) const {
|
[[nodiscard]] AMFBaseValue* Get(const std::string_view 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 : nullptr;
|
return it != m_Associative.cend() ? it->second.get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -355,13 +334,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)) :
|
dynamic_cast<AMFValue<AmfType>*>(m_Dense.at(index).get()) :
|
||||||
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) : nullptr;
|
return index < m_Dense.size() ? m_Dense.at(index).get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -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 (sql::SQLException exception) {
|
} catch (std::exception& 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,7 +37,6 @@ 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)
|
||||||
|
|||||||
@@ -201,7 +201,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;
|
||||||
|
|||||||
@@ -129,6 +129,29 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string_view folder);
|
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string_view 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>
|
||||||
concept Enum = std::is_enum_v<T>;
|
concept Enum = std::is_enum_v<T>;
|
||||||
|
|||||||
92
dCommon/Implementation.h
Normal file
92
dCommon/Implementation.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#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) = 0;
|
virtual void WriteToPacket(RakNet::BitStream& packet) const = 0;
|
||||||
|
|
||||||
virtual const std::u16string& GetKey() = 0;
|
virtual const std::u16string& GetKey() const = 0;
|
||||||
|
|
||||||
virtual eLDFType GetValueType() = 0;
|
virtual eLDFType GetValueType() const = 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) = 0;
|
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) const = 0;
|
||||||
|
|
||||||
virtual std::string GetValueAsString() = 0;
|
virtual std::string GetValueAsString() const = 0;
|
||||||
|
|
||||||
virtual LDFBaseData* Copy() = 0;
|
virtual LDFBaseData* Copy() const = 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) {
|
void WriteKey(RakNet::BitStream& packet) const {
|
||||||
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) {
|
void WriteValue(RakNet::BitStream& packet) const {
|
||||||
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) { return this->value; }
|
const T& GetValue(void) const { 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) { return ""; }
|
std::string GetValueString(void) const { 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) override {
|
void WriteToPacket(RakNet::BitStream& packet) const 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) override { return this->key; }
|
const std::u16string& GetKey(void) const 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) override { return LDF_TYPE_UNKNOWN; }
|
eLDFType GetValueType(void) const 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) override {
|
std::string GetString(const bool includeKey = true, const bool includeTypeId = true) const 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() override {
|
std::string GetValueAsString() const override {
|
||||||
return this->GetValueString();
|
return this->GetValueString();
|
||||||
}
|
}
|
||||||
|
|
||||||
LDFBaseData* Copy() override {
|
LDFBaseData* Copy() const 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) { return LDF_TYPE_UTF_16; };
|
template<> inline eLDFType LDFData<std::u16string>::GetValueType(void) const { return LDF_TYPE_UTF_16; };
|
||||||
template<> inline eLDFType LDFData<int32_t>::GetValueType(void) { return LDF_TYPE_S32; };
|
template<> inline eLDFType LDFData<int32_t>::GetValueType(void) const { return LDF_TYPE_S32; };
|
||||||
template<> inline eLDFType LDFData<float>::GetValueType(void) { return LDF_TYPE_FLOAT; };
|
template<> inline eLDFType LDFData<float>::GetValueType(void) const { return LDF_TYPE_FLOAT; };
|
||||||
template<> inline eLDFType LDFData<double>::GetValueType(void) { return LDF_TYPE_DOUBLE; };
|
template<> inline eLDFType LDFData<double>::GetValueType(void) const { return LDF_TYPE_DOUBLE; };
|
||||||
template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) { return LDF_TYPE_U32; };
|
template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) const { return LDF_TYPE_U32; };
|
||||||
template<> inline eLDFType LDFData<bool>::GetValueType(void) { return LDF_TYPE_BOOLEAN; };
|
template<> inline eLDFType LDFData<bool>::GetValueType(void) const { return LDF_TYPE_BOOLEAN; };
|
||||||
template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) { return LDF_TYPE_U64; };
|
template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) const { return LDF_TYPE_U64; };
|
||||||
template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) { return LDF_TYPE_OBJID; };
|
template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) const { return LDF_TYPE_OBJID; };
|
||||||
template<> inline eLDFType LDFData<std::string>::GetValueType(void) { return LDF_TYPE_UTF_8; };
|
template<> inline eLDFType LDFData<std::string>::GetValueType(void) const { 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) {
|
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) const {
|
||||||
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) {
|
|||||||
|
|
||||||
// The specialized version for bool
|
// The specialized version for bool
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) {
|
inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) const {
|
||||||
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) {
|
|||||||
|
|
||||||
// The specialized version for std::string (UTF-8)
|
// The specialized version for std::string (UTF-8)
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) {
|
inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) const {
|
||||||
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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline std::string LDFData<std::u16string>::GetValueString() {
|
template<> inline std::string LDFData<std::u16string>::GetValueString() const {
|
||||||
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline std::string LDFData<int32_t>::GetValueString() { return std::to_string(this->value); }
|
template<> inline std::string LDFData<int32_t>::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<float>::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<double>::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<uint32_t>::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<bool>::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<uint64_t>::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<LWOOBJID>::GetValueString() const { return std::to_string(this->value); }
|
||||||
|
|
||||||
template<> inline std::string LDFData<std::string>::GetValueString() { return this->value; }
|
template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; }
|
||||||
|
|
||||||
#endif //!__LDFFORMAT__H__
|
#endif //!__LDFFORMAT__H__
|
||||||
|
|||||||
73
dCommon/Observable.h
Normal file
73
dCommon/Observable.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#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,6 +1,7 @@
|
|||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "BinaryPathFinder.h"
|
#include "BinaryPathFinder.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|||||||
13
dCommon/dEnums/MessageType/Auth.h
Normal file
13
dCommon/dEnums/MessageType/Auth.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
}
|
||||||
78
dCommon/dEnums/MessageType/Chat.h
Normal file
78
dCommon/dEnums/MessageType/Chat.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#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,
|
||||||
|
};
|
||||||
|
}
|
||||||
74
dCommon/dEnums/MessageType/Client.h
Normal file
74
dCommon/dEnums/MessageType/Client.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
}
|
||||||
1612
dCommon/dEnums/MessageType/Game.h
Normal file
1612
dCommon/dEnums/MessageType/Game.h
Normal file
File diff suppressed because it is too large
Load Diff
34
dCommon/dEnums/MessageType/Master.h
Normal file
34
dCommon/dEnums/MessageType/Master.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
}
|
||||||
11
dCommon/dEnums/MessageType/Server.h
Normal file
11
dCommon/dEnums/MessageType/Server.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace MessageType {
|
||||||
|
//! The Internal Server Packet Identifiers
|
||||||
|
enum class Server : uint32_t {
|
||||||
|
VERSION_CONFIRM = 0,
|
||||||
|
DISCONNECT_NOTIFY,
|
||||||
|
GENERAL_NOTIFY
|
||||||
|
};
|
||||||
|
}
|
||||||
49
dCommon/dEnums/MessageType/World.h
Normal file
49
dCommon/dEnums/MessageType/World.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#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 "eClientMessageType.h"
|
#include "MessageType/Client.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, eClientMessageType::GAME_MSG);
|
#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::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);
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
#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,7 +15,8 @@ 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
|
||||||
UP_TO_DATE, // will become SPEED_BASE
|
SPEED_BASE,
|
||||||
|
UP_TO_DATE, // will become NJ_JAYMISSIONS
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ECHARACTERVERSION__H__
|
#endif //!__ECHARACTERVERSION__H__
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
#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,
|
|
||||||
// CUSTOM DLU MESSAGE ID FOR INTERNAL USE
|
|
||||||
CREATE_TEAM,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__ECHATMESSAGETYPE__H__
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
#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__
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,9 @@
|
|||||||
#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
|
||||||
@@ -56,4 +59,10 @@ 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__
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
#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__
|
|
||||||
11
dCommon/dEnums/ePropertySortType.h
Normal file
11
dCommon/dEnums/ePropertySortType.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#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
|
||||||
21
dCommon/dEnums/eReponseMoveItemBetweenInventoryTypeCode.h
Normal file
21
dCommon/dEnums/eReponseMoveItemBetweenInventoryTypeCode.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#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__
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#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__
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#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, // 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<eWorldMessageType> {
|
|
||||||
static constexpr int min = 0;
|
|
||||||
static constexpr int max = 91;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__EWORLDMESSAGETYPE__H__
|
|
||||||
@@ -2,6 +2,12 @@ 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,15 +8,28 @@ 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"
|
"ITables" PRIVATE "MySQL" "SQLite" "TestSQL"
|
||||||
"${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
|
||||||
PUBLIC MariaDB::ConnCpp
|
INTERFACE dCommon
|
||||||
INTERFACE dCommon)
|
PRIVATE sqlite3 MariaDB::ConnCpp)
|
||||||
|
|
||||||
# Glob together all headers that need to be precompiled
|
# Glob together all headers that need to be precompiled
|
||||||
file(
|
file(
|
||||||
|
|||||||
@@ -2,22 +2,46 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "MySQLDatabase.h"
|
|
||||||
#include "DluAssert.h"
|
#include "DluAssert.h"
|
||||||
|
|
||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
#pragma warning (disable:4251) //Disables SQL warnings
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
|
|
||||||
namespace {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
database = new MySQLDatabase();
|
const auto databaseType = GetMigrationFolder();
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,3 +62,8 @@ 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,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <conncpp.hpp>
|
|
||||||
|
|
||||||
#include "GameDatabase.h"
|
#include "GameDatabase.h"
|
||||||
|
|
||||||
@@ -9,4 +8,10 @@ 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,14 +23,11 @@
|
|||||||
#include "IActivityLog.h"
|
#include "IActivityLog.h"
|
||||||
#include "IIgnoreList.h"
|
#include "IIgnoreList.h"
|
||||||
#include "IAccountsRewardCodes.h"
|
#include "IAccountsRewardCodes.h"
|
||||||
|
#include "IBehaviors.h"
|
||||||
namespace sql {
|
#include "IUgcModularBuild.h"
|
||||||
class Statement;
|
|
||||||
class PreparedStatement;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (sql::SQLException& ex) { LOG("SQL Error: %s", ex.what()); throw; } } while(0)
|
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (std::exception& 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
|
||||||
@@ -40,14 +37,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,6 +33,11 @@ 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__
|
||||||
|
|||||||
22
dDatabase/GameDatabase/ITables/IBehaviors.h
Normal file
22
dDatabase/GameDatabase/ITables/IBehaviors.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#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,12 +3,45 @@
|
|||||||
|
|
||||||
#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,6 +4,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
enum ePropertySortType : int32_t;
|
||||||
|
|
||||||
class IProperty {
|
class IProperty {
|
||||||
public:
|
public:
|
||||||
struct Info {
|
struct Info {
|
||||||
@@ -18,11 +20,33 @@ 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,6 +1,7 @@
|
|||||||
#ifndef __IPROPERTIESCONTENTS__H__
|
#ifndef __IPROPERTIESCONTENTS__H__
|
||||||
#define __IPROPERTIESCONTENTS__H__
|
#define __IPROPERTIESCONTENTS__H__
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ 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.
|
||||||
@@ -32,7 +34,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 UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) = 0;
|
virtual void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) = 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;
|
||||||
|
|||||||
14
dDatabase/GameDatabase/ITables/IUgcModularBuild.h
Normal file
14
dDatabase/GameDatabase/ITables/IUgcModularBuild.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#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,6 +4,7 @@
|
|||||||
#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;
|
||||||
@@ -13,6 +14,7 @@ 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
|
||||||
@@ -39,14 +41,13 @@ 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 (properties.find("localSocket") != properties.end() || properties.find("pipe") != properties.end()) {
|
#if defined(DARKFLAME_PLATFORM_WIN32) && defined(_DEBUG)
|
||||||
con = driver->connect(properties);
|
|
||||||
} else {
|
|
||||||
con = driver->connect(properties["hostName"].c_str(), properties["user"].c_str(), properties["password"].c_str());
|
con = driver->connect(properties["hostName"].c_str(), properties["user"].c_str(), properties["password"].c_str());
|
||||||
}
|
#else
|
||||||
|
con = driver->connect(properties);
|
||||||
|
#endif
|
||||||
con->setSchema(databaseName.c_str());
|
con->setSchema(databaseName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +68,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) {
|
||||||
Connect();
|
Database::Get()->Connect();
|
||||||
LOG("Trying to reconnect to MySQL");
|
LOG("Trying to reconnect to MySQL");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& quer
|
|||||||
|
|
||||||
con = nullptr;
|
con = nullptr;
|
||||||
|
|
||||||
Connect();
|
Database::Get()->Connect();
|
||||||
LOG("Trying to reconnect to MySQL from invalid or closed connection");
|
LOG("Trying to reconnect to MySQL from invalid or closed connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#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.
|
||||||
@@ -29,7 +30,6 @@ 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 UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) 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 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,6 +108,24 @@ 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,3 +35,12 @@ 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;
|
||||||
|
}
|
||||||
|
|||||||
19
dDatabase/GameDatabase/MySQL/Tables/Behaviors.cpp
Normal file
19
dDatabase/GameDatabase/MySQL/Tables/Behaviors.cpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#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,6 +2,7 @@ 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"
|
||||||
@@ -19,6 +20,7 @@ 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,5 +1,9 @@
|
|||||||
#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);
|
||||||
|
|
||||||
@@ -9,3 +13,79 @@ 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,8 +1,140 @@
|
|||||||
#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 "
|
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
||||||
"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()) {
|
||||||
@@ -21,6 +153,7 @@ 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,7 +1,10 @@
|
|||||||
#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("SELECT id, lot, x, y, z, rx, ry, rz, rw, ugc_id FROM properties_contents WHERE property_id = ?;", propertyId);
|
auto result = ExecuteSelect(
|
||||||
|
"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());
|
||||||
@@ -17,6 +20,12 @@ 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;
|
||||||
@@ -32,21 +41,23 @@ 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.
|
||||||
0, // behavior 1. TODO implement this.
|
model.behaviors[0], // behavior 1
|
||||||
0, // behavior 2. TODO implement this.
|
model.behaviors[1], // behavior 2
|
||||||
0, // behavior 3. TODO implement this.
|
model.behaviors[2], // behavior 3
|
||||||
0, // behavior 4. TODO implement this.
|
model.behaviors[3], // behavior 4
|
||||||
0 // behavior 5. TODO implement this.
|
model.behaviors[4] // behavior 5
|
||||||
);
|
);
|
||||||
} 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::UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) {
|
void MySQLDatabase::UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) {
|
||||||
ExecuteUpdate(
|
ExecuteUpdate(
|
||||||
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ? WHERE id = ?;",
|
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ?, "
|
||||||
position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w, propertyId);
|
"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,
|
||||||
|
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) {
|
||||||
|
|||||||
9
dDatabase/GameDatabase/MySQL/Tables/UgcModularBuild.cpp
Normal file
9
dDatabase/GameDatabase/MySQL/Tables/UgcModularBuild.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
11
dDatabase/GameDatabase/SQLite/CMakeLists.txt
Normal file
11
dDatabase/GameDatabase/SQLite/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
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)
|
||||||
73
dDatabase/GameDatabase/SQLite/SQLiteDatabase.cpp
Normal file
73
dDatabase/GameDatabase/SQLite/SQLiteDatabase.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
#include "Database.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "dPlatforms.h"
|
||||||
|
|
||||||
|
// Static Variables
|
||||||
|
|
||||||
|
// Status Variables
|
||||||
|
namespace {
|
||||||
|
CppSQLite3DB* con = nullptr;
|
||||||
|
bool isConnected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void SQLiteDatabase::Connect() {
|
||||||
|
LOG("Using SQLite database");
|
||||||
|
con = new CppSQLite3DB();
|
||||||
|
con->open(Game::config->GetValue("sqlite_database_path").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);
|
||||||
|
}
|
||||||
270
dDatabase/GameDatabase/SQLite/SQLiteDatabase.h
Normal file
270
dDatabase/GameDatabase/SQLite/SQLiteDatabase.h
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
#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
|
||||||
49
dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp
Normal file
49
dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#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");
|
||||||
|
}
|
||||||
17
dDatabase/GameDatabase/SQLite/Tables/AccountsRewardCodes.cpp
Normal file
17
dDatabase/GameDatabase/SQLite/Tables/AccountsRewardCodes.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
6
dDatabase/GameDatabase/SQLite/Tables/ActivityLog.cpp
Normal file
6
dDatabase/GameDatabase/SQLite/Tables/ActivityLog.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
19
dDatabase/GameDatabase/SQLite/Tables/Behaviors.cpp
Normal file
19
dDatabase/GameDatabase/SQLite/Tables/Behaviors.cpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#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") : "";
|
||||||
|
}
|
||||||
6
dDatabase/GameDatabase/SQLite/Tables/BugReports.cpp
Normal file
6
dDatabase/GameDatabase/SQLite/Tables/BugReports.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
26
dDatabase/GameDatabase/SQLite/Tables/CMakeLists.txt
Normal file
26
dDatabase/GameDatabase/SQLite/Tables/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
79
dDatabase/GameDatabase/SQLite/Tables/CharInfo.cpp
Normal file
79
dDatabase/GameDatabase/SQLite/Tables/CharInfo.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
19
dDatabase/GameDatabase/SQLite/Tables/CharXml.cpp
Normal file
19
dDatabase/GameDatabase/SQLite/Tables/CharXml.cpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
5
dDatabase/GameDatabase/SQLite/Tables/CommandLog.cpp
Normal file
5
dDatabase/GameDatabase/SQLite/Tables/CommandLog.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
73
dDatabase/GameDatabase/SQLite/Tables/Friends.cpp
Normal file
73
dDatabase/GameDatabase/SQLite/Tables/Friends.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#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
|
||||||
|
);
|
||||||
|
}
|
||||||
22
dDatabase/GameDatabase/SQLite/Tables/IgnoreList.cpp
Normal file
22
dDatabase/GameDatabase/SQLite/Tables/IgnoreList.cpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
91
dDatabase/GameDatabase/SQLite/Tables/Leaderboard.cpp
Normal file
91
dDatabase/GameDatabase/SQLite/Tables/Leaderboard.cpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
83
dDatabase/GameDatabase/SQLite/Tables/Mail.cpp
Normal file
83
dDatabase/GameDatabase/SQLite/Tables/Mail.cpp
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
13
dDatabase/GameDatabase/SQLite/Tables/MigrationHistory.cpp
Normal file
13
dDatabase/GameDatabase/SQLite/Tables/MigrationHistory.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
17
dDatabase/GameDatabase/SQLite/Tables/ObjectIdTracker.cpp
Normal file
17
dDatabase/GameDatabase/SQLite/Tables/ObjectIdTracker.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
std::optional<uint32_t> SQLiteDatabase::GetCurrentPersistentId() {
|
||||||
|
auto [_, result] = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
||||||
|
if (result.eof()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return result.getIntField("last_object_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::InsertDefaultPersistentId() {
|
||||||
|
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::UpdatePersistentId(const uint32_t newId) {
|
||||||
|
ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = ?;", newId);
|
||||||
|
}
|
||||||
26
dDatabase/GameDatabase/SQLite/Tables/PetNames.cpp
Normal file
26
dDatabase/GameDatabase/SQLite/Tables/PetNames.cpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
void SQLiteDatabase::SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) {
|
||||||
|
ExecuteInsert(
|
||||||
|
"INSERT INTO `pet_names` (`id`, `pet_name`, `approved`) VALUES (?, ?, ?) "
|
||||||
|
"ON CONFLICT(id) DO UPDATE SET pet_name = ?, approved = ?;",
|
||||||
|
petId,
|
||||||
|
info.petName,
|
||||||
|
info.approvalStatus,
|
||||||
|
info.petName,
|
||||||
|
info.approvalStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IPetNames::Info> SQLiteDatabase::GetPetNameInfo(const LWOOBJID& petId) {
|
||||||
|
auto [_, result] = ExecuteSelect("SELECT pet_name, approved FROM pet_names WHERE id = ? LIMIT 1;", petId);
|
||||||
|
|
||||||
|
if (result.eof()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPetNames::Info toReturn;
|
||||||
|
toReturn.petName = result.getStringField("pet_name");
|
||||||
|
toReturn.approvalStatus = result.getIntField("approved");
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
11
dDatabase/GameDatabase/SQLite/Tables/PlayKeys.cpp
Normal file
11
dDatabase/GameDatabase/SQLite/Tables/PlayKeys.cpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
std::optional<bool> SQLiteDatabase::IsPlaykeyActive(const int32_t playkeyId) {
|
||||||
|
auto [_, keyCheckRes] = ExecuteSelect("SELECT active FROM `play_keys` WHERE id=?", playkeyId);
|
||||||
|
|
||||||
|
if (keyCheckRes.eof()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyCheckRes.getIntField("active");
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
void SQLiteDatabase::InsertCheatDetection(const IPlayerCheatDetections::Info& info) {
|
||||||
|
ExecuteInsert(
|
||||||
|
"INSERT INTO player_cheat_detections (account_id, name, violation_msg, violation_system_address) VALUES (?, ?, ?, ?)",
|
||||||
|
info.userId, info.username, info.extraMessage, info.systemAddress);
|
||||||
|
}
|
||||||
195
dDatabase/GameDatabase/SQLite/Tables/Property.cpp
Normal file
195
dDatabase/GameDatabase/SQLite/Tables/Property.cpp
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
#include "ePropertySortType.h"
|
||||||
|
|
||||||
|
std::optional<IProperty::PropertyEntranceResult> SQLiteDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
||||||
|
std::optional<IProperty::PropertyEntranceResult> result;
|
||||||
|
std::string query;
|
||||||
|
std::pair<CppSQLite3Statement, CppSQLite3Query> propertiesRes;
|
||||||
|
|
||||||
|
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 ?;";
|
||||||
|
propertiesRes = 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.eof()) {
|
||||||
|
result = IProperty::PropertyEntranceResult();
|
||||||
|
result->totalEntriesMatchingQuery = count.getIntField("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 ?;";
|
||||||
|
propertiesRes = 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.eof()) {
|
||||||
|
result = IProperty::PropertyEntranceResult();
|
||||||
|
result->totalEntriesMatchingQuery = count.getIntField("count");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& [_, properties] = propertiesRes;
|
||||||
|
if (!properties.eof() && !result.has_value()) result = IProperty::PropertyEntranceResult();
|
||||||
|
while (!properties.eof()) {
|
||||||
|
auto& entry = result->entries.emplace_back();
|
||||||
|
entry.id = properties.getInt64Field("id");
|
||||||
|
entry.ownerId = properties.getInt64Field("owner_id");
|
||||||
|
entry.cloneId = properties.getInt64Field("clone_id");
|
||||||
|
entry.name = properties.getStringField("name");
|
||||||
|
entry.description = properties.getStringField("description");
|
||||||
|
entry.privacyOption = properties.getIntField("privacy_option");
|
||||||
|
entry.rejectionReason = properties.getStringField("rejection_reason");
|
||||||
|
entry.lastUpdatedTime = properties.getIntField("last_updated");
|
||||||
|
entry.claimedTime = properties.getIntField("time_claimed");
|
||||||
|
entry.reputation = properties.getIntField("reputation");
|
||||||
|
entry.modApproved = properties.getIntField("mod_approved");
|
||||||
|
entry.performanceCost = properties.getFloatField("performance_cost");
|
||||||
|
properties.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IProperty::Info> SQLiteDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) {
|
||||||
|
auto [_, propertyEntry] = ExecuteSelect(
|
||||||
|
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
||||||
|
"FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId);
|
||||||
|
|
||||||
|
if (propertyEntry.eof()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
IProperty::Info toReturn;
|
||||||
|
toReturn.id = propertyEntry.getInt64Field("id");
|
||||||
|
toReturn.ownerId = propertyEntry.getInt64Field("owner_id");
|
||||||
|
toReturn.cloneId = propertyEntry.getInt64Field("clone_id");
|
||||||
|
toReturn.name = propertyEntry.getStringField("name");
|
||||||
|
toReturn.description = propertyEntry.getStringField("description");
|
||||||
|
toReturn.privacyOption = propertyEntry.getIntField("privacy_option");
|
||||||
|
toReturn.rejectionReason = propertyEntry.getStringField("rejection_reason");
|
||||||
|
toReturn.lastUpdatedTime = propertyEntry.getIntField("last_updated");
|
||||||
|
toReturn.claimedTime = propertyEntry.getIntField("time_claimed");
|
||||||
|
toReturn.reputation = propertyEntry.getIntField("reputation");
|
||||||
|
toReturn.modApproved = propertyEntry.getIntField("mod_approved");
|
||||||
|
toReturn.performanceCost = propertyEntry.getFloatField("performance_cost");
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
||||||
|
ExecuteUpdate("UPDATE properties SET privacy_option = ?, rejection_reason = ?, mod_approved = ? WHERE id = ?;",
|
||||||
|
info.privacyOption,
|
||||||
|
info.rejectionReason,
|
||||||
|
info.modApproved,
|
||||||
|
info.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::UpdatePropertyDetails(const IProperty::Info& info) {
|
||||||
|
ExecuteUpdate("UPDATE properties SET name = ?, description = ? WHERE id = ?;", info.name, info.description, info.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) {
|
||||||
|
ExecuteUpdate("UPDATE properties SET performance_cost = ? WHERE zone_id = ? AND clone_id = ?;", performanceCost, zoneId.GetMapID(), zoneId.GetCloneID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) {
|
||||||
|
auto insertion = ExecuteInsert(
|
||||||
|
"INSERT INTO properties"
|
||||||
|
" (id, owner_id, template_id, clone_id, name, description, zone_id, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, performance_cost)"
|
||||||
|
" VALUES (?, ?, ?, ?, ?, ?, ?, 0, 0, 0, CAST(strftime('%s', 'now') as INT), CAST(strftime('%s', 'now') as INT), '', 0, 0.0)",
|
||||||
|
info.id,
|
||||||
|
info.ownerId,
|
||||||
|
templateId,
|
||||||
|
zoneId.GetCloneID(),
|
||||||
|
info.name,
|
||||||
|
info.description,
|
||||||
|
zoneId.GetMapID()
|
||||||
|
);
|
||||||
|
}
|
||||||
65
dDatabase/GameDatabase/SQLite/Tables/PropertyContents.cpp
Normal file
65
dDatabase/GameDatabase/SQLite/Tables/PropertyContents.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
std::vector<IPropertyContents::Model> SQLiteDatabase::GetPropertyModels(const LWOOBJID& propertyId) {
|
||||||
|
auto [_, result] = ExecuteSelect(
|
||||||
|
"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;
|
||||||
|
while (!result.eof()) {
|
||||||
|
IPropertyContents::Model model;
|
||||||
|
model.id = result.getInt64Field("id");
|
||||||
|
model.lot = static_cast<LOT>(result.getIntField("lot"));
|
||||||
|
model.position.x = result.getFloatField("x");
|
||||||
|
model.position.y = result.getFloatField("y");
|
||||||
|
model.position.z = result.getFloatField("z");
|
||||||
|
model.rotation.w = result.getFloatField("rw");
|
||||||
|
model.rotation.x = result.getFloatField("rx");
|
||||||
|
model.rotation.y = result.getFloatField("ry");
|
||||||
|
model.rotation.z = result.getFloatField("rz");
|
||||||
|
model.ugcId = result.getInt64Field("ugc_id");
|
||||||
|
model.behaviors[0] = result.getIntField("behavior_1");
|
||||||
|
model.behaviors[1] = result.getIntField("behavior_2");
|
||||||
|
model.behaviors[2] = result.getIntField("behavior_3");
|
||||||
|
model.behaviors[3] = result.getIntField("behavior_4");
|
||||||
|
model.behaviors[4] = result.getIntField("behavior_5");
|
||||||
|
|
||||||
|
toReturn.push_back(std::move(model));
|
||||||
|
result.nextRow();
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) {
|
||||||
|
try {
|
||||||
|
ExecuteInsert(
|
||||||
|
"INSERT INTO properties_contents"
|
||||||
|
"(id, property_id, ugc_id, lot, x, y, z, rx, ry, rz, rw, model_name, model_description, behavior_1, behavior_2, behavior_3, behavior_4, behavior_5)"
|
||||||
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 18
|
||||||
|
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,
|
||||||
|
name, "", // Model description. TODO implement this.
|
||||||
|
model.behaviors[0], // behavior 1
|
||||||
|
model.behaviors[1], // behavior 2
|
||||||
|
model.behaviors[2], // behavior 3
|
||||||
|
model.behaviors[3], // behavior 4
|
||||||
|
model.behaviors[4] // behavior 5
|
||||||
|
);
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
LOG("Error inserting new property model: %s", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) {
|
||||||
|
ExecuteUpdate(
|
||||||
|
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ?, "
|
||||||
|
"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,
|
||||||
|
behaviors[0].first, behaviors[1].first, behaviors[2].first, behaviors[3].first, behaviors[4].first, propertyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::RemoveModel(const LWOOBJID& modelId) {
|
||||||
|
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
||||||
|
}
|
||||||
23
dDatabase/GameDatabase/SQLite/Tables/Servers.cpp
Normal file
23
dDatabase/GameDatabase/SQLite/Tables/Servers.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
void SQLiteDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||||
|
// We only want our 1 entry anyways, so we can just delete all and reinsert the one we want
|
||||||
|
// since it would be two queries anyways.
|
||||||
|
ExecuteDelete("DELETE FROM servers;");
|
||||||
|
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`) VALUES ('master', ?, ?, 0, 171022)", ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IServers::MasterInfo> SQLiteDatabase::GetMasterInfo() {
|
||||||
|
auto [_, result] = ExecuteSelect("SELECT ip, port FROM servers WHERE name='master' LIMIT 1;");
|
||||||
|
|
||||||
|
if (result.eof()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
MasterInfo toReturn;
|
||||||
|
|
||||||
|
toReturn.ip = result.getStringField("ip");
|
||||||
|
toReturn.port = result.getIntField("port");
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
72
dDatabase/GameDatabase/SQLite/Tables/Ugc.cpp
Normal file
72
dDatabase/GameDatabase/SQLite/Tables/Ugc.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
std::vector<IUgc::Model> SQLiteDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
||||||
|
auto [_, result] = ExecuteSelect(
|
||||||
|
"SELECT lxfml, u.id FROM ugc AS u JOIN properties_contents AS pc ON u.id = pc.ugc_id WHERE lot = 14 AND property_id = ? AND pc.ugc_id IS NOT NULL;",
|
||||||
|
propertyId);
|
||||||
|
|
||||||
|
std::vector<IUgc::Model> toReturn;
|
||||||
|
|
||||||
|
while (!result.eof()) {
|
||||||
|
IUgc::Model model;
|
||||||
|
|
||||||
|
int blobSize{};
|
||||||
|
const auto* blob = result.getBlobField("lxfml", blobSize);
|
||||||
|
model.lxfmlData << std::string(reinterpret_cast<const char*>(blob), blobSize);
|
||||||
|
model.id = result.getInt64Field("id");
|
||||||
|
toReturn.push_back(std::move(model));
|
||||||
|
result.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IUgc::Model> SQLiteDatabase::GetAllUgcModels() {
|
||||||
|
auto [_, result] = ExecuteSelect("SELECT id, lxfml FROM ugc;");
|
||||||
|
|
||||||
|
std::vector<IUgc::Model> models;
|
||||||
|
while (!result.eof()) {
|
||||||
|
IUgc::Model model;
|
||||||
|
model.id = result.getInt64Field("id");
|
||||||
|
|
||||||
|
int blobSize{};
|
||||||
|
const auto* blob = result.getBlobField("lxfml", blobSize);
|
||||||
|
model.lxfmlData << std::string(reinterpret_cast<const char*>(blob), blobSize);
|
||||||
|
models.push_back(std::move(model));
|
||||||
|
result.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::RemoveUnreferencedUgcModels() {
|
||||||
|
ExecuteDelete("DELETE FROM ugc WHERE id NOT IN (SELECT ugc_id FROM properties_contents WHERE ugc_id IS NOT NULL);");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::InsertNewUgcModel(
|
||||||
|
std::istringstream& sd0Data, // cant be const sad
|
||||||
|
const uint32_t blueprintId,
|
||||||
|
const uint32_t accountId,
|
||||||
|
const uint32_t characterId) {
|
||||||
|
const std::istream stream(sd0Data.rdbuf());
|
||||||
|
ExecuteInsert(
|
||||||
|
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
||||||
|
blueprintId,
|
||||||
|
accountId,
|
||||||
|
characterId,
|
||||||
|
0,
|
||||||
|
&stream,
|
||||||
|
false,
|
||||||
|
"weedeater.lxfml"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::DeleteUgcModelData(const LWOOBJID& modelId) {
|
||||||
|
ExecuteDelete("DELETE FROM ugc WHERE id = ?;", modelId);
|
||||||
|
ExecuteDelete("DELETE FROM properties_contents WHERE ugc_id = ?;", modelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SQLiteDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::istringstream& lxfml) {
|
||||||
|
const std::istream stream(lxfml.rdbuf());
|
||||||
|
ExecuteUpdate("UPDATE ugc SET lxfml = ? WHERE id = ?;", &stream, modelId);
|
||||||
|
}
|
||||||
9
dDatabase/GameDatabase/SQLite/Tables/UgcModularBuild.cpp
Normal file
9
dDatabase/GameDatabase/SQLite/Tables/UgcModularBuild.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
void SQLiteDatabase::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 SQLiteDatabase::DeleteUgcBuild(const LWOOBJID bigId) {
|
||||||
|
ExecuteDelete("DELETE FROM ugc_modular_build WHERE ugc_id = ?;", bigId);
|
||||||
|
}
|
||||||
4
dDatabase/GameDatabase/TestSQL/CMakeLists.txt
Normal file
4
dDatabase/GameDatabase/TestSQL/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
SET(DDATABSE_DATABSES_TEST_SQL_SOURCES
|
||||||
|
"TestSQLDatabase.cpp"
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
302
dDatabase/GameDatabase/TestSQL/TestSQLDatabase.cpp
Normal file
302
dDatabase/GameDatabase/TestSQL/TestSQLDatabase.cpp
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
#include "TestSQLDatabase.h"
|
||||||
|
|
||||||
|
void TestSQLDatabase::Connect() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::Destroy(std::string source) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::Commit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestSQLDatabase::GetAutoCommit() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::SetAutoCommit(bool value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::ExecuteCustomQuery(const std::string_view query) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IServers::MasterInfo> TestSQLDatabase::GetMasterInfo() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> TestSQLDatabase::GetApprovedCharacterNames() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<FriendData> TestSQLDatabase::GetFriendsList(uint32_t charID) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IFriends::BestFriendStatus> TestSQLDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::DeleteUgcModelData(const LWOOBJID& modelId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::istringstream& lxfml) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IUgc::Model> TestSQLDatabase::GetAllUgcModels() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::CreateMigrationHistoryTable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestSQLDatabase::IsMigrationRun(const std::string_view str) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertMigration(const std::string_view str) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ICharInfo::Info> TestSQLDatabase::GetCharacterInfo(const uint32_t charId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ICharInfo::Info> TestSQLDatabase::GetCharacterInfo(const std::string_view charId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TestSQLDatabase::GetCharacterXml(const uint32_t accountId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IAccounts::Info> TestSQLDatabase::GetAccountInfo(const std::string_view username) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> TestSQLDatabase::GetAccountCharacterIds(uint32_t accountId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::DeleteCharacter(const uint32_t characterId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IPetNames::Info> TestSQLDatabase::GetPetNameInfo(const LWOOBJID& petId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IProperty::Info> TestSQLDatabase::GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdatePropertyDetails(const IProperty::Info& info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IPropertyContents::Model> TestSQLDatabase::GetPropertyModels(const LWOOBJID& propertyId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::RemoveUnreferencedUgcModels() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::RemoveModel(const LWOOBJID& modelId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertNewBugReport(const IBugReports::Info& info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertCheatDetection(const IPlayerCheatDetections::Info& info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertNewMail(const IMail::MailInfo& mail) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertNewUgcModel(std::istringstream& sd0Data, const uint32_t blueprintId, const uint32_t accountId, const uint32_t characterId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IMail::MailInfo> TestSQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<IMail::MailInfo> TestSQLDatabase::GetMail(const uint64_t mailId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TestSQLDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::MarkMailRead(const uint64_t mailId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::DeleteMail(const uint64_t mailId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::ClaimMailItem(const uint64_t mailId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateAccountBan(const uint32_t accountId, const bool banned) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint32_t> TestSQLDatabase::GetCurrentPersistentId() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertDefaultPersistentId() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdatePersistentId(const uint32_t id) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint32_t> TestSQLDatabase::GetDonationTotal(const uint32_t activityId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<bool> TestSQLDatabase::IsPlaykeyActive(const int32_t playkeyId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IUgc::Model> TestSQLDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IIgnoreList::Info> TestSQLDatabase::GetIgnoreList(const uint32_t playerId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> TestSQLDatabase::GetRewardCodesByAccountID(const uint32_t account_id) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::AddBehavior(const IBehaviors::Info& info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TestSQLDatabase::GetBehavior(const int32_t behaviorId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::RemoveBehavior(const int32_t behaviorId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSQLDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
107
dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h
Normal file
107
dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#ifndef TESTSQLDATABASE_H
|
||||||
|
#define TESTSQLDATABASE_H
|
||||||
|
|
||||||
|
#include "GameDatabase.h"
|
||||||
|
|
||||||
|
class TestSQLDatabase : public GameDatabase {
|
||||||
|
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 behaviorId) override;
|
||||||
|
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
||||||
|
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override { return {}; };
|
||||||
|
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override { return {}; };
|
||||||
|
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override { return {}; };
|
||||||
|
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override { return {}; };
|
||||||
|
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override { return {}; };
|
||||||
|
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 { return {}; };
|
||||||
|
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 { return 0; };
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!TESTSQLDATABASE_H
|
||||||
@@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
Migration LoadMigration(std::string path) {
|
Migration LoadMigration(std::string folder, std::string path) {
|
||||||
Migration migration{};
|
Migration migration{};
|
||||||
std::ifstream file(BinaryPathFinder::GetBinaryDir() / "migrations/" / path);
|
std::ifstream file(BinaryPathFinder::GetBinaryDir() / "migrations/" / folder / path);
|
||||||
|
|
||||||
if (file.is_open()) {
|
if (file.is_open()) {
|
||||||
std::string line;
|
std::string line;
|
||||||
@@ -34,10 +34,19 @@ Migration LoadMigration(std::string path) {
|
|||||||
void MigrationRunner::RunMigrations() {
|
void MigrationRunner::RunMigrations() {
|
||||||
Database::Get()->CreateMigrationHistoryTable();
|
Database::Get()->CreateMigrationHistoryTable();
|
||||||
|
|
||||||
sql::SQLString finalSQL = "";
|
// has to be here because when moving the files to the new folder, the migration_history table is not updated so it will run them all again.
|
||||||
|
|
||||||
|
const auto migrationFolder = Database::GetMigrationFolder();
|
||||||
|
if (!Database::Get()->IsMigrationRun("17_migration_for_migrations.sql") && migrationFolder == "mysql") {
|
||||||
|
LOG("Running migration: 17_migration_for_migrations.sql");
|
||||||
|
Database::Get()->ExecuteCustomQuery("UPDATE `migration_history` SET `name` = SUBSTR(`name`, 5) WHERE `name` LIKE \"dlu%\";");
|
||||||
|
Database::Get()->InsertMigration("17_migration_for_migrations.sql");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string finalSQL = "";
|
||||||
bool runSd0Migrations = false;
|
bool runSd0Migrations = false;
|
||||||
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "./migrations/dlu/").string())) {
|
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "./migrations/dlu/" / migrationFolder).string())) {
|
||||||
auto migration = LoadMigration("dlu/" + entry);
|
auto migration = LoadMigration("dlu/" + migrationFolder + "/", entry);
|
||||||
|
|
||||||
if (migration.data.empty()) {
|
if (migration.data.empty()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -46,7 +55,7 @@ void MigrationRunner::RunMigrations() {
|
|||||||
if (Database::Get()->IsMigrationRun(migration.name)) continue;
|
if (Database::Get()->IsMigrationRun(migration.name)) continue;
|
||||||
|
|
||||||
LOG("Running migration: %s", migration.name.c_str());
|
LOG("Running migration: %s", migration.name.c_str());
|
||||||
if (migration.name == "dlu/5_brick_model_sd0.sql") {
|
if (migration.name == "5_brick_model_sd0.sql") {
|
||||||
runSd0Migrations = true;
|
runSd0Migrations = true;
|
||||||
} else {
|
} else {
|
||||||
finalSQL.append(migration.data.c_str());
|
finalSQL.append(migration.data.c_str());
|
||||||
@@ -61,12 +70,12 @@ void MigrationRunner::RunMigrations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!finalSQL.empty()) {
|
if (!finalSQL.empty()) {
|
||||||
auto migration = GeneralUtils::SplitString(static_cast<std::string>(finalSQL), ';');
|
auto migration = GeneralUtils::SplitString(finalSQL, ';');
|
||||||
for (auto& query : migration) {
|
for (auto& query : migration) {
|
||||||
try {
|
try {
|
||||||
if (query.empty()) continue;
|
if (query.empty()) continue;
|
||||||
Database::Get()->ExecuteCustomQuery(query.c_str());
|
Database::Get()->ExecuteCustomQuery(query);
|
||||||
} catch (sql::SQLException& e) {
|
} catch (std::exception& e) {
|
||||||
LOG("Encountered error running migration: %s", e.what());
|
LOG("Encountered error running migration: %s", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,10 +95,14 @@ void MigrationRunner::RunSQLiteMigrations() {
|
|||||||
cdstmt.execQuery().finalize();
|
cdstmt.execQuery().finalize();
|
||||||
cdstmt.finalize();
|
cdstmt.finalize();
|
||||||
|
|
||||||
Database::Get()->CreateMigrationHistoryTable();
|
if (CDClientDatabase::ExecuteQuery("select * from migration_history where name = \"7_migration_for_migrations.sql\";").eof()) {
|
||||||
|
LOG("Running migration: 7_migration_for_migrations.sql");
|
||||||
|
CDClientDatabase::ExecuteQuery("UPDATE `migration_history` SET `name` = SUBSTR(`name`, 10) WHERE `name` LIKE \"cdserver%\";");
|
||||||
|
CDClientDatabase::ExecuteQuery("INSERT INTO migration_history (name) VALUES (\"7_migration_for_migrations.sql\");");
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "migrations/cdserver/").string())) {
|
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "migrations/cdserver/").string())) {
|
||||||
auto migration = LoadMigration("cdserver/" + entry);
|
auto migration = LoadMigration("cdserver/", entry);
|
||||||
|
|
||||||
if (migration.data.empty()) continue;
|
if (migration.data.empty()) continue;
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ target_include_directories(dGameBase PUBLIC "." "dEntity"
|
|||||||
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables"
|
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables"
|
||||||
"${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}/thirdparty/mariadb-connector-cpp/include"
|
|
||||||
# dPhysics
|
# dPhysics
|
||||||
"${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Recast/Include"
|
"${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Recast/Include"
|
||||||
"${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Detour/Include"
|
"${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Detour/Include"
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ Character::Character(uint32_t id, User* parentUser) {
|
|||||||
m_ID = id;
|
m_ID = id;
|
||||||
m_ParentUser = parentUser;
|
m_ParentUser = parentUser;
|
||||||
m_OurEntity = nullptr;
|
m_OurEntity = nullptr;
|
||||||
|
m_GMLevel = eGameMasterLevel::CIVILIAN;
|
||||||
|
m_PermissionMap = static_cast<ePermissionMap>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Character::~Character() {
|
Character::~Character() {
|
||||||
@@ -38,8 +40,8 @@ void Character::UpdateInfoFromDatabase() {
|
|||||||
auto charInfo = Database::Get()->GetCharacterInfo(m_ID);
|
auto charInfo = Database::Get()->GetCharacterInfo(m_ID);
|
||||||
|
|
||||||
if (charInfo) {
|
if (charInfo) {
|
||||||
m_Name = charInfo->name;
|
m_Name = charInfo->name;
|
||||||
m_UnapprovedName = charInfo->pendingName;
|
m_UnapprovedName = charInfo->pendingName;
|
||||||
m_NameRejected = charInfo->needsRename;
|
m_NameRejected = charInfo->needsRename;
|
||||||
m_PropertyCloneID = charInfo->cloneId;
|
m_PropertyCloneID = charInfo->cloneId;
|
||||||
m_PermissionMap = charInfo->permissionMap;
|
m_PermissionMap = charInfo->permissionMap;
|
||||||
@@ -74,7 +76,7 @@ void Character::DoQuickXMLDataParse() {
|
|||||||
if (m_Doc.Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
|
if (m_Doc.Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
|
||||||
LOG("Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID);
|
LOG("Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID);
|
||||||
} else {
|
} else {
|
||||||
LOG("Failed to load xmlData!");
|
LOG("Failed to load xmlData (%i) (%s) (%s)!", m_Doc.ErrorID(), m_Doc.ErrorIDToName(m_Doc.ErrorID()), m_Doc.ErrorStr());
|
||||||
//Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true);
|
//Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
|
|
||||||
const std::string& GetXMLData() const { return m_XMLData; }
|
const std::string& GetXMLData() const { return m_XMLData; }
|
||||||
const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; }
|
const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; }
|
||||||
|
void _setXmlDoc(tinyxml2::XMLDocument& doc) { doc.DeepCopy(&m_Doc); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Out of abundance of safety and clarity of what this saves, this is its own function.
|
* Out of abundance of safety and clarity of what this saves, this is its own function.
|
||||||
@@ -459,27 +460,31 @@ public:
|
|||||||
|
|
||||||
User* GetParentUser() const { return m_ParentUser; }
|
User* GetParentUser() const { return m_ParentUser; }
|
||||||
|
|
||||||
|
void _doQuickXMLDataParse() { DoQuickXMLDataParse(); }
|
||||||
|
|
||||||
|
void _setXmlData(const std::string& xmlData) { m_XMLData = xmlData; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateInfoFromDatabase();
|
void UpdateInfoFromDatabase();
|
||||||
/**
|
/**
|
||||||
* The ID of this character. First 32 bits of the ObjectID.
|
* The ID of this character. First 32 bits of the ObjectID.
|
||||||
*/
|
*/
|
||||||
uint32_t m_ID;
|
uint32_t m_ID{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The 64-bit unique ID used in the game.
|
* The 64-bit unique ID used in the game.
|
||||||
*/
|
*/
|
||||||
LWOOBJID m_ObjectID;
|
LWOOBJID m_ObjectID{ LWOOBJID_EMPTY };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user that owns this character.
|
* The user that owns this character.
|
||||||
*/
|
*/
|
||||||
User* m_ParentUser;
|
User* m_ParentUser{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the character is in game, this is the entity that it represents, else nullptr.
|
* If the character is in game, this is the entity that it represents, else nullptr.
|
||||||
*/
|
*/
|
||||||
Entity* m_OurEntity;
|
Entity* m_OurEntity{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0-9, the Game Master level of this character.
|
* 0-9, the Game Master level of this character.
|
||||||
@@ -506,17 +511,17 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Whether the custom name of this character is rejected
|
* Whether the custom name of this character is rejected
|
||||||
*/
|
*/
|
||||||
bool m_NameRejected;
|
bool m_NameRejected{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current amount of coins of this character
|
* The current amount of coins of this character
|
||||||
*/
|
*/
|
||||||
int64_t m_Coins;
|
int64_t m_Coins{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the character is building
|
* Whether the character is building
|
||||||
*/
|
*/
|
||||||
bool m_BuildMode;
|
bool m_BuildMode{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The items equipped by the character on world load
|
* The items equipped by the character on world load
|
||||||
@@ -583,7 +588,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The ID of the properties of this character
|
* The ID of the properties of this character
|
||||||
*/
|
*/
|
||||||
uint32_t m_PropertyCloneID;
|
uint32_t m_PropertyCloneID{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The XML data for this character, stored as string
|
* The XML data for this character, stored as string
|
||||||
@@ -613,7 +618,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The last time this character logged in
|
* The last time this character logged in
|
||||||
*/
|
*/
|
||||||
uint64_t m_LastLogin;
|
uint64_t m_LastLogin{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The gameplay flags this character has (not just true values)
|
* The gameplay flags this character has (not just true values)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user