mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 03:37:08 -06:00
Compare commits
15 Commits
windows-cl
...
naming-of-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f6ee6327e | ||
|
|
d572ce1f1c | ||
|
|
85cd609168 | ||
|
|
d4e6939dbd | ||
|
|
f8d5110290 | ||
|
|
a153d0a78c | ||
|
|
bfeb10c972 | ||
|
|
82507e642a | ||
|
|
abd978c348 | ||
|
|
10f8d40b69 | ||
|
|
37c2c5db5d | ||
|
|
693a2fef35 | ||
|
|
787237c930 | ||
|
|
0464f37fab | ||
|
|
78ae8bc6b6 |
@@ -73,4 +73,4 @@ cpp_space_around_assignment_operator=insert
|
||||
cpp_space_pointer_reference_alignment=left
|
||||
cpp_space_around_ternary_operator=insert
|
||||
cpp_wrap_preserve_blocks=one_liners
|
||||
cpp_indent_comment=false
|
||||
cpp_indent_comment=fasle
|
||||
|
||||
30
.github/workflows/build-and-test.yml
vendored
30
.github/workflows/build-and-test.yml
vendored
@@ -16,12 +16,12 @@ jobs:
|
||||
os: [ windows-2022, ubuntu-22.04, macos-13 ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- name: Add msbuild to PATH (Windows only)
|
||||
if: ${{ matrix.os == 'windows-2022' }}
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
with:
|
||||
vs-version: '[17,18)'
|
||||
msbuild-architecture: x64
|
||||
@@ -33,19 +33,21 @@ jobs:
|
||||
- name: cmake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
workflowPreset: "ci-${{matrix.os}}"
|
||||
configurePreset: "ci-${{matrix.os}}"
|
||||
buildPreset: "ci-${{matrix.os}}"
|
||||
testPreset: "ci-${{matrix.os}}"
|
||||
- name: artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: build-${{matrix.os}}
|
||||
path: |
|
||||
build/*/*Server*
|
||||
build/*/*.ini
|
||||
build/*/*.so
|
||||
build/*/*.dll
|
||||
build/*/vanity/
|
||||
build/*/navmeshes/
|
||||
build/*/migrations/
|
||||
build/*/*.dcf
|
||||
!build/*/*.pdb
|
||||
!build/*/d*/
|
||||
build/*Server*
|
||||
build/*.ini
|
||||
build/*.so
|
||||
build/*.dll
|
||||
build/vanity/
|
||||
build/navmeshes/
|
||||
build/migrations/
|
||||
build/*.dcf
|
||||
!build/*.pdb
|
||||
!build/d*/
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -112,8 +112,6 @@ CMakeFiles/TargetDirectories.txt
|
||||
*.sln
|
||||
*.recipe
|
||||
|
||||
CMakeUserPresets.json
|
||||
|
||||
# clangd
|
||||
.cache
|
||||
thirdparty/zlib-1.2.11/
|
||||
@@ -124,7 +122,4 @@ docker/__pycache__
|
||||
docker-compose.override.yml
|
||||
|
||||
!*Test.bin
|
||||
|
||||
# CMake scripts
|
||||
!cmake/*
|
||||
!cmake/toolchains/*
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
project(Darkflame
|
||||
HOMEPAGE_URL "https://github.com/DarkflameUniverse/DarkflameServer"
|
||||
LANGUAGES C CXX
|
||||
)
|
||||
project(Darkflame)
|
||||
|
||||
# check if the path to the source directory contains a space
|
||||
if("${CMAKE_SOURCE_DIR}" MATCHES " ")
|
||||
@@ -11,17 +8,12 @@ endif()
|
||||
|
||||
include(CTest)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CXX_STANDARD_REQUIRED ON)
|
||||
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_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: Debug, Release, RelWithDebInfo, MinSizeRel")
|
||||
set(DLU_CONFIG_DIR ${CMAKE_SOURCE_DIR}/build CACHE PATH "The directory where the server configuration files are stored")
|
||||
|
||||
# Read variables from file
|
||||
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
|
||||
@@ -69,37 +61,35 @@ set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
# Disabled no-register
|
||||
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
||||
if(UNIX)
|
||||
add_compile_options("-fPIC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wuninitialized -fPIC")
|
||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0)
|
||||
|
||||
# For all except Clang and Apple Clang
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options("-static-libgcc" "-lstdc++fs" "-Wno-error=implicit-function-declaration" "-Wno-error=int-conversion")
|
||||
if(NOT APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -lstdc++fs")
|
||||
endif()
|
||||
|
||||
if(${DYNAMIC} AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
add_link_options("-export-dynamic")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
|
||||
endif()
|
||||
|
||||
if(${GGDB})
|
||||
add_compile_options("-ggdb")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
|
||||
elseif(MSVC)
|
||||
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
|
||||
# Also disable non-portable MSVC volatile behavior
|
||||
add_compile_options("/wd4267" "/utf-8" "/volatile:iso" "/Zc:inline")
|
||||
add_compile_options("/wd4267" "/utf-8" "/volatile:iso")
|
||||
elseif(WIN32)
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
# Set the output directories
|
||||
# ./build/<platform + architecture (x64, x86, aarch64)>/<compiler>/<build_mode>/
|
||||
# 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_BINARY_DIR ${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_CXX_COMPILER_ID}/${CMAKE_BUILD_TYPE})
|
||||
|
||||
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})
|
||||
# TODO make this not have to override the build type directories
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||
@@ -111,15 +101,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
# Get DLU config directory
|
||||
if(DEFINED ENV{DLU_CONFIG_DIR})
|
||||
set(DLU_CONFIG_DIR $ENV{DLU_CONFIG_DIR})
|
||||
else()
|
||||
set(DLU_CONFIG_DIR ${CMAKE_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
message(STATUS "Configuration Directory is ${DLU_CONFIG_DIR}, and the build directory is ${CMAKE_BINARY_DIR}")
|
||||
|
||||
find_package(MariaDB)
|
||||
|
||||
# Create a /resServer directory
|
||||
@@ -132,28 +113,27 @@ make_directory(${CMAKE_BINARY_DIR}/logs)
|
||||
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blocklist.dcf")
|
||||
message(STATUS "Checking resource file integrity")
|
||||
|
||||
|
||||
include(Utils)
|
||||
UpdateConfigOption(${DLU_CONFIG_DIR}/authconfig.ini "port" "auth_server_port")
|
||||
UpdateConfigOption(${DLU_CONFIG_DIR}/chatconfig.ini "port" "chat_server_port")
|
||||
UpdateConfigOption(${DLU_CONFIG_DIR}/masterconfig.ini "port" "master_server_port")
|
||||
UpdateConfigOption(${PROJECT_BINARY_DIR}/authconfig.ini "port" "auth_server_port")
|
||||
UpdateConfigOption(${PROJECT_BINARY_DIR}/chatconfig.ini "port" "chat_server_port")
|
||||
UpdateConfigOption(${PROJECT_BINARY_DIR}/masterconfig.ini "port" "master_server_port")
|
||||
|
||||
foreach(resource_file ${RESOURCE_FILES})
|
||||
set(file_size 0)
|
||||
|
||||
if(EXISTS ${DLU_CONFIG_DIR}/${resource_file})
|
||||
file(SIZE ${DLU_CONFIG_DIR}/${resource_file} file_size)
|
||||
if(EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
||||
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
|
||||
endif()
|
||||
|
||||
if(${file_size} EQUAL 0)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${DLU_CONFIG_DIR}/${resource_file}
|
||||
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
||||
COPYONLY
|
||||
)
|
||||
message(STATUS "Moved " ${resource_file} " to DLU config directory")
|
||||
message(STATUS "Moved " ${resource_file} " to project binary directory")
|
||||
elseif(resource_file MATCHES ".ini")
|
||||
message(STATUS "Checking " ${resource_file} " for missing config options")
|
||||
file(READ ${DLU_CONFIG_DIR}/${resource_file} current_file_contents)
|
||||
file(READ ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
|
||||
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
|
||||
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
|
||||
set(parsed_current_file_contents "")
|
||||
@@ -184,10 +164,10 @@ foreach(resource_file ${RESOURCE_FILES})
|
||||
set(line_to_add ${line_to_add} ${line})
|
||||
|
||||
foreach(line_to_append ${line_to_add})
|
||||
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n" ${line_to_append})
|
||||
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
|
||||
endforeach()
|
||||
|
||||
file(APPEND ${DLU_CONFIG_DIR}/${resource_file} "\n")
|
||||
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
|
||||
endif()
|
||||
|
||||
set(line_to_add "")
|
||||
@@ -256,15 +236,14 @@ include_directories(
|
||||
"tests/dGameTests"
|
||||
"tests/dGameTests/dComponentsTests"
|
||||
|
||||
SYSTEM
|
||||
"thirdparty/magic_enum/include/magic_enum"
|
||||
"thirdparty/raknet/Source"
|
||||
"thirdparty/tinyxml2"
|
||||
"thirdparty/recastnavigation"
|
||||
"thirdparty/SQLite"
|
||||
"thirdparty/cpplinq"
|
||||
"thirdparty/cpp-httplib"
|
||||
"thirdparty/MD5"
|
||||
SYSTEM "thirdparty/magic_enum/include/magic_enum"
|
||||
SYSTEM "thirdparty/raknet/Source"
|
||||
SYSTEM "thirdparty/tinyxml2"
|
||||
SYSTEM "thirdparty/recastnavigation"
|
||||
SYSTEM "thirdparty/SQLite"
|
||||
SYSTEM "thirdparty/cpplinq"
|
||||
SYSTEM "thirdparty/cpp-httplib"
|
||||
SYSTEM "thirdparty/MD5"
|
||||
)
|
||||
|
||||
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
||||
@@ -273,17 +252,10 @@ if(APPLE)
|
||||
include_directories("/usr/local/include/")
|
||||
endif()
|
||||
|
||||
# Set warning flags
|
||||
if(MSVC)
|
||||
# add_compile_options("/W4")
|
||||
# Want to enable warnings eventually, but WAY too much noise right now
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
||||
add_compile_options("-Wuninitialized" "-Wold-style-cast")
|
||||
else()
|
||||
message(WARNING "Unknown compiler: '${CMAKE_CXX_COMPILER_ID}' - No warning flags enabled.")
|
||||
endif()
|
||||
|
||||
# Add linking directories:
|
||||
if (UNIX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast -Werror") # Warning flags
|
||||
endif()
|
||||
file(
|
||||
GLOB HEADERS_DZONEMANAGER
|
||||
LIST_DIRECTORIES false
|
||||
|
||||
@@ -1,191 +1,128 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 25,
|
||||
"patch": 0
|
||||
"major": 3,
|
||||
"minor": 14,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"displayName": "Default configure step",
|
||||
"description": "Use 'build' dir and Unix makefiles",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"generator": "Unix Makefiles",
|
||||
"hidden": true
|
||||
{
|
||||
"name": "default",
|
||||
"displayName": "Default configure step",
|
||||
"description": "Use 'build' dir and Unix makefiles",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"name": "windows-default",
|
||||
"inherits": "default",
|
||||
"displayName": "Windows Default Configure Settings",
|
||||
"description": "Sets build and install directories",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"hidden": true
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc",
|
||||
"inherits": "windows-default",
|
||||
"displayName": "Windows (MSVC)",
|
||||
"description": "Create a build using MSVC"
|
||||
},
|
||||
{
|
||||
"name": "windows-clang",
|
||||
"inherits": "windows-default",
|
||||
"displayName": "EXPERIMENTAL - Windows (Clang)",
|
||||
"description": "Create a build using Clang",
|
||||
"toolset": "ClangCL"
|
||||
},
|
||||
{
|
||||
"name": "linux-default",
|
||||
"inherits": "default",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-clang",
|
||||
"inherits": "linux-default",
|
||||
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-clang.cmake",
|
||||
"displayName": "Linux (Clang)",
|
||||
"description": "Create a build using the Clang toolchain for Linux"
|
||||
},
|
||||
{
|
||||
"name": "linux-gnu",
|
||||
"inherits": "linux-default",
|
||||
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-gnu.cmake",
|
||||
"displayName": "Linux (GNU)",
|
||||
"description": "Create a build using the GNU toolchain for Linux"
|
||||
},
|
||||
{
|
||||
"name": "macos",
|
||||
"inherits": "default",
|
||||
"displayName": "MacOS",
|
||||
"description": "Create a build for MacOS",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
}
|
||||
"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": "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": "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": "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
|
||||
}
|
||||
],
|
||||
"workflowPresets": [
|
||||
{
|
||||
"name": "ci-windows-2022",
|
||||
"displayName": "[Release] Windows (MSVC)",
|
||||
"description": "CI workflow preset for Windows",
|
||||
"steps": [
|
||||
{
|
||||
"type": "configure",
|
||||
"name": "windows-msvc"
|
||||
},
|
||||
{
|
||||
"type": "build",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"type": "test",
|
||||
"name": "default"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-22.04",
|
||||
"displayName": "[Release] Linux (GNU)",
|
||||
"description": "CI workflow preset for Ubuntu",
|
||||
"steps": [
|
||||
{
|
||||
"type": "configure",
|
||||
"name": "linux-gnu"
|
||||
},
|
||||
{
|
||||
"type": "build",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"type": "test",
|
||||
"name": "ci-ubuntu-22.04"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13",
|
||||
"displayName": "[Release] MacOS",
|
||||
"description": "CI workflow preset for MacOS",
|
||||
"steps": [
|
||||
{
|
||||
"type": "configure",
|
||||
"name": "macos"
|
||||
},
|
||||
{
|
||||
"type": "build",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"type": "test",
|
||||
"name": "default"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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))+"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ COPY --from=build /app/build/*Server /app/
|
||||
|
||||
# Necessary suplimentary files
|
||||
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/migrations /app/migrations
|
||||
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
|
||||
# of a mount clobbering the copy from above
|
||||
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
|
||||
# and therefore sudo doesn't exist
|
||||
|
||||
3
build.sh
3
build.sh
@@ -6,7 +6,8 @@ mkdir -p build
|
||||
cd build
|
||||
|
||||
# Run cmake to generate make files
|
||||
cmake -DCMAKE_BUILD_TYPE="Release" ..
|
||||
cmake ..
|
||||
|
||||
# To build utilizing multiple cores, append `-j` and the amount of cores to utilize, for example `cmake --build . --config Release -j8'
|
||||
cmake --build . --config Release $1
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# Try and find a clang-16 install, falling back to a generic clang install otherwise
|
||||
find_program(CLANG_C_COMPILER clang-16 | clang REQUIRED)
|
||||
find_program(CLANG_CXX_COMPILER clang++-16 | clang++ REQUIRED)
|
||||
|
||||
# Debug messages
|
||||
message(DEBUG "CLANG_C_COMPILER = ${CLANG_C_COMPILER}")
|
||||
message(DEBUG "CLANG_CXX_COMPILER = ${CLANG_CXX_COMPILER}")
|
||||
|
||||
# Set compilers to clang (need to cache for VSCode tools to work correctly)
|
||||
set(CMAKE_C_COMPILER ${CLANG_C_COMPILER} CACHE STRING "Set C compiler")
|
||||
set(CMAKE_CXX_COMPILER ${CLANG_CXX_COMPILER} CACHE STRING "Set C++ compiler")
|
||||
|
||||
# Set linker to lld
|
||||
add_link_options("-fuse-ld=lld")
|
||||
@@ -1,11 +0,0 @@
|
||||
# Try and find a gcc/g++ install
|
||||
find_program(GNU_C_COMPILER cc | gcc REQUIRED)
|
||||
find_program(GNU_CXX_COMPILER c++ | g++ REQUIRED)
|
||||
|
||||
# Debug messages
|
||||
message(DEBUG "GNU_C_COMPILER = ${GNU_C_COMPILER}")
|
||||
message(DEBUG "GNU_CXX_COMPILER = ${GNU_CXX_COMPILER}")
|
||||
|
||||
# Set compilers to GNU (need to cache for VSCode tools to work correctly)
|
||||
set(CMAKE_C_COMPILER ${GNU_C_COMPILER} CACHE STRING "Set C compiler")
|
||||
set(CMAKE_CXX_COMPILER ${GNU_CXX_COMPILER} CACHE STRING "Set C++ compiler")
|
||||
@@ -21,8 +21,8 @@
|
||||
//Auth includes:
|
||||
#include "AuthPackets.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "MessageType/Server.h"
|
||||
#include "MessageType/Auth.h"
|
||||
#include "eServerMessageType.h"
|
||||
#include "eAuthMessageType.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "Server.h"
|
||||
@@ -102,7 +102,7 @@ int main(int argc, char** argv) {
|
||||
uint32_t framesSinceLastSQLPing = 0;
|
||||
|
||||
AuthPackets::LoadClaimCodes();
|
||||
|
||||
|
||||
Game::logger->Flush(); // once immediately before main loop
|
||||
while (!Game::ShouldShutdown()) {
|
||||
//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 (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
|
||||
if (static_cast<MessageType::Server>(packet->data[3]) == MessageType::Server::VERSION_CONFIRM) {
|
||||
if (static_cast<eServerMessageType>(packet->data[3]) == eServerMessageType::VERSION_CONFIRM) {
|
||||
AuthPackets::HandleHandshake(Game::server, packet);
|
||||
}
|
||||
} else if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::AUTH) {
|
||||
if (static_cast<MessageType::Auth>(packet->data[3]) == MessageType::Auth::LOGIN_REQUEST) {
|
||||
if (static_cast<eAuthMessageType>(packet->data[3]) == eAuthMessageType::LOGIN_REQUEST) {
|
||||
AuthPackets::HandleLoginRequest(Game::server, packet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "ChatIgnoreList.h"
|
||||
#include "PlayerContainer.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include "eChatMessageType.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
@@ -13,7 +13,7 @@
|
||||
// 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) {
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receivingPlayer);
|
||||
|
||||
//portion that will get routed:
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
#include "dConfig.h"
|
||||
#include "eObjectBits.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include "MessageType/Client.h"
|
||||
#include "MessageType/Game.h"
|
||||
#include "eChatMessageType.h"
|
||||
#include "eClientMessageType.h"
|
||||
#include "eGameMessageType.h"
|
||||
#include "StringifiedEnum.h"
|
||||
#include "eGameMasterLevel.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:
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::GET_FRIENDS_LIST_RESPONSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
||||
bitStream.Write<uint8_t>(0);
|
||||
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
||||
bitStream.Write<uint16_t>(player.friends.size());
|
||||
@@ -368,10 +368,10 @@ void ChatPacketHandler::HandleWho(Packet* packet) {
|
||||
bool online = player;
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(request.requestor);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::WHO_RESPONSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::WHO_RESPONSE);
|
||||
bitStream.Write<uint8_t>(online);
|
||||
bitStream.Write(player.zoneID.GetMapID());
|
||||
bitStream.Write(player.zoneID.GetInstanceID());
|
||||
@@ -391,10 +391,10 @@ void ChatPacketHandler::HandleShowAll(Packet* packet) {
|
||||
if (!sender) return;
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(request.requestor);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::SHOW_ALL_RESPONSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::SHOW_ALL_RESPONSE);
|
||||
bitStream.Write<uint8_t>(!request.displayZoneData && !request.displayIndividualPlayers);
|
||||
bitStream.Write(Game::playerContainer.GetPlayerCount());
|
||||
bitStream.Write(Game::playerContainer.GetSimCount());
|
||||
@@ -416,7 +416,7 @@ void ChatPacketHandler::HandleShowAll(Packet* 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
|
||||
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
@@ -428,7 +428,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||
|
||||
eChatChannel channel;
|
||||
uint32_t size;
|
||||
|
||||
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(channel);
|
||||
inStream.Read(size);
|
||||
@@ -436,7 +436,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||
|
||||
LUWString message(size);
|
||||
inStream.Read(message);
|
||||
|
||||
|
||||
LOG("Got a message from (%s) via [%s]: %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str());
|
||||
|
||||
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
|
||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
@@ -484,7 +484,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||
|
||||
LUWString message(size);
|
||||
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());
|
||||
|
||||
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) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(routeTo.playerID);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::PRIVATE_CHAT_MESSAGE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||
bitStream.Write(sender.playerID);
|
||||
bitStream.Write(channel);
|
||||
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) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::TEAM_INVITE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
||||
|
||||
bitStream.Write(LUWString(sender.playerName.c_str()));
|
||||
bitStream.Write(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) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(receiver.playerID);
|
||||
bitStream.Write(MessageType::Game::TEAM_INVITE_CONFIRM);
|
||||
bitStream.Write(eGameMessageType::TEAM_INVITE_CONFIRM);
|
||||
|
||||
bitStream.Write(bLeaderIsFreeTrial);
|
||||
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) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(receiver.playerID);
|
||||
bitStream.Write(MessageType::Game::TEAM_GET_STATUS_RESPONSE);
|
||||
bitStream.Write(eGameMessageType::TEAM_GET_STATUS_RESPONSE);
|
||||
|
||||
bitStream.Write(i64LeaderID);
|
||||
bitStream.Write(i64LeaderZoneID);
|
||||
@@ -824,14 +824,14 @@ void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64L
|
||||
|
||||
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(receiver.playerID);
|
||||
bitStream.Write(MessageType::Game::TEAM_SET_LEADER);
|
||||
bitStream.Write(eGameMessageType::TEAM_SET_LEADER);
|
||||
|
||||
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) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(receiver.playerID);
|
||||
bitStream.Write(MessageType::Game::TEAM_ADD_PLAYER);
|
||||
bitStream.Write(eGameMessageType::TEAM_ADD_PLAYER);
|
||||
|
||||
bitStream.Write(bIsFreeTrial);
|
||||
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) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(receiver.playerID);
|
||||
bitStream.Write(MessageType::Game::TEAM_REMOVE_PLAYER);
|
||||
bitStream.Write(eGameMessageType::TEAM_REMOVE_PLAYER);
|
||||
|
||||
bitStream.Write(bDisband);
|
||||
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) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(receiver.playerID);
|
||||
bitStream.Write(MessageType::Game::TEAM_SET_OFF_WORLD_FLAG);
|
||||
bitStream.Write(eGameMessageType::TEAM_SET_OFF_WORLD_FLAG);
|
||||
|
||||
bitStream.Write(i64PlayerID);
|
||||
if (receiver.zoneID.GetCloneID() == zoneID.GetCloneID()) {
|
||||
@@ -930,11 +930,11 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
|
||||
[bool] - is FTP*/
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(friendData.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::UPDATE_FRIEND_NOTIFY);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
||||
bitStream.Write<uint8_t>(notifyType);
|
||||
|
||||
std::string playerName = playerData.playerName.c_str();
|
||||
@@ -967,11 +967,11 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
|
||||
}
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::ADD_FRIEND_REQUEST);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
||||
bitStream.Write(LUWString(sender.playerName));
|
||||
bitStream.Write<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) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
// Portion that will get routed:
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::ADD_FRIEND_RESPONSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
||||
bitStream.Write(responseCode);
|
||||
// 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);
|
||||
@@ -1004,11 +1004,11 @@ void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const Pla
|
||||
|
||||
void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||
bitStream.Write(receiver.playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::REMOVE_FRIEND_RESPONSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
||||
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
||||
bitStream.Write(LUWString(personToRemove));
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include "eConnectionType.h"
|
||||
#include "PlayerContainer.h"
|
||||
#include "ChatPacketHandler.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include "MessageType/World.h"
|
||||
#include "eChatMessageType.h"
|
||||
#include "eWorldMessageType.h"
|
||||
#include "ChatIgnoreList.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
@@ -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);
|
||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
||||
|
||||
|
||||
Game::randomEngine = std::mt19937(time(0));
|
||||
|
||||
Game::playerContainer.Initialize();
|
||||
@@ -179,7 +179,6 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
void HandlePacket(Packet* packet) {
|
||||
if (packet->length < 1) return;
|
||||
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.");
|
||||
} else if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
||||
@@ -190,154 +189,154 @@ void HandlePacket(Packet* packet) {
|
||||
inStream.SetReadOffset(BYTES_TO_BITS(1));
|
||||
|
||||
eConnectionType connection;
|
||||
MessageType::Chat chatMessageID;
|
||||
eChatMessageType chatMessageID;
|
||||
|
||||
inStream.Read(connection);
|
||||
if (connection != eConnectionType::CHAT) return;
|
||||
inStream.Read(chatMessageID);
|
||||
|
||||
|
||||
switch (chatMessageID) {
|
||||
case MessageType::Chat::GM_MUTE:
|
||||
case eChatMessageType::GM_MUTE:
|
||||
Game::playerContainer.MuteUpdate(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::CREATE_TEAM:
|
||||
case eChatMessageType::CREATE_TEAM:
|
||||
Game::playerContainer.CreateTeamServer(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::GET_FRIENDS_LIST:
|
||||
case eChatMessageType::GET_FRIENDS_LIST:
|
||||
ChatPacketHandler::HandleFriendlistRequest(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::GET_IGNORE_LIST:
|
||||
case eChatMessageType::GET_IGNORE_LIST:
|
||||
ChatIgnoreList::GetIgnoreList(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::ADD_IGNORE:
|
||||
case eChatMessageType::ADD_IGNORE:
|
||||
ChatIgnoreList::AddIgnore(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::REMOVE_IGNORE:
|
||||
case eChatMessageType::REMOVE_IGNORE:
|
||||
ChatIgnoreList::RemoveIgnore(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::TEAM_GET_STATUS:
|
||||
case eChatMessageType::TEAM_GET_STATUS:
|
||||
ChatPacketHandler::HandleTeamStatusRequest(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::ADD_FRIEND_REQUEST:
|
||||
case eChatMessageType::ADD_FRIEND_REQUEST:
|
||||
//this involves someone sending the initial request, the response is below, response as in from the other player.
|
||||
//We basically just check to see if this player is online or not and route the packet.
|
||||
ChatPacketHandler::HandleFriendRequest(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::ADD_FRIEND_RESPONSE:
|
||||
case eChatMessageType::ADD_FRIEND_RESPONSE:
|
||||
//This isn't the response a server sent, rather it is a player's response to a received request.
|
||||
//Here, we'll actually have to add them to eachother's friend lists depending on the response code.
|
||||
ChatPacketHandler::HandleFriendResponse(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::REMOVE_FRIEND:
|
||||
case eChatMessageType::REMOVE_FRIEND:
|
||||
ChatPacketHandler::HandleRemoveFriend(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::GENERAL_CHAT_MESSAGE:
|
||||
case eChatMessageType::GENERAL_CHAT_MESSAGE:
|
||||
ChatPacketHandler::HandleChatMessage(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::PRIVATE_CHAT_MESSAGE:
|
||||
case eChatMessageType::PRIVATE_CHAT_MESSAGE:
|
||||
//This message is supposed to be echo'd to both the sender and the receiver
|
||||
//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);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::TEAM_INVITE:
|
||||
case eChatMessageType::TEAM_INVITE:
|
||||
ChatPacketHandler::HandleTeamInvite(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::TEAM_INVITE_RESPONSE:
|
||||
case eChatMessageType::TEAM_INVITE_RESPONSE:
|
||||
ChatPacketHandler::HandleTeamInviteResponse(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::TEAM_LEAVE:
|
||||
case eChatMessageType::TEAM_LEAVE:
|
||||
ChatPacketHandler::HandleTeamLeave(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::TEAM_SET_LEADER:
|
||||
case eChatMessageType::TEAM_SET_LEADER:
|
||||
ChatPacketHandler::HandleTeamPromote(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::TEAM_KICK:
|
||||
case eChatMessageType::TEAM_KICK:
|
||||
ChatPacketHandler::HandleTeamKick(packet);
|
||||
break;
|
||||
|
||||
case MessageType::Chat::TEAM_SET_LOOT:
|
||||
case eChatMessageType::TEAM_SET_LOOT:
|
||||
ChatPacketHandler::HandleTeamLootOption(packet);
|
||||
break;
|
||||
case MessageType::Chat::GMLEVEL_UPDATE:
|
||||
case eChatMessageType::GMLEVEL_UPDATE:
|
||||
ChatPacketHandler::HandleGMLevelUpdate(packet);
|
||||
break;
|
||||
case MessageType::Chat::LOGIN_SESSION_NOTIFY:
|
||||
case eChatMessageType::LOGIN_SESSION_NOTIFY:
|
||||
Game::playerContainer.InsertPlayer(packet);
|
||||
break;
|
||||
case MessageType::Chat::GM_ANNOUNCE:{
|
||||
case eChatMessageType::GM_ANNOUNCE:{
|
||||
// we just forward this packet to every connected server
|
||||
inStream.ResetReadPointer();
|
||||
Game::server->Send(inStream, packet->systemAddress, true); // send to everyone except origin
|
||||
}
|
||||
break;
|
||||
case MessageType::Chat::UNEXPECTED_DISCONNECT:
|
||||
case eChatMessageType::UNEXPECTED_DISCONNECT:
|
||||
Game::playerContainer.RemovePlayer(packet);
|
||||
break;
|
||||
case MessageType::Chat::WHO:
|
||||
case eChatMessageType::WHO:
|
||||
ChatPacketHandler::HandleWho(packet);
|
||||
break;
|
||||
case MessageType::Chat::SHOW_ALL:
|
||||
case eChatMessageType::SHOW_ALL:
|
||||
ChatPacketHandler::HandleShowAll(packet);
|
||||
break;
|
||||
case MessageType::Chat::USER_CHANNEL_CHAT_MESSAGE:
|
||||
case MessageType::Chat::WORLD_DISCONNECT_REQUEST:
|
||||
case MessageType::Chat::WORLD_PROXIMITY_RESPONSE:
|
||||
case MessageType::Chat::WORLD_PARCEL_RESPONSE:
|
||||
case MessageType::Chat::TEAM_MISSED_INVITE_CHECK:
|
||||
case MessageType::Chat::GUILD_CREATE:
|
||||
case MessageType::Chat::GUILD_INVITE:
|
||||
case MessageType::Chat::GUILD_INVITE_RESPONSE:
|
||||
case MessageType::Chat::GUILD_LEAVE:
|
||||
case MessageType::Chat::GUILD_KICK:
|
||||
case MessageType::Chat::GUILD_GET_STATUS:
|
||||
case MessageType::Chat::GUILD_GET_ALL:
|
||||
case MessageType::Chat::BLUEPRINT_MODERATED:
|
||||
case MessageType::Chat::BLUEPRINT_MODEL_READY:
|
||||
case MessageType::Chat::PROPERTY_READY_FOR_APPROVAL:
|
||||
case MessageType::Chat::PROPERTY_MODERATION_CHANGED:
|
||||
case MessageType::Chat::PROPERTY_BUILDMODE_CHANGED:
|
||||
case MessageType::Chat::PROPERTY_BUILDMODE_CHANGED_REPORT:
|
||||
case MessageType::Chat::MAIL:
|
||||
case MessageType::Chat::WORLD_INSTANCE_LOCATION_REQUEST:
|
||||
case MessageType::Chat::REPUTATION_UPDATE:
|
||||
case MessageType::Chat::SEND_CANNED_TEXT:
|
||||
case MessageType::Chat::CHARACTER_NAME_CHANGE_REQUEST:
|
||||
case MessageType::Chat::CSR_REQUEST:
|
||||
case MessageType::Chat::CSR_REPLY:
|
||||
case MessageType::Chat::GM_KICK:
|
||||
case MessageType::Chat::WORLD_ROUTE_PACKET:
|
||||
case MessageType::Chat::GET_ZONE_POPULATIONS:
|
||||
case MessageType::Chat::REQUEST_MINIMUM_CHAT_MODE:
|
||||
case MessageType::Chat::MATCH_REQUEST:
|
||||
case MessageType::Chat::UGCMANIFEST_REPORT_MISSING_FILE:
|
||||
case MessageType::Chat::UGCMANIFEST_REPORT_DONE_FILE:
|
||||
case MessageType::Chat::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
||||
case MessageType::Chat::UGCC_REQUEST:
|
||||
case MessageType::Chat::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
||||
case MessageType::Chat::ACHIEVEMENT_NOTIFY:
|
||||
case MessageType::Chat::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
||||
case MessageType::Chat::PLAYER_READY:
|
||||
case MessageType::Chat::GET_DONATION_TOTAL:
|
||||
case MessageType::Chat::UPDATE_DONATION:
|
||||
case MessageType::Chat::PRG_CSR_COMMAND:
|
||||
case MessageType::Chat::HEARTBEAT_REQUEST_FROM_WORLD:
|
||||
case MessageType::Chat::UPDATE_FREE_TRIAL_STATUS:
|
||||
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
|
||||
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
|
||||
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
|
||||
case eChatMessageType::WORLD_PARCEL_RESPONSE:
|
||||
case eChatMessageType::TEAM_MISSED_INVITE_CHECK:
|
||||
case eChatMessageType::GUILD_CREATE:
|
||||
case eChatMessageType::GUILD_INVITE:
|
||||
case eChatMessageType::GUILD_INVITE_RESPONSE:
|
||||
case eChatMessageType::GUILD_LEAVE:
|
||||
case eChatMessageType::GUILD_KICK:
|
||||
case eChatMessageType::GUILD_GET_STATUS:
|
||||
case eChatMessageType::GUILD_GET_ALL:
|
||||
case eChatMessageType::BLUEPRINT_MODERATED:
|
||||
case eChatMessageType::BLUEPRINT_MODEL_READY:
|
||||
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
|
||||
case eChatMessageType::PROPERTY_MODERATION_CHANGED:
|
||||
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED:
|
||||
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED_REPORT:
|
||||
case eChatMessageType::MAIL:
|
||||
case eChatMessageType::WORLD_INSTANCE_LOCATION_REQUEST:
|
||||
case eChatMessageType::REPUTATION_UPDATE:
|
||||
case eChatMessageType::SEND_CANNED_TEXT:
|
||||
case eChatMessageType::CHARACTER_NAME_CHANGE_REQUEST:
|
||||
case eChatMessageType::CSR_REQUEST:
|
||||
case eChatMessageType::CSR_REPLY:
|
||||
case eChatMessageType::GM_KICK:
|
||||
case eChatMessageType::WORLD_ROUTE_PACKET:
|
||||
case eChatMessageType::GET_ZONE_POPULATIONS:
|
||||
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
|
||||
case eChatMessageType::MATCH_REQUEST:
|
||||
case eChatMessageType::UGCMANIFEST_REPORT_MISSING_FILE:
|
||||
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
|
||||
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
||||
case eChatMessageType::UGCC_REQUEST:
|
||||
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
||||
case eChatMessageType::ACHIEVEMENT_NOTIFY:
|
||||
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
||||
case eChatMessageType::PLAYER_READY:
|
||||
case eChatMessageType::GET_DONATION_TOTAL:
|
||||
case eChatMessageType::UPDATE_DONATION:
|
||||
case eChatMessageType::PRG_CSR_COMMAND:
|
||||
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
|
||||
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
|
||||
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "eConnectionType.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "dConfig.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include "eChatMessageType.h"
|
||||
|
||||
void PlayerContainer::Initialize() {
|
||||
m_MaxNumberOfBestFriends =
|
||||
@@ -36,19 +36,16 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||
data.playerID = playerId;
|
||||
|
||||
uint32_t len;
|
||||
if (!inStream.Read<uint32_t>(len)) return;
|
||||
inStream.Read<uint32_t>(len);
|
||||
|
||||
if (len > 33) {
|
||||
LOG("Received a really long player name, probably a fake packet %i.", len);
|
||||
return;
|
||||
for (int i = 0; i < len; i++) {
|
||||
char character; inStream.Read<char>(character);
|
||||
data.playerName += character;
|
||||
}
|
||||
|
||||
data.playerName.resize(len);
|
||||
inStream.ReadAlignedBytes(reinterpret_cast<unsigned char*>(data.playerName.data()), len);
|
||||
|
||||
if (!inStream.Read(data.zoneID)) return;
|
||||
if (!inStream.Read(data.muteExpire)) return;
|
||||
if (!inStream.Read(data.gmLevel)) return;
|
||||
inStream.Read(data.zoneID);
|
||||
inStream.Read(data.muteExpire);
|
||||
inStream.Read(data.gmLevel);
|
||||
data.sysAddr = packet->systemAddress;
|
||||
|
||||
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
|
||||
@@ -125,11 +122,6 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
||||
size_t membersSize = 0;
|
||||
inStream.Read(membersSize);
|
||||
|
||||
if (membersSize >= 4) {
|
||||
LOG("Tried to create a team with more than 4 players");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> members;
|
||||
|
||||
members.reserve(membersSize);
|
||||
@@ -148,13 +140,14 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
||||
|
||||
if (team != nullptr) {
|
||||
team->zoneId = zoneId;
|
||||
UpdateTeamsOnWorld(team, false);
|
||||
}
|
||||
|
||||
UpdateTeamsOnWorld(team, false);
|
||||
}
|
||||
|
||||
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::GM_MUTE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GM_MUTE);
|
||||
|
||||
bitStream.Write(player);
|
||||
bitStream.Write(time);
|
||||
@@ -361,7 +354,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
||||
|
||||
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::TEAM_GET_STATUS);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::TEAM_GET_STATUS);
|
||||
|
||||
bitStream.Write(team->teamID);
|
||||
bitStream.Write(deleteTeam);
|
||||
|
||||
@@ -9,54 +9,73 @@
|
||||
* AMF3 Deserializer written by EmosewaMC
|
||||
*/
|
||||
|
||||
std::unique_ptr<AMFBaseValue> AMFDeserialize::Read(RakNet::BitStream& inStream) {
|
||||
AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream& inStream) {
|
||||
AMFBaseValue* returnValue = nullptr;
|
||||
// Read in the value type from the bitStream
|
||||
eAmf marker;
|
||||
inStream.Read(marker);
|
||||
// Based on the typing, create the value associated with that and return the base value class
|
||||
switch (marker) {
|
||||
case eAmf::Undefined:
|
||||
return std::make_unique<AMFBaseValue>();
|
||||
case eAmf::Null:
|
||||
return std::make_unique<AMFNullValue>();
|
||||
case eAmf::False:
|
||||
return std::make_unique<AMFBoolValue>(false);
|
||||
case eAmf::True:
|
||||
return std::make_unique<AMFBoolValue>(true);
|
||||
case eAmf::Integer:
|
||||
return ReadAmfInteger(inStream);
|
||||
case eAmf::Double:
|
||||
return ReadAmfDouble(inStream);
|
||||
case eAmf::String:
|
||||
return ReadAmfString(inStream);
|
||||
case eAmf::Array:
|
||||
return ReadAmfArray(inStream);
|
||||
case eAmf::Undefined: {
|
||||
returnValue = new AMFBaseValue();
|
||||
break;
|
||||
}
|
||||
|
||||
case eAmf::Null: {
|
||||
returnValue = new AMFNullValue();
|
||||
break;
|
||||
}
|
||||
|
||||
case eAmf::False: {
|
||||
returnValue = new AMFBoolValue(false);
|
||||
break;
|
||||
}
|
||||
|
||||
case eAmf::True: {
|
||||
returnValue = new AMFBoolValue(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case eAmf::Integer: {
|
||||
returnValue = ReadAmfInteger(inStream);
|
||||
break;
|
||||
}
|
||||
|
||||
case eAmf::Double: {
|
||||
returnValue = ReadAmfDouble(inStream);
|
||||
break;
|
||||
}
|
||||
|
||||
case eAmf::String: {
|
||||
returnValue = ReadAmfString(inStream);
|
||||
break;
|
||||
}
|
||||
|
||||
case eAmf::Array: {
|
||||
returnValue = ReadAmfArray(inStream);
|
||||
break;
|
||||
}
|
||||
|
||||
// These values are unimplemented in the live client and will remain unimplemented
|
||||
// unless someone modifies the client to allow serializing of these values.
|
||||
case eAmf::XMLDoc:
|
||||
[[fallthrough]];
|
||||
case eAmf::Date:
|
||||
[[fallthrough]];
|
||||
case eAmf::Object:
|
||||
[[fallthrough]];
|
||||
case eAmf::XML:
|
||||
[[fallthrough]];
|
||||
case eAmf::ByteArray:
|
||||
[[fallthrough]];
|
||||
case eAmf::VectorInt:
|
||||
[[fallthrough]];
|
||||
case eAmf::VectorUInt:
|
||||
[[fallthrough]];
|
||||
case eAmf::VectorDouble:
|
||||
[[fallthrough]];
|
||||
case eAmf::VectorObject:
|
||||
[[fallthrough]];
|
||||
case eAmf::Dictionary:
|
||||
case eAmf::Dictionary: {
|
||||
throw marker;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
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) {
|
||||
@@ -99,14 +118,14 @@ const std::string AMFDeserialize::ReadString(RakNet::BitStream& inStream) {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<AMFDoubleValue> AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) {
|
||||
AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) {
|
||||
double value;
|
||||
inStream.Read<double>(value);
|
||||
return std::make_unique<AMFDoubleValue>(value);
|
||||
return new AMFDoubleValue(value);
|
||||
}
|
||||
|
||||
std::unique_ptr<AMFArrayValue> AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) {
|
||||
auto arrayValue = std::make_unique<AMFArrayValue>();
|
||||
AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) {
|
||||
auto arrayValue = new AMFArrayValue();
|
||||
|
||||
// Read size of dense array
|
||||
const auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
||||
@@ -124,10 +143,10 @@ std::unique_ptr<AMFArrayValue> AMFDeserialize::ReadAmfArray(RakNet::BitStream& i
|
||||
return arrayValue;
|
||||
}
|
||||
|
||||
std::unique_ptr<AMFStringValue> AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) {
|
||||
return std::make_unique<AMFStringValue>(ReadString(inStream));
|
||||
AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) {
|
||||
return new AMFStringValue(ReadString(inStream));
|
||||
}
|
||||
|
||||
std::unique_ptr<AMFIntValue> AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) {
|
||||
return std::make_unique<AMFIntValue>(ReadU29(inStream)); // NOTE: NARROWING CONVERSION FROM UINT TO INT. IS THIS INTENDED?
|
||||
AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) {
|
||||
return new AMFIntValue(ReadU29(inStream));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Amf3.h"
|
||||
#include "BitStream.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class AMFBaseValue;
|
||||
|
||||
class AMFDeserialize {
|
||||
public:
|
||||
/**
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
* @param inStream inStream to read value from.
|
||||
* @return Returns an AMFValue with all the information from the bitStream in it.
|
||||
*/
|
||||
std::unique_ptr<AMFBaseValue> Read(RakNet::BitStream& inStream);
|
||||
AMFBaseValue* Read(RakNet::BitStream& inStream);
|
||||
private:
|
||||
/**
|
||||
* @brief Private method to read a U29 integer from a bitstream
|
||||
@@ -39,7 +39,7 @@ private:
|
||||
* @param inStream bitStream to read data from
|
||||
* @return Double value represented as an AMFValue
|
||||
*/
|
||||
static std::unique_ptr<AMFDoubleValue> ReadAmfDouble(RakNet::BitStream& inStream);
|
||||
AMFBaseValue* ReadAmfDouble(RakNet::BitStream& inStream);
|
||||
|
||||
/**
|
||||
* @brief Read an AMFArray from a bitStream
|
||||
@@ -47,7 +47,7 @@ private:
|
||||
* @param inStream bitStream to read data from
|
||||
* @return Array value represented as an AMFValue
|
||||
*/
|
||||
std::unique_ptr<AMFArrayValue> ReadAmfArray(RakNet::BitStream& inStream);
|
||||
AMFBaseValue* ReadAmfArray(RakNet::BitStream& inStream);
|
||||
|
||||
/**
|
||||
* @brief Read an AMFString from a bitStream
|
||||
@@ -55,7 +55,7 @@ private:
|
||||
* @param inStream bitStream to read data from
|
||||
* @return String value represented as an AMFValue
|
||||
*/
|
||||
std::unique_ptr<AMFStringValue> ReadAmfString(RakNet::BitStream& inStream);
|
||||
AMFBaseValue* ReadAmfString(RakNet::BitStream& inStream);
|
||||
|
||||
/**
|
||||
* @brief Read an AMFInteger from a bitStream
|
||||
@@ -63,7 +63,7 @@ private:
|
||||
* @param inStream bitStream to read data from
|
||||
* @return Integer value represented as an AMFValue
|
||||
*/
|
||||
static std::unique_ptr<AMFIntValue> ReadAmfInteger(RakNet::BitStream& inStream);
|
||||
AMFBaseValue* ReadAmfInteger(RakNet::BitStream& inStream);
|
||||
|
||||
/**
|
||||
* List of strings read so far saved to be read by reference.
|
||||
|
||||
@@ -105,14 +105,27 @@ using AMFDoubleValue = AMFValue<double>;
|
||||
* and are not to be deleted by a caller.
|
||||
*/
|
||||
class AMFArrayValue : public AMFBaseValue {
|
||||
using AMFAssociative =
|
||||
std::unordered_map<std::string, std::unique_ptr<AMFBaseValue>, GeneralUtils::transparent_string_hash, std::equal_to<>>;
|
||||
|
||||
using AMFDense = std::vector<std::unique_ptr<AMFBaseValue>>;
|
||||
using AMFAssociative = std::unordered_map<std::string, AMFBaseValue*>;
|
||||
using AMFDense = std::vector<AMFBaseValue*>;
|
||||
|
||||
public:
|
||||
[[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
|
||||
*/
|
||||
@@ -138,32 +151,30 @@ public:
|
||||
* or nullptr if a key existed and was not the same type
|
||||
*/
|
||||
template <typename ValueType>
|
||||
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string_view key, const ValueType value) {
|
||||
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, const ValueType value) {
|
||||
const auto element = m_Associative.find(key);
|
||||
AMFValue<ValueType>* val = nullptr;
|
||||
bool found = true;
|
||||
if (element == m_Associative.cend()) {
|
||||
auto newVal = std::make_unique<AMFValue<ValueType>>(value);
|
||||
val = newVal.get();
|
||||
m_Associative.emplace(key, std::move(newVal));
|
||||
val = new AMFValue<ValueType>(value);
|
||||
m_Associative.emplace(key, val);
|
||||
} else {
|
||||
val = dynamic_cast<AMFValue<ValueType>*>(element->second.get());
|
||||
val = dynamic_cast<AMFValue<ValueType>*>(element->second);
|
||||
found = false;
|
||||
}
|
||||
return std::make_pair(val, found);
|
||||
}
|
||||
|
||||
// Associates an array with a string key
|
||||
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string_view key) {
|
||||
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
|
||||
const auto element = m_Associative.find(key);
|
||||
AMFArrayValue* val = nullptr;
|
||||
bool found = true;
|
||||
if (element == m_Associative.cend()) {
|
||||
auto newVal = std::make_unique<AMFArrayValue>();
|
||||
val = newVal.get();
|
||||
m_Associative.emplace(key, std::move(newVal));
|
||||
val = new AMFArrayValue();
|
||||
m_Associative.emplace(key, val);
|
||||
} else {
|
||||
val = dynamic_cast<AMFArrayValue*>(element->second.get());
|
||||
val = dynamic_cast<AMFArrayValue*>(element->second);
|
||||
found = false;
|
||||
}
|
||||
return std::make_pair(val, found);
|
||||
@@ -171,13 +182,15 @@ public:
|
||||
|
||||
// Associates an array with an integer key
|
||||
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const size_t index) {
|
||||
AMFArrayValue* val = nullptr;
|
||||
bool inserted = false;
|
||||
if (index >= m_Dense.size()) {
|
||||
m_Dense.resize(index + 1);
|
||||
m_Dense.at(index) = std::make_unique<AMFArrayValue>();
|
||||
val = new AMFArrayValue();
|
||||
m_Dense.at(index) = val;
|
||||
inserted = true;
|
||||
}
|
||||
return std::make_pair(dynamic_cast<AMFArrayValue*>(m_Dense.at(index).get()), inserted);
|
||||
return std::make_pair(dynamic_cast<AMFArrayValue*>(m_Dense.at(index)), inserted);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,13 +205,15 @@ public:
|
||||
*/
|
||||
template <typename ValueType>
|
||||
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const size_t index, const ValueType value) {
|
||||
AMFValue<ValueType>* val = nullptr;
|
||||
bool inserted = false;
|
||||
if (index >= m_Dense.size()) {
|
||||
m_Dense.resize(index + 1);
|
||||
m_Dense.at(index) = std::make_unique<AMFValue<ValueType>>(value);
|
||||
val = new AMFValue<ValueType>(value);
|
||||
m_Dense.at(index) = val;
|
||||
inserted = true;
|
||||
}
|
||||
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(m_Dense.at(index).get()), inserted);
|
||||
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(m_Dense.at(index)), inserted);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,12 +225,13 @@ public:
|
||||
* @param key The key to associate with the value
|
||||
* @param value The value to insert
|
||||
*/
|
||||
void Insert(const std::string_view key, std::unique_ptr<AMFBaseValue> value) {
|
||||
void Insert(const std::string& key, AMFBaseValue* const value) {
|
||||
const auto element = m_Associative.find(key);
|
||||
if (element != m_Associative.cend() && element->second) {
|
||||
element->second = std::move(value);
|
||||
delete element->second;
|
||||
element->second = value;
|
||||
} else {
|
||||
m_Associative.emplace(key, std::move(value));
|
||||
m_Associative.emplace(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,11 +244,14 @@ public:
|
||||
* @param key The key to associate with the value
|
||||
* @param value The value to insert
|
||||
*/
|
||||
void Insert(const size_t index, std::unique_ptr<AMFBaseValue> value) {
|
||||
if (index >= m_Dense.size()) {
|
||||
void Insert(const size_t index, AMFBaseValue* const value) {
|
||||
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.at(index) = std::move(value);
|
||||
m_Dense.at(index) = value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,7 +279,8 @@ public:
|
||||
void Remove(const std::string& key, const bool deleteValue = true) {
|
||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||
if (it != m_Associative.cend()) {
|
||||
if (deleteValue) m_Associative.erase(it);
|
||||
if (deleteValue) delete it->second;
|
||||
m_Associative.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +290,7 @@ public:
|
||||
void Remove(const size_t index) {
|
||||
if (!m_Dense.empty() && index < m_Dense.size()) {
|
||||
const auto itr = m_Dense.cbegin() + index;
|
||||
if (*itr) delete (*itr);
|
||||
m_Dense.erase(itr);
|
||||
}
|
||||
}
|
||||
@@ -278,16 +299,16 @@ public:
|
||||
if (!m_Dense.empty()) Remove(m_Dense.size() - 1);
|
||||
}
|
||||
|
||||
[[nodiscard]] AMFArrayValue* GetArray(const std::string_view key) const {
|
||||
[[nodiscard]] AMFArrayValue* GetArray(const std::string& key) const {
|
||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||
return it != m_Associative.cend() ? dynamic_cast<AMFArrayValue*>(it->second.get()) : nullptr;
|
||||
return it != m_Associative.cend() ? dynamic_cast<AMFArrayValue*>(it->second) : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] AMFArrayValue* GetArray(const size_t index) const {
|
||||
return index < m_Dense.size() ? dynamic_cast<AMFArrayValue*>(m_Dense.at(index).get()) : nullptr;
|
||||
return index < m_Dense.size() ? dynamic_cast<AMFArrayValue*>(m_Dense.at(index)) : nullptr;
|
||||
}
|
||||
|
||||
[[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string_view key) {
|
||||
[[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string& key) {
|
||||
return static_cast<AMFArrayValue*>(Insert(key).first);
|
||||
}
|
||||
|
||||
@@ -309,17 +330,17 @@ public:
|
||||
* @return The AMFValue
|
||||
*/
|
||||
template <typename AmfType>
|
||||
[[nodiscard]] AMFValue<AmfType>* Get(const std::string_view key) const {
|
||||
[[nodiscard]] AMFValue<AmfType>* Get(const std::string& key) const {
|
||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||
return it != m_Associative.cend() ?
|
||||
dynamic_cast<AMFValue<AmfType>*>(it->second.get()) :
|
||||
dynamic_cast<AMFValue<AmfType>*>(it->second) :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
// Get from the array but dont cast it
|
||||
[[nodiscard]] AMFBaseValue* Get(const std::string_view key) const {
|
||||
[[nodiscard]] AMFBaseValue* Get(const std::string& key) const {
|
||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||
return it != m_Associative.cend() ? it->second.get() : nullptr;
|
||||
return it != m_Associative.cend() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,13 +355,13 @@ public:
|
||||
template <typename AmfType>
|
||||
[[nodiscard]] AMFValue<AmfType>* Get(const size_t index) const {
|
||||
return index < m_Dense.size() ?
|
||||
dynamic_cast<AMFValue<AmfType>*>(m_Dense.at(index).get()) :
|
||||
dynamic_cast<AMFValue<AmfType>*>(m_Dense.at(index)) :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
// Get from the dense but dont cast it
|
||||
[[nodiscard]] AMFBaseValue* Get(const size_t index) const {
|
||||
return index < m_Dense.size() ? m_Dense.at(index).get() : nullptr;
|
||||
return index < m_Dense.size() ? m_Dense.at(index) : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -45,14 +45,11 @@ if (UNIX)
|
||||
elseif (WIN32)
|
||||
include(FetchContent)
|
||||
|
||||
set(WITH_GTEST OFF CACHE BOOL "" FORCE)
|
||||
set(ZLIB_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
|
||||
|
||||
# TODO Keep an eye on the zlib repository for an update to disable testing. Don't forget to update CMakePresets
|
||||
FetchContent_Declare(
|
||||
zlib
|
||||
URL https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.2.2.zip
|
||||
URL_HASH MD5=2cf9199fb785ea579a2a9905a75c38b3
|
||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
||||
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
|
||||
)
|
||||
|
||||
# Disable warning about no project version.
|
||||
@@ -63,6 +60,7 @@ elseif (WIN32)
|
||||
FetchContent_MakeAvailable(zlib)
|
||||
|
||||
set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
|
||||
set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}")
|
||||
add_library(ZLIB::ZLIB ALIAS zlib)
|
||||
else ()
|
||||
message(
|
||||
|
||||
@@ -201,7 +201,7 @@ void OnTerminate() {
|
||||
}
|
||||
|
||||
void MakeBacktrace() {
|
||||
struct sigaction sigact{};
|
||||
struct sigaction sigact;
|
||||
|
||||
sigact.sa_sigaction = CritErrHdlr;
|
||||
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
|
||||
@@ -129,29 +129,6 @@ namespace GeneralUtils {
|
||||
|
||||
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
|
||||
template <typename T>
|
||||
concept Enum = std::is_enum_v<T>;
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#ifndef __IMPLEMENTATION_H__
|
||||
#define __IMPLEMENTATION_H__
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
/**
|
||||
* @brief A way to defer the implementation of an action.
|
||||
*
|
||||
* @tparam R The result of the action.
|
||||
* @tparam T The types of the arguments that the implementation requires.
|
||||
*/
|
||||
template <typename R, typename... T>
|
||||
class Implementation {
|
||||
public:
|
||||
typedef std::function<std::optional<R>(T...)> ImplementationFunction;
|
||||
|
||||
/**
|
||||
* @brief Sets the implementation of the action.
|
||||
*
|
||||
* @param implementation The implementation of the action.
|
||||
*/
|
||||
void SetImplementation(const ImplementationFunction& implementation) {
|
||||
this->implementation = implementation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the implementation of the action.
|
||||
*/
|
||||
void ClearImplementation() {
|
||||
implementation.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the implementation is set.
|
||||
*
|
||||
* @return true If the implementation is set.
|
||||
* @return false If the implementation is not set.
|
||||
*/
|
||||
bool IsSet() const {
|
||||
return implementation.has_value();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Executes the implementation if it is set.
|
||||
*
|
||||
* @param args The arguments to pass to the implementation.
|
||||
* @return std::optional<R> The optional result of the implementation. If the result is not set, it indicates that the default action should be taken.
|
||||
*/
|
||||
std::optional<R> Execute(T... args) const {
|
||||
return IsSet() ? implementation.value()(args...) : std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exectues the implementation if it is set, otherwise returns a default value.
|
||||
*
|
||||
* @param args The arguments to pass to the implementation.
|
||||
* @param defaultValue The default value to return if the implementation is not set or should not be deferred.
|
||||
*/
|
||||
R ExecuteWithDefault(T... args, const R& defaultValue) const {
|
||||
return Execute(args...).value_or(defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* = operator overload.
|
||||
*/
|
||||
Implementation& operator=(const Implementation& other) {
|
||||
implementation = other.implementation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* = operator overload.
|
||||
*/
|
||||
Implementation& operator=(const ImplementationFunction& implementation) {
|
||||
this->implementation = implementation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* () operator overload.
|
||||
*/
|
||||
std::optional<R> operator()(T... args) {
|
||||
return !IsSet() ? std::nullopt : implementation(args...);
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<ImplementationFunction> implementation;
|
||||
|
||||
};
|
||||
|
||||
#endif //!__IMPLEMENTATION_H__
|
||||
@@ -1,73 +0,0 @@
|
||||
#ifndef __OBSERVABLE_H__
|
||||
#define __OBSERVABLE_H__
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
/**
|
||||
* @brief An event which can be observed by multiple observers.
|
||||
*
|
||||
* @tparam T The types of the arguments to be passed to the observers.
|
||||
*/
|
||||
template <typename... T>
|
||||
class Observable {
|
||||
public:
|
||||
typedef std::function<void(T...)> Observer;
|
||||
|
||||
/**
|
||||
* @brief Adds an observer to the event.
|
||||
*
|
||||
* @param observer The observer to add.
|
||||
*/
|
||||
void AddObserver(const Observer& observer) {
|
||||
observers.push_back(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes an observer from the event.
|
||||
*
|
||||
* @param observer The observer to remove.
|
||||
*/
|
||||
void RemoveObserver(const Observer& observer) {
|
||||
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notifies all observers of the event.
|
||||
*
|
||||
* @param args The arguments to pass to the observers.
|
||||
*/
|
||||
void Notify(T... args) {
|
||||
for (const auto& observer : observers) {
|
||||
observer(args...);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* += operator overload.
|
||||
*/
|
||||
Observable& operator+=(const Observer& observer) {
|
||||
AddObserver(observer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* -= operator overload.
|
||||
*/
|
||||
Observable& operator-=(const Observer& observer) {
|
||||
RemoveObserver(observer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* () operator overload.
|
||||
*/
|
||||
void operator()(T... args) {
|
||||
Notify(args...);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Observer> observers;
|
||||
};
|
||||
|
||||
#endif //!__OBSERVABLE_H__
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "ZCompression.h"
|
||||
|
||||
#include "zlib-ng.h"
|
||||
#include "zlib.h"
|
||||
|
||||
namespace ZCompression {
|
||||
int32_t GetMaxCompressedLength(int32_t nLenSrc) {
|
||||
@@ -9,41 +9,41 @@ namespace ZCompression {
|
||||
}
|
||||
|
||||
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst) {
|
||||
zng_stream zInfo = { 0 };
|
||||
z_stream zInfo = { 0 };
|
||||
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
||||
zInfo.total_out = zInfo.avail_out = nLenDst;
|
||||
zInfo.next_in = const_cast<Bytef*>(abSrc);
|
||||
zInfo.next_out = abDst;
|
||||
|
||||
int nErr, nRet = -1;
|
||||
nErr = zng_deflateInit(&zInfo, Z_DEFAULT_COMPRESSION); // zlib function
|
||||
nErr = deflateInit(&zInfo, Z_DEFAULT_COMPRESSION); // zlib function
|
||||
if (nErr == Z_OK) {
|
||||
nErr = zng_deflate(&zInfo, Z_FINISH); // zlib function
|
||||
nErr = deflate(&zInfo, Z_FINISH); // zlib function
|
||||
if (nErr == Z_STREAM_END) {
|
||||
nRet = zInfo.total_out;
|
||||
}
|
||||
}
|
||||
zng_deflateEnd(&zInfo); // zlib function
|
||||
deflateEnd(&zInfo); // zlib function
|
||||
return(nRet);
|
||||
}
|
||||
|
||||
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr) {
|
||||
// Get the size of the decompressed data
|
||||
zng_stream zInfo = { 0 };
|
||||
z_stream zInfo = { 0 };
|
||||
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
||||
zInfo.total_out = zInfo.avail_out = nLenDst;
|
||||
zInfo.next_in = const_cast<Bytef*>(abSrc);
|
||||
zInfo.next_out = abDst;
|
||||
|
||||
int nRet = -1;
|
||||
nErr = zng_inflateInit(&zInfo); // zlib function
|
||||
nErr = inflateInit(&zInfo); // zlib function
|
||||
if (nErr == Z_OK) {
|
||||
nErr = zng_inflate(&zInfo, Z_FINISH); // zlib function
|
||||
nErr = inflate(&zInfo, Z_FINISH); // zlib function
|
||||
if (nErr == Z_STREAM_END) {
|
||||
nRet = zInfo.total_out;
|
||||
}
|
||||
}
|
||||
zng_inflateEnd(&zInfo); // zlib function
|
||||
inflateEnd(&zInfo); // zlib function
|
||||
return(nRet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
AssetManager::AssetManager(const std::filesystem::path& path) {
|
||||
if (!std::filesystem::is_directory(path)) {
|
||||
throw std::runtime_error("Attempted to load asset bundle (" + path.string() + ") however it is not a valid directory.");
|
||||
@@ -80,7 +82,7 @@ bool AssetManager::HasFile(const char* name) {
|
||||
if (fixedName.rfind("client\\res\\", 0) != 0) fixedName = "client\\res\\" + fixedName;
|
||||
|
||||
uint32_t crc = crc32b(0xFFFFFFFF, reinterpret_cast<uint8_t*>(const_cast<char*>(fixedName.c_str())), fixedName.size());
|
||||
crc = crc32b(crc, reinterpret_cast<uint8_t*>(const_cast<char*>("\0\0\0\0")), 4);
|
||||
crc = crc32b(crc, reinterpret_cast<Bytef*>(const_cast<char*>("\0\0\0\0")), 4);
|
||||
|
||||
for (const auto& item : this->m_PackIndex->GetPackFileIndices()) {
|
||||
if (item.m_Crc == crc) {
|
||||
@@ -128,7 +130,7 @@ bool AssetManager::GetFile(const char* name, char** data, uint32_t* len) {
|
||||
}
|
||||
int32_t packIndex = -1;
|
||||
uint32_t crc = crc32b(0xFFFFFFFF, reinterpret_cast<uint8_t*>(const_cast<char*>(fixedName.c_str())), fixedName.size());
|
||||
crc = crc32b(crc, reinterpret_cast<uint8_t*>(const_cast<char*>("\0\0\0\0")), 4);
|
||||
crc = crc32b(crc, reinterpret_cast<Bytef*>(const_cast<char*>("\0\0\0\0")), 4);
|
||||
|
||||
for (const auto& item : this->m_PackIndex->GetPackFileIndices()) {
|
||||
if (item.m_Crc == crc) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "dConfig.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "BinaryPathFinder.h"
|
||||
#include "GeneralUtils.h"
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace MessageType {
|
||||
enum class Auth : uint32_t {
|
||||
LOGIN_REQUEST = 0,
|
||||
LOGOUT_REQUEST,
|
||||
CREATE_NEW_ACCOUNT_REQUEST,
|
||||
LEGOINTERFACE_AUTH_RESPONSE,
|
||||
SESSIONKEY_RECEIVED_CONFIRM,
|
||||
RUNTIME_CONFIG
|
||||
};
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace MessageType {
|
||||
//! The Internal Chat Packet Identifiers
|
||||
enum class Chat : uint32_t {
|
||||
LOGIN_SESSION_NOTIFY = 0,
|
||||
GENERAL_CHAT_MESSAGE,
|
||||
PRIVATE_CHAT_MESSAGE,
|
||||
USER_CHANNEL_CHAT_MESSAGE,
|
||||
WORLD_DISCONNECT_REQUEST,
|
||||
WORLD_PROXIMITY_RESPONSE,
|
||||
WORLD_PARCEL_RESPONSE,
|
||||
ADD_FRIEND_REQUEST,
|
||||
ADD_FRIEND_RESPONSE,
|
||||
REMOVE_FRIEND,
|
||||
GET_FRIENDS_LIST,
|
||||
ADD_IGNORE,
|
||||
REMOVE_IGNORE,
|
||||
GET_IGNORE_LIST,
|
||||
TEAM_MISSED_INVITE_CHECK,
|
||||
TEAM_INVITE,
|
||||
TEAM_INVITE_RESPONSE,
|
||||
TEAM_KICK,
|
||||
TEAM_LEAVE,
|
||||
TEAM_SET_LOOT,
|
||||
TEAM_SET_LEADER,
|
||||
TEAM_GET_STATUS,
|
||||
GUILD_CREATE,
|
||||
GUILD_INVITE,
|
||||
GUILD_INVITE_RESPONSE,
|
||||
GUILD_LEAVE,
|
||||
GUILD_KICK,
|
||||
GUILD_GET_STATUS,
|
||||
GUILD_GET_ALL,
|
||||
SHOW_ALL,
|
||||
BLUEPRINT_MODERATED,
|
||||
BLUEPRINT_MODEL_READY,
|
||||
PROPERTY_READY_FOR_APPROVAL,
|
||||
PROPERTY_MODERATION_CHANGED,
|
||||
PROPERTY_BUILDMODE_CHANGED,
|
||||
PROPERTY_BUILDMODE_CHANGED_REPORT,
|
||||
MAIL,
|
||||
WORLD_INSTANCE_LOCATION_REQUEST,
|
||||
REPUTATION_UPDATE,
|
||||
SEND_CANNED_TEXT,
|
||||
GMLEVEL_UPDATE,
|
||||
CHARACTER_NAME_CHANGE_REQUEST,
|
||||
CSR_REQUEST,
|
||||
CSR_REPLY,
|
||||
GM_KICK,
|
||||
GM_ANNOUNCE,
|
||||
GM_MUTE,
|
||||
ACTIVITY_UPDATE,
|
||||
WORLD_ROUTE_PACKET,
|
||||
GET_ZONE_POPULATIONS,
|
||||
REQUEST_MINIMUM_CHAT_MODE,
|
||||
REQUEST_MINIMUM_CHAT_MODE_PRIVATE,
|
||||
MATCH_REQUEST,
|
||||
UGCMANIFEST_REPORT_MISSING_FILE,
|
||||
UGCMANIFEST_REPORT_DONE_FILE,
|
||||
UGCMANIFEST_REPORT_DONE_BLUEPRINT,
|
||||
UGCC_REQUEST,
|
||||
WHO,
|
||||
WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE,
|
||||
ACHIEVEMENT_NOTIFY,
|
||||
GM_CLOSE_PRIVATE_CHAT_WINDOW,
|
||||
UNEXPECTED_DISCONNECT,
|
||||
PLAYER_READY,
|
||||
GET_DONATION_TOTAL,
|
||||
UPDATE_DONATION,
|
||||
PRG_CSR_COMMAND,
|
||||
HEARTBEAT_REQUEST_FROM_WORLD,
|
||||
UPDATE_FREE_TRIAL_STATUS,
|
||||
// CUSTOM DLU MESSAGE ID FOR INTERNAL USE
|
||||
CREATE_TEAM,
|
||||
};
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace MessageType {
|
||||
enum class Client : uint32_t {
|
||||
LOGIN_RESPONSE = 0,
|
||||
LOGOUT_RESPONSE,
|
||||
LOAD_STATIC_ZONE,
|
||||
CREATE_OBJECT,
|
||||
CREATE_CHARACTER,
|
||||
CREATE_CHARACTER_EXTENDED,
|
||||
CHARACTER_LIST_RESPONSE,
|
||||
CHARACTER_CREATE_RESPONSE,
|
||||
CHARACTER_RENAME_RESPONSE,
|
||||
CHAT_CONNECT_RESPONSE,
|
||||
AUTH_ACCOUNT_CREATE_RESPONSE,
|
||||
DELETE_CHARACTER_RESPONSE,
|
||||
GAME_MSG,
|
||||
CONNECT_CHAT,
|
||||
TRANSFER_TO_WORLD,
|
||||
IMPENDING_RELOAD_NOTIFY,
|
||||
MAKE_GM_RESPONSE,
|
||||
HTTP_MONITOR_INFO_RESPONSE,
|
||||
SLASH_PUSH_MAP_RESPONSE,
|
||||
SLASH_PULL_MAP_RESPONSE,
|
||||
SLASH_LOCK_MAP_RESPONSE,
|
||||
BLUEPRINT_SAVE_RESPONSE,
|
||||
BLUEPRINT_LUP_SAVE_RESPONSE,
|
||||
BLUEPRINT_LOAD_RESPONSE_ITEMID,
|
||||
BLUEPRINT_GET_ALL_DATA_RESPONSE,
|
||||
MODEL_INSTANTIATE_RESPONSE,
|
||||
DEBUG_OUTPUT,
|
||||
ADD_FRIEND_REQUEST,
|
||||
ADD_FRIEND_RESPONSE,
|
||||
REMOVE_FRIEND_RESPONSE,
|
||||
GET_FRIENDS_LIST_RESPONSE,
|
||||
UPDATE_FRIEND_NOTIFY,
|
||||
ADD_IGNORE_RESPONSE,
|
||||
REMOVE_IGNORE_RESPONSE,
|
||||
GET_IGNORE_LIST_RESPONSE,
|
||||
TEAM_INVITE,
|
||||
TEAM_INVITE_INITIAL_RESPONSE,
|
||||
GUILD_CREATE_RESPONSE,
|
||||
GUILD_GET_STATUS_RESPONSE,
|
||||
GUILD_INVITE,
|
||||
GUILD_INVITE_INITIAL_RESPONSE,
|
||||
GUILD_INVITE_FINAL_RESPONSE,
|
||||
GUILD_INVITE_CONFIRM,
|
||||
GUILD_ADD_PLAYER,
|
||||
GUILD_REMOVE_PLAYER,
|
||||
GUILD_LOGIN_LOGOUT,
|
||||
GUILD_RANK_CHANGE,
|
||||
GUILD_DATA,
|
||||
GUILD_STATUS,
|
||||
MAIL,
|
||||
DB_PROXY_RESULT,
|
||||
SHOW_ALL_RESPONSE,
|
||||
WHO_RESPONSE,
|
||||
SEND_CANNED_TEXT,
|
||||
UPDATE_CHARACTER_NAME,
|
||||
SET_NETWORK_SIMULATOR,
|
||||
INVALID_CHAT_MESSAGE,
|
||||
MINIMUM_CHAT_MODE_RESPONSE,
|
||||
MINIMUM_CHAT_MODE_RESPONSE_PRIVATE,
|
||||
CHAT_MODERATION_STRING,
|
||||
UGC_MANIFEST_RESPONSE,
|
||||
IN_LOGIN_QUEUE,
|
||||
SERVER_STATES,
|
||||
GM_CLOSE_TARGET_CHAT_WINDOW,
|
||||
GENERAL_TEXT_FOR_LOCALIZATION,
|
||||
UPDATE_FREE_TRIAL_STATUS,
|
||||
UGC_DOWNLOAD_FAILED = 120
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace MessageType {
|
||||
enum class Master : uint32_t {
|
||||
REQUEST_PERSISTENT_ID = 1,
|
||||
REQUEST_PERSISTENT_ID_RESPONSE,
|
||||
REQUEST_ZONE_TRANSFER,
|
||||
REQUEST_ZONE_TRANSFER_RESPONSE,
|
||||
SERVER_INFO,
|
||||
REQUEST_SESSION_KEY,
|
||||
SET_SESSION_KEY,
|
||||
SESSION_KEY_RESPONSE,
|
||||
PLAYER_ADDED,
|
||||
PLAYER_REMOVED,
|
||||
|
||||
CREATE_PRIVATE_ZONE,
|
||||
REQUEST_PRIVATE_ZONE,
|
||||
|
||||
WORLD_READY,
|
||||
PREP_ZONE,
|
||||
|
||||
SHUTDOWN,
|
||||
SHUTDOWN_RESPONSE,
|
||||
SHUTDOWN_IMMEDIATE,
|
||||
|
||||
SHUTDOWN_UNIVERSE,
|
||||
|
||||
AFFIRM_TRANSFER_REQUEST,
|
||||
AFFIRM_TRANSFER_RESPONSE,
|
||||
|
||||
NEW_SESSION_ALERT
|
||||
};
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace MessageType {
|
||||
//! The Internal Server Packet Identifiers
|
||||
enum class Server : uint32_t {
|
||||
VERSION_CONFIRM = 0,
|
||||
DISCONNECT_NOTIFY,
|
||||
GENERAL_NOTIFY
|
||||
};
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
namespace MessageType {
|
||||
enum class World : uint32_t {
|
||||
VALIDATION = 1, // Session info
|
||||
CHARACTER_LIST_REQUEST,
|
||||
CHARACTER_CREATE_REQUEST,
|
||||
LOGIN_REQUEST, // Character selected
|
||||
GAME_MSG,
|
||||
CHARACTER_DELETE_REQUEST,
|
||||
CHARACTER_RENAME_REQUEST,
|
||||
HAPPY_FLOWER_MODE_NOTIFY,
|
||||
SLASH_RELOAD_MAP, // Reload map cmp
|
||||
SLASH_PUSH_MAP_REQUEST, // Push map req cmd
|
||||
SLASH_PUSH_MAP, // Push map cmd
|
||||
SLASH_PULL_MAP, // Pull map cmd
|
||||
LOCK_MAP_REQUEST,
|
||||
GENERAL_CHAT_MESSAGE, // General chat message
|
||||
HTTP_MONITOR_INFO_REQUEST,
|
||||
SLASH_DEBUG_SCRIPTS, // Debug scripts cmd
|
||||
MODELS_CLEAR,
|
||||
EXHIBIT_INSERT_MODEL,
|
||||
LEVEL_LOAD_COMPLETE, // Character data request
|
||||
TMP_GUILD_CREATE,
|
||||
ROUTE_PACKET, // Social?
|
||||
POSITION_UPDATE,
|
||||
MAIL,
|
||||
WORD_CHECK, // AllowList word check
|
||||
STRING_CHECK, // AllowList string check
|
||||
GET_PLAYERS_IN_ZONE,
|
||||
REQUEST_UGC_MANIFEST_INFO,
|
||||
BLUEPRINT_GET_ALL_DATA_REQUEST,
|
||||
CANCEL_MAP_QUEUE,
|
||||
HANDLE_FUNNESS,
|
||||
FAKE_PRG_CSR_MESSAGE,
|
||||
REQUEST_FREE_TRIAL_REFRESH,
|
||||
GM_SET_FREE_TRIAL_STATUS,
|
||||
UI_HELP_TOP_5 = 91
|
||||
};
|
||||
}
|
||||
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<MessageType::World> {
|
||||
static constexpr int min = 0;
|
||||
static constexpr int max = 91;
|
||||
};
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <set>
|
||||
#include "BitStream.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "MessageType/Client.h"
|
||||
#include "eClientMessageType.h"
|
||||
#include "BitStreamUtils.h"
|
||||
|
||||
#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 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 CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::GAME_MSG);
|
||||
#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||
#define SEND_PACKET Game::server->Send(bitStream, sysAddr, false);
|
||||
#define SEND_PACKET_BROADCAST Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||
|
||||
|
||||
15
dCommon/dEnums/eAuthMessageType.h
Normal file
15
dCommon/dEnums/eAuthMessageType.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef __EAUTHMESSAGETYPE__H__
|
||||
#define __EAUTHMESSAGETYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eAuthMessageType : uint32_t {
|
||||
LOGIN_REQUEST = 0,
|
||||
LOGOUT_REQUEST,
|
||||
CREATE_NEW_ACCOUNT_REQUEST,
|
||||
LEGOINTERFACE_AUTH_RESPONSE,
|
||||
SESSIONKEY_RECEIVED_CONFIRM,
|
||||
RUNTIME_CONFIG
|
||||
};
|
||||
|
||||
#endif //!__EAUTHMESSAGETYPE__H__
|
||||
@@ -15,8 +15,7 @@ enum class eCharacterVersion : uint32_t {
|
||||
// Fixes vault size value
|
||||
VAULT_SIZE,
|
||||
// Fixes speed base value in level component
|
||||
SPEED_BASE,
|
||||
UP_TO_DATE, // will become NJ_JAYMISSIONS
|
||||
UP_TO_DATE, // will become SPEED_BASE
|
||||
};
|
||||
|
||||
#endif //!__ECHARACTERVERSION__H__
|
||||
|
||||
80
dCommon/dEnums/eChatMessageType.h
Normal file
80
dCommon/dEnums/eChatMessageType.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#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__
|
||||
76
dCommon/dEnums/eClientMessageType.h
Normal file
76
dCommon/dEnums/eClientMessageType.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef __ECLIENTMESSAGETYPE__H__
|
||||
#define __ECLIENTMESSAGETYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eClientMessageType : uint32_t {
|
||||
LOGIN_RESPONSE = 0,
|
||||
LOGOUT_RESPONSE,
|
||||
LOAD_STATIC_ZONE,
|
||||
CREATE_OBJECT,
|
||||
CREATE_CHARACTER,
|
||||
CREATE_CHARACTER_EXTENDED,
|
||||
CHARACTER_LIST_RESPONSE,
|
||||
CHARACTER_CREATE_RESPONSE,
|
||||
CHARACTER_RENAME_RESPONSE,
|
||||
CHAT_CONNECT_RESPONSE,
|
||||
AUTH_ACCOUNT_CREATE_RESPONSE,
|
||||
DELETE_CHARACTER_RESPONSE,
|
||||
GAME_MSG,
|
||||
CONNECT_CHAT,
|
||||
TRANSFER_TO_WORLD,
|
||||
IMPENDING_RELOAD_NOTIFY,
|
||||
MAKE_GM_RESPONSE,
|
||||
HTTP_MONITOR_INFO_RESPONSE,
|
||||
SLASH_PUSH_MAP_RESPONSE,
|
||||
SLASH_PULL_MAP_RESPONSE,
|
||||
SLASH_LOCK_MAP_RESPONSE,
|
||||
BLUEPRINT_SAVE_RESPONSE,
|
||||
BLUEPRINT_LUP_SAVE_RESPONSE,
|
||||
BLUEPRINT_LOAD_RESPONSE_ITEMID,
|
||||
BLUEPRINT_GET_ALL_DATA_RESPONSE,
|
||||
MODEL_INSTANTIATE_RESPONSE,
|
||||
DEBUG_OUTPUT,
|
||||
ADD_FRIEND_REQUEST,
|
||||
ADD_FRIEND_RESPONSE,
|
||||
REMOVE_FRIEND_RESPONSE,
|
||||
GET_FRIENDS_LIST_RESPONSE,
|
||||
UPDATE_FRIEND_NOTIFY,
|
||||
ADD_IGNORE_RESPONSE,
|
||||
REMOVE_IGNORE_RESPONSE,
|
||||
GET_IGNORE_LIST_RESPONSE,
|
||||
TEAM_INVITE,
|
||||
TEAM_INVITE_INITIAL_RESPONSE,
|
||||
GUILD_CREATE_RESPONSE,
|
||||
GUILD_GET_STATUS_RESPONSE,
|
||||
GUILD_INVITE,
|
||||
GUILD_INVITE_INITIAL_RESPONSE,
|
||||
GUILD_INVITE_FINAL_RESPONSE,
|
||||
GUILD_INVITE_CONFIRM,
|
||||
GUILD_ADD_PLAYER,
|
||||
GUILD_REMOVE_PLAYER,
|
||||
GUILD_LOGIN_LOGOUT,
|
||||
GUILD_RANK_CHANGE,
|
||||
GUILD_DATA,
|
||||
GUILD_STATUS,
|
||||
MAIL,
|
||||
DB_PROXY_RESULT,
|
||||
SHOW_ALL_RESPONSE,
|
||||
WHO_RESPONSE,
|
||||
SEND_CANNED_TEXT,
|
||||
UPDATE_CHARACTER_NAME,
|
||||
SET_NETWORK_SIMULATOR,
|
||||
INVALID_CHAT_MESSAGE,
|
||||
MINIMUM_CHAT_MODE_RESPONSE,
|
||||
MINIMUM_CHAT_MODE_RESPONSE_PRIVATE,
|
||||
CHAT_MODERATION_STRING,
|
||||
UGC_MANIFEST_RESPONSE,
|
||||
IN_LOGIN_QUEUE,
|
||||
SERVER_STATES,
|
||||
GM_CLOSE_TARGET_CHAT_WINDOW,
|
||||
GENERAL_TEXT_FOR_LOCALIZATION,
|
||||
UPDATE_FREE_TRIAL_STATUS,
|
||||
UGC_DOWNLOAD_FAILED = 120
|
||||
};
|
||||
|
||||
#endif //!__ECLIENTMESSAGETYPE__H__
|
||||
1614
dCommon/dEnums/eGameMessageType.h
Normal file
1614
dCommon/dEnums/eGameMessageType.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,6 @@
|
||||
#define __EINVENTORYTYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
static const uint8_t NUMBER_OF_INVENTORIES = 17;
|
||||
/**
|
||||
* Represents the different types of inventories an entity may have
|
||||
@@ -59,10 +56,4 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<eInventoryType> {
|
||||
static constexpr int min = 0;
|
||||
static constexpr int max = 16;
|
||||
};
|
||||
|
||||
#endif //!__EINVENTORYTYPE__H__
|
||||
|
||||
36
dCommon/dEnums/eMasterMessageType.h
Normal file
36
dCommon/dEnums/eMasterMessageType.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef __EMASTERMESSAGETYPE__H__
|
||||
#define __EMASTERMESSAGETYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eMasterMessageType : uint32_t {
|
||||
REQUEST_PERSISTENT_ID = 1,
|
||||
REQUEST_PERSISTENT_ID_RESPONSE,
|
||||
REQUEST_ZONE_TRANSFER,
|
||||
REQUEST_ZONE_TRANSFER_RESPONSE,
|
||||
SERVER_INFO,
|
||||
REQUEST_SESSION_KEY,
|
||||
SET_SESSION_KEY,
|
||||
SESSION_KEY_RESPONSE,
|
||||
PLAYER_ADDED,
|
||||
PLAYER_REMOVED,
|
||||
|
||||
CREATE_PRIVATE_ZONE,
|
||||
REQUEST_PRIVATE_ZONE,
|
||||
|
||||
WORLD_READY,
|
||||
PREP_ZONE,
|
||||
|
||||
SHUTDOWN,
|
||||
SHUTDOWN_RESPONSE,
|
||||
SHUTDOWN_IMMEDIATE,
|
||||
|
||||
SHUTDOWN_UNIVERSE,
|
||||
|
||||
AFFIRM_TRANSFER_REQUEST,
|
||||
AFFIRM_TRANSFER_RESPONSE,
|
||||
|
||||
NEW_SESSION_ALERT
|
||||
};
|
||||
|
||||
#endif //!__EMASTERMESSAGETYPE__H__
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef EPROPERTYSORTTYPE_H
|
||||
#define EPROPERTYSORTTYPE_H
|
||||
|
||||
enum ePropertySortType : int32_t {
|
||||
SORT_TYPE_FRIENDS = 0,
|
||||
SORT_TYPE_REPUTATION = 1,
|
||||
SORT_TYPE_RECENT = 3,
|
||||
SORT_TYPE_FEATURED = 5
|
||||
};
|
||||
|
||||
#endif //!EPROPERTYSORTTYPE_H
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef __EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
||||
#define __EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eReponseMoveItemBetweenInventoryTypeCode : int32_t {
|
||||
SUCCESS,
|
||||
FAIL_GENERIC,
|
||||
FAIL_INV_FULL,
|
||||
FAIL_ITEM_NOT_FOUND,
|
||||
FAIL_CANT_MOVE_TO_THAT_INV_TYPE,
|
||||
FAIL_NOT_NEAR_BANK,
|
||||
FAIL_CANT_SWAP_ITEMS,
|
||||
FAIL_SOURCE_TYPE,
|
||||
FAIL_WRONG_DEST_TYPE,
|
||||
FAIL_SWAP_DEST_TYPE,
|
||||
FAIL_CANT_MOVE_THINKING_HAT,
|
||||
FAIL_DISMOUNT_BEFORE_MOVING
|
||||
};
|
||||
|
||||
#endif //!__EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
||||
12
dCommon/dEnums/eServerMessageType.h
Normal file
12
dCommon/dEnums/eServerMessageType.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef __ESERVERMESSAGETYPE__H__
|
||||
#define __ESERVERMESSAGETYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
//! The Internal Server Packet Identifiers
|
||||
enum class eServerMessageType : uint32_t {
|
||||
VERSION_CONFIRM = 0,
|
||||
DISCONNECT_NOTIFY,
|
||||
GENERAL_NOTIFY
|
||||
};
|
||||
|
||||
#endif //!__ESERVERMESSAGETYPE__H__
|
||||
51
dCommon/dEnums/eWorldMessageType.h
Normal file
51
dCommon/dEnums/eWorldMessageType.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef __EWORLDMESSAGETYPE__H__
|
||||
#define __EWORLDMESSAGETYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
enum class eWorldMessageType : uint32_t {
|
||||
VALIDATION = 1, // Session info
|
||||
CHARACTER_LIST_REQUEST,
|
||||
CHARACTER_CREATE_REQUEST,
|
||||
LOGIN_REQUEST, // Character selected
|
||||
GAME_MSG,
|
||||
CHARACTER_DELETE_REQUEST,
|
||||
CHARACTER_RENAME_REQUEST,
|
||||
HAPPY_FLOWER_MODE_NOTIFY,
|
||||
SLASH_RELOAD_MAP, // Reload map cmp
|
||||
SLASH_PUSH_MAP_REQUEST, // Push map req cmd
|
||||
SLASH_PUSH_MAP, // Push map cmd
|
||||
SLASH_PULL_MAP, // Pull map cmd
|
||||
LOCK_MAP_REQUEST,
|
||||
GENERAL_CHAT_MESSAGE, // General chat message
|
||||
HTTP_MONITOR_INFO_REQUEST,
|
||||
SLASH_DEBUG_SCRIPTS, // Debug scripts cmd
|
||||
MODELS_CLEAR,
|
||||
EXHIBIT_INSERT_MODEL,
|
||||
LEVEL_LOAD_COMPLETE, // Character data request
|
||||
TMP_GUILD_CREATE,
|
||||
ROUTE_PACKET, // Social?
|
||||
POSITION_UPDATE,
|
||||
MAIL,
|
||||
WORD_CHECK, // 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__
|
||||
@@ -8,15 +8,9 @@ foreach(file ${DDATABSE_DATABSES_MYSQL_SOURCES})
|
||||
set(DDATABASE_GAMEDATABASE_SOURCES ${DDATABASE_GAMEDATABASE_SOURCES} "MySQL/${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})
|
||||
target_include_directories(dDatabaseGame PUBLIC "."
|
||||
"ITables" PRIVATE "MySQL" "TestSQL"
|
||||
"ITables" PRIVATE "MySQL"
|
||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||
)
|
||||
|
||||
@@ -38,8 +38,3 @@ void Database::Destroy(std::string source) {
|
||||
LOG("Trying to destroy database when it's not connected!");
|
||||
}
|
||||
}
|
||||
|
||||
void Database::_setDatabase(GameDatabase* const db) {
|
||||
if (database) delete database;
|
||||
database = db;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,4 @@ namespace Database {
|
||||
void Connect();
|
||||
GameDatabase* Get();
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "IActivityLog.h"
|
||||
#include "IIgnoreList.h"
|
||||
#include "IAccountsRewardCodes.h"
|
||||
#include "IBehaviors.h"
|
||||
|
||||
namespace sql {
|
||||
class Statement;
|
||||
@@ -41,8 +40,7 @@ class GameDatabase :
|
||||
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
|
||||
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
||||
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList,
|
||||
public IBehaviors {
|
||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList {
|
||||
public:
|
||||
virtual ~GameDatabase() = default;
|
||||
// TODO: These should be made private.
|
||||
|
||||
@@ -33,9 +33,6 @@ public:
|
||||
|
||||
// Add a new account to the database.
|
||||
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;
|
||||
};
|
||||
|
||||
#endif //!__IACCOUNTS__H__
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef IBEHAVIORS_H
|
||||
#define IBEHAVIORS_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
|
||||
class IBehaviors {
|
||||
public:
|
||||
struct Info {
|
||||
int32_t behaviorId{};
|
||||
uint32_t characterId{};
|
||||
std::string behaviorInfo;
|
||||
};
|
||||
|
||||
// This Add also takes care of updating if it exists.
|
||||
virtual void AddBehavior(const Info& info) = 0;
|
||||
virtual std::string GetBehavior(const int32_t behaviorId) = 0;
|
||||
virtual void RemoveBehavior(const int32_t behaviorId) = 0;
|
||||
};
|
||||
|
||||
#endif //!IBEHAVIORS_H
|
||||
@@ -4,8 +4,6 @@
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
enum ePropertySortType : int32_t;
|
||||
|
||||
class IProperty {
|
||||
public:
|
||||
struct Info {
|
||||
@@ -20,33 +18,11 @@ public:
|
||||
uint32_t lastUpdatedTime{};
|
||||
uint32_t claimedTime{};
|
||||
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.
|
||||
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.
|
||||
virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef __IPROPERTIESCONTENTS__H__
|
||||
#define __IPROPERTIESCONTENTS__H__
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
@@ -17,7 +16,6 @@ public:
|
||||
LWOOBJID id{};
|
||||
LOT lot{};
|
||||
uint32_t ugcId{};
|
||||
std::array<int32_t, 5> behaviors{};
|
||||
};
|
||||
|
||||
// Inserts a new UGC model into the database.
|
||||
@@ -34,7 +32,7 @@ public:
|
||||
virtual void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) = 0;
|
||||
|
||||
// Update the model position and rotation for the given property id.
|
||||
virtual void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) = 0;
|
||||
virtual void UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) = 0;
|
||||
|
||||
// Remove the model for the given property id.
|
||||
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "Game.h"
|
||||
#include "dConfig.h"
|
||||
#include "Logger.h"
|
||||
#include "dPlatforms.h"
|
||||
|
||||
namespace {
|
||||
std::string databaseName;
|
||||
@@ -40,13 +39,14 @@ void MySQLDatabase::Connect() {
|
||||
properties["autoReconnect"] = "true";
|
||||
|
||||
databaseName = Game::config->GetValue("mysql_database").c_str();
|
||||
|
||||
// `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
|
||||
#if defined(DARKFLAME_PLATFORM_WIN32) && defined(_DEBUG)
|
||||
con = driver->connect(properties["hostName"].c_str(), properties["user"].c_str(), properties["password"].c_str());
|
||||
#else
|
||||
if (properties.find("localSocket") != properties.end() || properties.find("pipe") != properties.end()) {
|
||||
con = driver->connect(properties);
|
||||
#endif
|
||||
} else {
|
||||
con = driver->connect(properties["hostName"].c_str(), properties["user"].c_str(), properties["password"].c_str());
|
||||
}
|
||||
con->setSchema(databaseName.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
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 UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) override;
|
||||
void RemoveModel(const LWOOBJID& modelId) override;
|
||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||
@@ -108,11 +108,6 @@ public:
|
||||
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;
|
||||
private:
|
||||
|
||||
// Generic query functions that can be used for any query.
|
||||
|
||||
@@ -35,7 +35,3 @@ void MySQLDatabase::UpdateAccountPassword(const uint32_t accountId, const std::s
|
||||
void MySQLDatabase::InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#include "IBehaviors.h"
|
||||
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
void MySQLDatabase::AddBehavior(const IBehaviors::Info& info) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO behaviors (behavior_info, character_id, behavior_id) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE behavior_info = ?",
|
||||
info.behaviorInfo, info.characterId, info.behaviorId, info.behaviorInfo
|
||||
);
|
||||
}
|
||||
|
||||
void MySQLDatabase::RemoveBehavior(const int32_t behaviorId) {
|
||||
ExecuteDelete("DELETE FROM behaviors WHERE behavior_id = ?", behaviorId);
|
||||
}
|
||||
|
||||
std::string MySQLDatabase::GetBehavior(const int32_t behaviorId) {
|
||||
auto result = ExecuteSelect("SELECT behavior_info FROM behaviors WHERE behavior_id = ?", behaviorId);
|
||||
return result->next() ? result->getString("behavior_info").c_str() : "";
|
||||
}
|
||||
@@ -2,7 +2,6 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
||||
"Accounts.cpp"
|
||||
"AccountsRewardCodes.cpp"
|
||||
"ActivityLog.cpp"
|
||||
"Behaviors.cpp"
|
||||
"BugReports.cpp"
|
||||
"CharInfo.cpp"
|
||||
"CharXml.cpp"
|
||||
|
||||
@@ -1,140 +1,8 @@
|
||||
#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) {
|
||||
auto propertyEntry = ExecuteSelect(
|
||||
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
||||
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved "
|
||||
"FROM properties WHERE zone_id = ? AND clone_id = ?;", mapId, cloneId);
|
||||
|
||||
if (!propertyEntry->next()) {
|
||||
@@ -153,7 +21,6 @@ std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID map
|
||||
toReturn.claimedTime = propertyEntry->getUInt("time_claimed");
|
||||
toReturn.reputation = propertyEntry->getUInt("reputation");
|
||||
toReturn.modApproved = propertyEntry->getUInt("mod_approved");
|
||||
toReturn.performanceCost = propertyEntry->getFloat("performance_cost");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
std::vector<IPropertyContents::Model> MySQLDatabase::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);
|
||||
auto result = ExecuteSelect("SELECT id, lot, x, y, z, rx, ry, rz, rw, ugc_id FROM properties_contents WHERE property_id = ?;", propertyId);
|
||||
|
||||
std::vector<IPropertyContents::Model> toReturn;
|
||||
toReturn.reserve(result->rowsCount());
|
||||
@@ -20,12 +17,6 @@ std::vector<IPropertyContents::Model> MySQLDatabase::GetPropertyModels(const LWO
|
||||
model.rotation.y = result->getFloat("ry");
|
||||
model.rotation.z = result->getFloat("rz");
|
||||
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));
|
||||
}
|
||||
return toReturn;
|
||||
@@ -41,23 +32,21 @@ void MySQLDatabase::InsertNewPropertyModel(const LWOOBJID& propertyId, const IPr
|
||||
model.id, propertyId, model.ugcId == 0 ? std::nullopt : std::optional(model.ugcId), static_cast<uint32_t>(model.lot),
|
||||
model.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
|
||||
0, // behavior 1. TODO implement this.
|
||||
0, // behavior 2. TODO implement this.
|
||||
0, // behavior 3. TODO implement this.
|
||||
0, // behavior 4. TODO implement this.
|
||||
0 // behavior 5. TODO implement this.
|
||||
);
|
||||
} catch (sql::SQLException& e) {
|
||||
LOG("Error inserting new property model: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MySQLDatabase::UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) {
|
||||
void MySQLDatabase::UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) {
|
||||
ExecuteUpdate(
|
||||
"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);
|
||||
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ? WHERE id = ?;",
|
||||
position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w, propertyId);
|
||||
}
|
||||
|
||||
void MySQLDatabase::RemoveModel(const LWOOBJID& modelId) {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
SET(DDATABSE_DATABSES_TEST_SQL_SOURCES
|
||||
"TestSQLDatabase.cpp"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -1,306 +0,0 @@
|
||||
#include "TestSQLDatabase.h"
|
||||
|
||||
void TestSQLDatabase::Connect() {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::Destroy(std::string source) {
|
||||
|
||||
}
|
||||
|
||||
sql::PreparedStatement* TestSQLDatabase::CreatePreppedStmt(const std::string& query) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
#ifndef TESTSQLDATABASE_H
|
||||
#define TESTSQLDATABASE_H
|
||||
|
||||
#include "GameDatabase.h"
|
||||
|
||||
class TestSQLDatabase : public GameDatabase {
|
||||
void Connect() override;
|
||||
void Destroy(std::string source = "") override;
|
||||
|
||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query) 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 {}; };
|
||||
};
|
||||
|
||||
#endif //!TESTSQLDATABASE_H
|
||||
@@ -27,8 +27,6 @@ Character::Character(uint32_t id, User* parentUser) {
|
||||
m_ID = id;
|
||||
m_ParentUser = parentUser;
|
||||
m_OurEntity = nullptr;
|
||||
m_GMLevel = eGameMasterLevel::CIVILIAN;
|
||||
m_PermissionMap = static_cast<ePermissionMap>(0);
|
||||
}
|
||||
|
||||
Character::~Character() {
|
||||
@@ -40,8 +38,8 @@ void Character::UpdateInfoFromDatabase() {
|
||||
auto charInfo = Database::Get()->GetCharacterInfo(m_ID);
|
||||
|
||||
if (charInfo) {
|
||||
m_Name = charInfo->name;
|
||||
m_UnapprovedName = charInfo->pendingName;
|
||||
m_Name = charInfo->name;
|
||||
m_UnapprovedName = charInfo->pendingName;
|
||||
m_NameRejected = charInfo->needsRename;
|
||||
m_PropertyCloneID = charInfo->cloneId;
|
||||
m_PermissionMap = charInfo->permissionMap;
|
||||
@@ -76,7 +74,7 @@ void Character::DoQuickXMLDataParse() {
|
||||
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);
|
||||
} else {
|
||||
LOG("Failed to load xmlData (%i) (%s) (%s)!", m_Doc.ErrorID(), m_Doc.ErrorIDToName(m_Doc.ErrorID()), m_Doc.ErrorStr());
|
||||
LOG("Failed to load xmlData!");
|
||||
//Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true);
|
||||
return;
|
||||
}
|
||||
@@ -241,7 +239,7 @@ void Character::SaveXMLToDatabase() {
|
||||
|
||||
auto zoneInfo = Game::zoneManager->GetZone()->GetZoneID();
|
||||
// lzid garbage, binary concat of zoneID, zoneInstance and zoneClone
|
||||
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0 && !Game::zoneManager->GetDisableSaveLocation()) {
|
||||
// if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0 && !Game::zoneManager->GetDisableSaveLocation()) {
|
||||
uint64_t lzidConcat = zoneInfo.GetCloneID();
|
||||
lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetInstanceID());
|
||||
lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetMapID());
|
||||
@@ -253,7 +251,7 @@ void Character::SaveXMLToDatabase() {
|
||||
|
||||
// Set the target scene, custom attribute
|
||||
character->SetAttribute("tscene", m_TargetScene.c_str());
|
||||
}
|
||||
// }
|
||||
|
||||
auto emotes = character->FirstChildElement("ue");
|
||||
if (!emotes) emotes = m_Doc.NewElement("ue");
|
||||
|
||||
@@ -38,7 +38,6 @@ public:
|
||||
|
||||
const std::string& GetXMLData() const { return m_XMLData; }
|
||||
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.
|
||||
@@ -460,31 +459,27 @@ public:
|
||||
|
||||
User* GetParentUser() const { return m_ParentUser; }
|
||||
|
||||
void _doQuickXMLDataParse() { DoQuickXMLDataParse(); }
|
||||
|
||||
void _setXmlData(const std::string& xmlData) { m_XMLData = xmlData; }
|
||||
|
||||
private:
|
||||
void UpdateInfoFromDatabase();
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
LWOOBJID m_ObjectID{ LWOOBJID_EMPTY };
|
||||
LWOOBJID m_ObjectID;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
Entity* m_OurEntity{};
|
||||
Entity* m_OurEntity;
|
||||
|
||||
/**
|
||||
* 0-9, the Game Master level of this character.
|
||||
@@ -511,17 +506,17 @@ private:
|
||||
/**
|
||||
* Whether the custom name of this character is rejected
|
||||
*/
|
||||
bool m_NameRejected{};
|
||||
bool m_NameRejected;
|
||||
|
||||
/**
|
||||
* The current amount of coins of this character
|
||||
*/
|
||||
int64_t m_Coins{};
|
||||
int64_t m_Coins;
|
||||
|
||||
/**
|
||||
* Whether the character is building
|
||||
*/
|
||||
bool m_BuildMode{};
|
||||
bool m_BuildMode;
|
||||
|
||||
/**
|
||||
* The items equipped by the character on world load
|
||||
@@ -588,7 +583,7 @@ private:
|
||||
/**
|
||||
* 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
|
||||
@@ -618,7 +613,7 @@ private:
|
||||
/**
|
||||
* 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)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "eTriggerEventType.h"
|
||||
#include "eObjectBits.h"
|
||||
#include "PositionUpdate.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include "eChatMessageType.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
//Component includes:
|
||||
@@ -96,8 +96,6 @@
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
#include "CDZoneTableTable.h"
|
||||
|
||||
Observable<Entity*, const PositionUpdate&> Entity::OnPlayerPositionUpdate;
|
||||
|
||||
Entity::Entity(const LWOOBJID& objectID, EntityInfo info, User* parentUser, Entity* parentEntity) {
|
||||
m_ObjectID = objectID;
|
||||
m_TemplateID = info.lot;
|
||||
@@ -227,7 +225,7 @@ void Entity::Initialize() {
|
||||
|
||||
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
|
||||
|
||||
AddComponent<ModelComponent>()->LoadBehaviors();
|
||||
AddComponent<ModelComponent>();
|
||||
|
||||
AddComponent<RenderComponent>();
|
||||
|
||||
@@ -651,7 +649,7 @@ void Entity::Initialize() {
|
||||
}
|
||||
|
||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1) != -1 && !GetComponent<PetComponent>()) {
|
||||
AddComponent<ModelComponent>()->LoadBehaviors();
|
||||
AddComponent<ModelComponent>();
|
||||
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) {
|
||||
auto* destroyableComponent = AddComponent<DestroyableComponent>();
|
||||
destroyableComponent->SetHealth(1);
|
||||
@@ -662,7 +660,7 @@ void Entity::Initialize() {
|
||||
}
|
||||
|
||||
PetComponent* petComponent;
|
||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM) > 0 && !TryGetComponent(eReplicaComponentType::PET, petComponent) && !HasComponent(eReplicaComponentType::MODEL)) {
|
||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM) > 0) {
|
||||
AddComponent<ItemComponent>();
|
||||
}
|
||||
|
||||
@@ -883,7 +881,7 @@ void Entity::SetGMLevel(eGameMasterLevel value) {
|
||||
// Update the chat server of our GM Level
|
||||
{
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::GMLEVEL_UPDATE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GMLEVEL_UPDATE);
|
||||
bitStream.Write(m_ObjectID);
|
||||
bitStream.Write(m_GMLevel);
|
||||
|
||||
@@ -903,6 +901,14 @@ void Entity::WriteBaseReplicaData(RakNet::BitStream& outBitStream, eReplicaPacke
|
||||
for (size_t i = 0; i < name.size(); ++i) {
|
||||
outBitStream.Write<uint16_t>(name[i]);
|
||||
}
|
||||
} else if (HasVar(u"userModelName")) {
|
||||
const auto& name = GetVar<std::string>(u"userModelName");
|
||||
outBitStream.Write<uint8_t>(uint8_t(name.size()));
|
||||
|
||||
for (size_t i = 0; i < name.size(); ++i) {
|
||||
outBitStream.Write<uint16_t>(name[i]);
|
||||
}
|
||||
|
||||
} else {
|
||||
const auto& name = GetVar<std::string>(u"npcName");
|
||||
outBitStream.Write<uint8_t>(uint8_t(name.size()));
|
||||
@@ -1351,6 +1357,11 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
|
||||
callback(other);
|
||||
}
|
||||
|
||||
SwitchComponent* switchComp = GetComponent<SwitchComponent>();
|
||||
if (switchComp) {
|
||||
switchComp->EntityEnter(other);
|
||||
}
|
||||
|
||||
TriggerEvent(eTriggerEventType::ENTER, other);
|
||||
|
||||
// POI system
|
||||
@@ -2130,8 +2141,6 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
|
||||
Game::entityManager->QueueGhostUpdate(GetObjectID());
|
||||
|
||||
if (updateChar) Game::entityManager->SerializeEntity(this);
|
||||
|
||||
OnPlayerPositionUpdate.Notify(this, update);
|
||||
}
|
||||
|
||||
const SystemAddress& Entity::GetSystemAddress() const {
|
||||
@@ -2157,3 +2166,12 @@ void Entity::SetRespawnRot(const NiQuaternion& rotation) {
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
if (characterComponent) characterComponent->SetRespawnRot(rotation);
|
||||
}
|
||||
|
||||
void Entity::EraseVar(const std::u16string& name) {
|
||||
for (auto it = m_Settings.begin(); it != m_Settings.end(); ++it) {
|
||||
if ((*it)->GetKey() == name) {
|
||||
m_Settings.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "NiQuaternion.h"
|
||||
#include "LDFFormat.h"
|
||||
#include "eKillType.h"
|
||||
#include "Observable.h"
|
||||
|
||||
namespace Loot {
|
||||
class Info;
|
||||
@@ -300,11 +299,7 @@ public:
|
||||
// Scale will only be communicated to the client when the construction packet is sent
|
||||
void SetScale(const float scale) { m_Scale = scale; };
|
||||
|
||||
/**
|
||||
* @brief The observable for player entity position updates.
|
||||
*/
|
||||
static Observable<Entity*, const PositionUpdate&> OnPlayerPositionUpdate;
|
||||
|
||||
void EraseVar(const std::u16string& name);
|
||||
protected:
|
||||
LWOOBJID m_ObjectID;
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
|
||||
m_AccountID = 0;
|
||||
m_Username = "";
|
||||
m_SessionKey = "";
|
||||
m_MuteExpire = 0;
|
||||
|
||||
m_MaxGMLevel = eGameMasterLevel::CIVILIAN; //The max GM level this account can assign to it's characters
|
||||
m_LastCharID = 0;
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
User& operator=(const User& other);
|
||||
bool operator==(const User& other) const;
|
||||
|
||||
uint32_t GetAccountID() const noexcept { return m_AccountID; }
|
||||
uint32_t GetAccountID() { return m_AccountID; }
|
||||
std::string& GetUsername() { return m_Username; }
|
||||
std::string& GetSessionKey() { return m_SessionKey; }
|
||||
SystemAddress& GetSystemAddress() { return m_SystemAddress; }
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "eCharacterCreationResponse.h"
|
||||
#include "eRenameResponse.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include "eChatMessageType.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "CheatDetection.h"
|
||||
|
||||
@@ -216,7 +216,7 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) {
|
||||
}
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::CHARACTER_LIST_RESPONSE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_LIST_RESPONSE);
|
||||
|
||||
std::vector<Character*> characters = u->GetCharacters();
|
||||
bitStream.Write<uint8_t>(characters.size());
|
||||
@@ -266,7 +266,7 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) {
|
||||
void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
||||
User* u = GetUser(sysAddr);
|
||||
if (!u) return;
|
||||
|
||||
|
||||
LUWString LUWStringName;
|
||||
uint32_t firstNameIndex;
|
||||
uint32_t middleNameIndex;
|
||||
@@ -422,7 +422,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
|
||||
Database::Get()->DeleteCharacter(charID);
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::UNEXPECTED_DISCONNECT);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::UNEXPECTED_DISCONNECT);
|
||||
bitStream.Write(objectID);
|
||||
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||
|
||||
@@ -439,7 +439,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
||||
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID objectID;
|
||||
inStream.Read(objectID);
|
||||
inStream.Read(objectID);
|
||||
GeneralUtils::ClearBit(objectID, eObjectBits::CHARACTER);
|
||||
GeneralUtils::ClearBit(objectID, eObjectBits::PERSISTENT);
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ void BehaviorContext::ExecuteUpdates() {
|
||||
this->scheduledUpdates.clear();
|
||||
}
|
||||
|
||||
bool BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bitStream) {
|
||||
void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bitStream) {
|
||||
BehaviorSyncEntry entry;
|
||||
auto found = false;
|
||||
|
||||
@@ -128,7 +128,7 @@ bool BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bit
|
||||
if (!found) {
|
||||
LOG("Failed to find behavior sync entry with sync id (%i)!", syncId);
|
||||
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto* behavior = entry.behavior;
|
||||
@@ -137,11 +137,10 @@ bool BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bit
|
||||
if (behavior == nullptr) {
|
||||
LOG("Invalid behavior for sync id (%i)!", syncId);
|
||||
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
behavior->Sync(this, bitStream, branch);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,26 +198,6 @@ void BehaviorContext::UpdatePlayerSyncs(float deltaTime) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this->skillUId != 0 && !clientInitalized) {
|
||||
EchoSyncSkill echo;
|
||||
echo.bDone = true;
|
||||
echo.uiSkillHandle = this->skillUId;
|
||||
echo.uiBehaviorHandle = entry.handle;
|
||||
|
||||
RakNet::BitStream bitStream{};
|
||||
entry.behavior->SyncCalculation(this, bitStream, entry.branchContext);
|
||||
|
||||
echo.sBitStream.assign(reinterpret_cast<char*>(bitStream.GetData()), bitStream.GetNumberOfBytesUsed());
|
||||
|
||||
RakNet::BitStream message;
|
||||
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, MessageType::Client::GAME_MSG);
|
||||
message.Write(this->originator);
|
||||
echo.Serialize(message);
|
||||
|
||||
Game::server->Send(message, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||
}
|
||||
|
||||
this->syncEntries.erase(this->syncEntries.begin() + i);
|
||||
}
|
||||
}
|
||||
@@ -285,7 +264,7 @@ bool BehaviorContext::CalculateUpdate(const float deltaTime) {
|
||||
// Write message
|
||||
RakNet::BitStream message;
|
||||
|
||||
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, MessageType::Client::GAME_MSG);
|
||||
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||
message.Write(this->originator);
|
||||
echo.Serialize(message);
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ struct BehaviorContext
|
||||
|
||||
void ExecuteUpdates();
|
||||
|
||||
bool SyncBehavior(uint32_t syncId, RakNet::BitStream& bitStream);
|
||||
void SyncBehavior(uint32_t syncId, RakNet::BitStream& bitStream);
|
||||
|
||||
void Update(float deltaTime);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "Behavior.h"
|
||||
#include "eAnimationFlags.h"
|
||||
#include "eAninmationFlags.h"
|
||||
|
||||
class ChangeIdleFlagsBehavior final : public Behavior {
|
||||
public:
|
||||
|
||||
@@ -27,8 +27,6 @@ void DamageAbsorptionBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
|
||||
destroyable->SetIsShielded(true);
|
||||
|
||||
context->RegisterTimerBehavior(this, branch, target->GetObjectID());
|
||||
|
||||
Game::entityManager->SerializeEntity(target);
|
||||
}
|
||||
|
||||
void DamageAbsorptionBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||
@@ -54,13 +52,7 @@ void DamageAbsorptionBehavior::Timer(BehaviorContext* context, BehaviorBranchCon
|
||||
|
||||
const auto toRemove = std::min(present, this->m_absorbAmount);
|
||||
|
||||
const auto remaining = present - toRemove;
|
||||
|
||||
destroyable->SetDamageToAbsorb(remaining);
|
||||
|
||||
destroyable->SetIsShielded(remaining > 0);
|
||||
|
||||
Game::entityManager->SerializeEntity(target);
|
||||
destroyable->SetDamageToAbsorb(present - toRemove);
|
||||
}
|
||||
|
||||
void DamageAbsorptionBehavior::Load() {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eMatchUpdate.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include "eChatMessageType.h"
|
||||
|
||||
#include "CDCurrencyTableTable.h"
|
||||
#include "CDActivityRewardsTable.h"
|
||||
@@ -501,7 +501,7 @@ void ActivityInstance::StartZone() {
|
||||
// only make a team if we have more than one participant
|
||||
if (participants.size() > 1) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::CREATE_TEAM);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::CREATE_TEAM);
|
||||
|
||||
bitStream.Write(leader->GetObjectID());
|
||||
bitStream.Write(m_Participants.size());
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
|
||||
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): Component(parent) {
|
||||
m_Target = LWOOBJID_EMPTY;
|
||||
m_DirtyStateOrTarget = true;
|
||||
m_State = AiState::spawn;
|
||||
SetAiState(AiState::spawn);
|
||||
m_Timer = 1.0f;
|
||||
m_StartPosition = parent->GetPosition();
|
||||
m_MovementAI = nullptr;
|
||||
|
||||
@@ -25,8 +25,6 @@ struct ZoneStatistics {
|
||||
uint64_t m_CoinsCollected;
|
||||
uint64_t m_EnemiesSmashed;
|
||||
uint64_t m_QuickBuildsCompleted;
|
||||
|
||||
bool operator==(const ZoneStatistics& rhs) const = default;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -281,9 +279,9 @@ public:
|
||||
*/
|
||||
void UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const;
|
||||
|
||||
void SetCurrentInteracting(LWOOBJID objectID) { m_CurrentInteracting = objectID; };
|
||||
void SetCurrentInteracting(LWOOBJID objectID) {m_CurrentInteracting = objectID;};
|
||||
|
||||
LWOOBJID GetCurrentInteracting() { return m_CurrentInteracting; };
|
||||
LWOOBJID GetCurrentInteracting() {return m_CurrentInteracting;};
|
||||
|
||||
/**
|
||||
* Sends a player to another zone with an optional clone ID
|
||||
@@ -309,14 +307,6 @@ public:
|
||||
|
||||
void SetDroppedCoins(const uint64_t value) { m_DroppedCoins = value; };
|
||||
|
||||
const std::array<uint64_t, 4>& GetClaimCodes() const { return m_ClaimCodes; };
|
||||
|
||||
const std::map<LWOMAPID, ZoneStatistics>& GetZoneStatistics() const { return m_ZoneStatistics; };
|
||||
|
||||
const std::u16string& GetLastRocketConfig() const { return m_LastRocketConfig; };
|
||||
|
||||
uint64_t GetTotalTimePlayed() const { return m_TotalTimePlayed; };
|
||||
|
||||
/**
|
||||
* Character info regarding this character, including clothing styles, etc.
|
||||
*/
|
||||
|
||||
@@ -187,7 +187,7 @@ void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||
|
||||
auto zoneInfo = Game::zoneManager->GetZone()->GetZoneID();
|
||||
|
||||
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0 && !Game::zoneManager->GetDisableSaveLocation()) {
|
||||
// if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0 && !Game::zoneManager->GetDisableSaveLocation()) {
|
||||
character->SetAttribute("lzx", m_Position.x);
|
||||
character->SetAttribute("lzy", m_Position.y);
|
||||
character->SetAttribute("lzz", m_Position.z);
|
||||
@@ -195,7 +195,7 @@ void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||
character->SetAttribute("lzry", m_Rotation.y);
|
||||
character->SetAttribute("lzrz", m_Rotation.z);
|
||||
character->SetAttribute("lzrw", m_Rotation.w);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void ControllablePhysicsComponent::SetPosition(const NiPoint3& pos) {
|
||||
|
||||
@@ -38,9 +38,6 @@
|
||||
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
|
||||
Implementation<bool, const Entity*> DestroyableComponent::IsEnemyImplentation;
|
||||
Implementation<bool, const Entity*> DestroyableComponent::IsFriendImplentation;
|
||||
|
||||
DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
||||
m_iArmor = 0;
|
||||
m_fMaxArmor = 0.0f;
|
||||
@@ -421,7 +418,6 @@ void DestroyableComponent::AddFaction(const int32_t factionID, const bool ignore
|
||||
}
|
||||
|
||||
bool DestroyableComponent::IsEnemy(const Entity* other) const {
|
||||
if (IsEnemyImplentation.ExecuteWithDefault(other, false)) return true;
|
||||
if (m_Parent->IsPlayer() && other->IsPlayer()) {
|
||||
auto* thisCharacterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||
if (!thisCharacterComponent) return false;
|
||||
@@ -444,7 +440,6 @@ bool DestroyableComponent::IsEnemy(const Entity* other) const {
|
||||
}
|
||||
|
||||
bool DestroyableComponent::IsFriend(const Entity* other) const {
|
||||
if (IsFriendImplentation.ExecuteWithDefault(other, false)) return true;
|
||||
const auto* otherDestroyableComponent = other->GetComponent<DestroyableComponent>();
|
||||
if (otherDestroyableComponent != nullptr) {
|
||||
for (const auto enemyFaction : m_EnemyFactionIDs) {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "Implementation.h"
|
||||
|
||||
namespace CppScripts {
|
||||
class Script;
|
||||
@@ -464,9 +463,6 @@ public:
|
||||
// handle hardcode mode drops
|
||||
void DoHardcoreModeDrops(const LWOOBJID source);
|
||||
|
||||
static Implementation<bool, const Entity*> IsEnemyImplentation;
|
||||
static Implementation<bool, const Entity*> IsFriendImplentation;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Whether or not the health should be serialized
|
||||
|
||||
@@ -37,9 +37,6 @@
|
||||
#include "CDScriptComponentTable.h"
|
||||
#include "CDObjectSkillsTable.h"
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
|
||||
this->m_Dirty = true;
|
||||
@@ -495,11 +492,6 @@ void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* const groups = inventoryElement->FirstChildElement("grps");
|
||||
if (groups) {
|
||||
LoadGroupXml(*groups);
|
||||
}
|
||||
|
||||
m_Consumable = inventoryElement->IntAttribute("csl", LOT_NULL);
|
||||
|
||||
auto* bag = bags->FirstChildElement();
|
||||
@@ -638,15 +630,6 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
|
||||
bags->LinkEndChild(bag);
|
||||
}
|
||||
|
||||
auto* groups = inventoryElement->FirstChildElement("grps");
|
||||
if (groups) {
|
||||
groups->DeleteChildren();
|
||||
} else {
|
||||
groups = inventoryElement->InsertNewChildElement("grps");
|
||||
}
|
||||
|
||||
UpdateGroupXml(*groups);
|
||||
|
||||
auto* items = inventoryElement->FirstChildElement("items");
|
||||
|
||||
if (items == nullptr) {
|
||||
@@ -892,6 +875,8 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
||||
|
||||
RemoveSlot(item->GetInfo().equipLocation);
|
||||
|
||||
PurgeProxies(item);
|
||||
|
||||
UnequipScripts(item);
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
@@ -901,8 +886,6 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
||||
PropertyManagementComponent::Instance()->GetParent()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
||||
Game::zoneManager->GetZoneControlObject()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
||||
}
|
||||
|
||||
PurgeProxies(item);
|
||||
}
|
||||
|
||||
|
||||
@@ -1522,10 +1505,10 @@ void InventoryComponent::PurgeProxies(Item* item) {
|
||||
const auto root = item->GetParent();
|
||||
|
||||
if (root != LWOOBJID_EMPTY) {
|
||||
Item* itemRoot = FindItemById(root);
|
||||
item = FindItemById(root);
|
||||
|
||||
if (itemRoot != nullptr) {
|
||||
UnEquipItem(itemRoot);
|
||||
if (item != nullptr) {
|
||||
UnEquipItem(item);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1620,110 +1603,3 @@ bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId) {
|
||||
m_Skills.insert_or_assign(slot, skillId);
|
||||
return true;
|
||||
}
|
||||
|
||||
void InventoryComponent::UpdateGroup(const GroupUpdate& groupUpdate) {
|
||||
if (groupUpdate.groupId.empty()) return;
|
||||
|
||||
if (groupUpdate.inventory != eInventoryType::BRICKS && groupUpdate.inventory != eInventoryType::MODELS) {
|
||||
LOG("Invalid inventory type for grouping %s", StringifiedEnum::ToString(groupUpdate.inventory).data());
|
||||
return;
|
||||
}
|
||||
|
||||
auto& groups = m_Groups[groupUpdate.inventory];
|
||||
auto groupItr = std::ranges::find_if(groups, [&groupUpdate](const Group& group) {
|
||||
return group.groupId == groupUpdate.groupId;
|
||||
});
|
||||
|
||||
if (groupUpdate.command != GroupUpdateCommand::ADD && groupItr == groups.end()) {
|
||||
LOG("Group %s not found in inventory %s. Cannot process command.", groupUpdate.groupId.c_str(), StringifiedEnum::ToString(groupUpdate.inventory).data());
|
||||
return;
|
||||
}
|
||||
|
||||
if (groupUpdate.command == GroupUpdateCommand::ADD && groups.size() >= MaximumGroupCount) {
|
||||
LOG("Cannot add group to inventory %s. Maximum group count reached.", StringifiedEnum::ToString(groupUpdate.inventory).data());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (groupUpdate.command) {
|
||||
case GroupUpdateCommand::ADD: {
|
||||
auto& group = groups.emplace_back();
|
||||
group.groupId = groupUpdate.groupId;
|
||||
group.groupName = groupUpdate.groupName;
|
||||
break;
|
||||
}
|
||||
case GroupUpdateCommand::ADD_LOT: {
|
||||
groupItr->lots.insert(groupUpdate.lot);
|
||||
break;
|
||||
}
|
||||
case GroupUpdateCommand::REMOVE: {
|
||||
groups.erase(groupItr);
|
||||
break;
|
||||
}
|
||||
case GroupUpdateCommand::REMOVE_LOT: {
|
||||
groupItr->lots.erase(groupUpdate.lot);
|
||||
break;
|
||||
}
|
||||
case GroupUpdateCommand::MODIFY: {
|
||||
groupItr->groupName = groupUpdate.groupName;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG("Invalid group update command %i", groupUpdate.command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::UpdateGroupXml(tinyxml2::XMLElement& groups) const {
|
||||
for (const auto& [inventory, groupsData] : m_Groups) {
|
||||
for (const auto& group : groupsData) {
|
||||
auto* const groupElement = groups.InsertNewChildElement("grp");
|
||||
|
||||
groupElement->SetAttribute("id", group.groupId.c_str());
|
||||
groupElement->SetAttribute("n", group.groupName.c_str());
|
||||
groupElement->SetAttribute("t", static_cast<uint32_t>(inventory));
|
||||
groupElement->SetAttribute("u", 0);
|
||||
std::ostringstream lots;
|
||||
bool first = true;
|
||||
for (const auto lot : group.lots) {
|
||||
if (!first) lots << ' ';
|
||||
first = false;
|
||||
|
||||
lots << lot;
|
||||
}
|
||||
groupElement->SetAttribute("l", lots.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::LoadGroupXml(const tinyxml2::XMLElement& groups) {
|
||||
auto* groupElement = groups.FirstChildElement("grp");
|
||||
|
||||
while (groupElement) {
|
||||
const char* groupId = nullptr;
|
||||
const char* groupName = nullptr;
|
||||
const char* lots = nullptr;
|
||||
uint32_t inventory = eInventoryType::INVALID;
|
||||
|
||||
groupElement->QueryStringAttribute("id", &groupId);
|
||||
groupElement->QueryStringAttribute("n", &groupName);
|
||||
groupElement->QueryStringAttribute("l", &lots);
|
||||
groupElement->QueryAttribute("t", &inventory);
|
||||
|
||||
if (!groupId || !groupName || !lots) {
|
||||
LOG("Failed to load group from xml id %i name %i lots %i",
|
||||
groupId == nullptr, groupName == nullptr, lots == nullptr);
|
||||
} else {
|
||||
auto& group = m_Groups[static_cast<eInventoryType>(inventory)].emplace_back();
|
||||
group.groupId = groupId;
|
||||
group.groupName = groupName;
|
||||
|
||||
for (const auto& lotStr : GeneralUtils::SplitString(lots, ' ')) {
|
||||
auto lot = GeneralUtils::TryParse<LOT>(lotStr);
|
||||
if (lot) group.lots.insert(*lot);
|
||||
}
|
||||
}
|
||||
|
||||
groupElement = groupElement->NextSiblingElement("grp");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,35 +37,6 @@ enum class eItemType : int32_t;
|
||||
*/
|
||||
class InventoryComponent final : public Component {
|
||||
public:
|
||||
struct Group {
|
||||
// Generated ID for the group. The ID is sent by the client and has the format user_group + Math.random() * UINT_MAX.
|
||||
std::string groupId;
|
||||
// Custom name assigned by the user.
|
||||
std::string groupName;
|
||||
// All the lots the user has in the group.
|
||||
std::set<LOT> lots;
|
||||
};
|
||||
|
||||
enum class GroupUpdateCommand {
|
||||
ADD,
|
||||
ADD_LOT,
|
||||
MODIFY,
|
||||
REMOVE,
|
||||
REMOVE_LOT,
|
||||
};
|
||||
|
||||
// Based on the command, certain fields will be used or not used.
|
||||
// for example, ADD_LOT wont use groupName, MODIFY wont use lots, etc.
|
||||
struct GroupUpdate {
|
||||
std::string groupId;
|
||||
std::string groupName;
|
||||
LOT lot;
|
||||
eInventoryType inventory;
|
||||
GroupUpdateCommand command;
|
||||
};
|
||||
|
||||
static constexpr uint32_t MaximumGroupCount = 50;
|
||||
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
||||
InventoryComponent(Entity* parent);
|
||||
|
||||
@@ -396,23 +367,14 @@ public:
|
||||
*/
|
||||
void UnequipScripts(Item* unequippedItem);
|
||||
|
||||
std::map<BehaviorSlot, uint32_t> GetSkills() { return m_Skills; };
|
||||
std::map<BehaviorSlot, uint32_t> GetSkills(){ return m_Skills; };
|
||||
|
||||
bool SetSkill(int slot, uint32_t skillId);
|
||||
bool SetSkill(BehaviorSlot slot, uint32_t skillId);
|
||||
|
||||
void UpdateGroup(const GroupUpdate& groupUpdate);
|
||||
void RemoveGroup(const std::string& groupId);
|
||||
|
||||
~InventoryComponent() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The key is the inventory the group belongs to, the value maps' key is the id for the group.
|
||||
* This is only used for bricks and model inventories.
|
||||
*/
|
||||
std::map<eInventoryType, std::vector<Group>> m_Groups{ { eInventoryType::BRICKS, {} }, { eInventoryType::MODELS, {} } };
|
||||
|
||||
/**
|
||||
* All the inventory this entity possesses
|
||||
*/
|
||||
@@ -515,9 +477,6 @@ private:
|
||||
* @param document the xml doc to load from
|
||||
*/
|
||||
void UpdatePetXml(tinyxml2::XMLDocument& document);
|
||||
|
||||
void LoadGroupXml(const tinyxml2::XMLElement& groups);
|
||||
void UpdateGroupXml(tinyxml2::XMLElement& groups) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
#include "ItemComponent.h"
|
||||
|
||||
void ItemComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {
|
||||
outBitStream.Write0();
|
||||
ItemComponent::ItemComponent(Entity* entity) : Component(entity) {
|
||||
m_UgcId = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
|
||||
m_Description = GeneralUtils::ASCIIToUTF16(m_Parent->GetVar<std::string>(u"userModelDesc"));
|
||||
m_Dirty = false;
|
||||
m_ModerationStatus = 2;
|
||||
LOG("%s", m_Parent->GetVarAsString(u"userModelDesc").c_str());
|
||||
}
|
||||
|
||||
void ItemComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {
|
||||
outBitStream.Write(m_Dirty || isConstruction);
|
||||
if (m_Dirty || isConstruction) {
|
||||
outBitStream.Write(m_UgcId);
|
||||
outBitStream.Write(m_ModerationStatus);
|
||||
outBitStream.Write(!m_Description.empty());
|
||||
if (!m_Description.empty()) {
|
||||
outBitStream.Write<uint32_t>(m_Description.size());
|
||||
outBitStream.Write(m_Description);
|
||||
}
|
||||
if (!isConstruction) m_Dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ItemComponent::UpdateDescription(const std::u16string& description) {
|
||||
if (m_Description == description) return;
|
||||
m_Dirty = true;
|
||||
m_Description = description;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,16 @@ class ItemComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ITEM;
|
||||
|
||||
ItemComponent(Entity* entity) : Component(entity) {}
|
||||
ItemComponent(Entity* entity);
|
||||
|
||||
void Serialize(RakNet::BitStream& bitStream, bool isConstruction) override;
|
||||
|
||||
void UpdateDescription(const std::u16string& description);
|
||||
private:
|
||||
std::u16string m_Description;
|
||||
bool m_Dirty = false;
|
||||
LWOOBJID m_UgcId = LWOOBJID_EMPTY;
|
||||
uint32_t m_ModerationStatus = 0;
|
||||
};
|
||||
|
||||
#endif //!__ITEMCOMPONENT__H__
|
||||
|
||||
@@ -6,54 +6,13 @@
|
||||
|
||||
#include "BehaviorStates.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "SimplePhysicsComponent.h"
|
||||
|
||||
#include "Database.h"
|
||||
|
||||
ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
||||
m_OriginalPosition = m_Parent->GetDefaultPosition();
|
||||
m_OriginalRotation = m_Parent->GetDefaultRotation();
|
||||
|
||||
m_userModelID = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
|
||||
}
|
||||
|
||||
void ModelComponent::LoadBehaviors() {
|
||||
auto behaviors = GeneralUtils::SplitString(m_Parent->GetVar<std::string>(u"userModelBehaviors"), ',');
|
||||
for (const auto& behavior : behaviors) {
|
||||
if (behavior.empty()) continue;
|
||||
|
||||
const auto behaviorId = GeneralUtils::TryParse<int32_t>(behavior);
|
||||
if (!behaviorId.has_value() || behaviorId.value() == 0) continue;
|
||||
|
||||
LOG_DEBUG("Loading behavior %d", behaviorId.value());
|
||||
auto& inserted = m_Behaviors.emplace_back();
|
||||
inserted.SetBehaviorId(*behaviorId);
|
||||
|
||||
const auto behaviorStr = Database::Get()->GetBehavior(behaviorId.value());
|
||||
|
||||
tinyxml2::XMLDocument behaviorXml;
|
||||
auto res = behaviorXml.Parse(behaviorStr.c_str(), behaviorStr.size());
|
||||
LOG_DEBUG("Behavior %i %d: %s", res, behaviorId.value(), behaviorStr.c_str());
|
||||
|
||||
const auto* const behaviorRoot = behaviorXml.FirstChildElement("Behavior");
|
||||
if (!behaviorRoot) {
|
||||
LOG("Failed to load behavior %d due to missing behavior root", behaviorId.value());
|
||||
continue;
|
||||
}
|
||||
inserted.Deserialize(*behaviorRoot);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||
// ItemComponent Serialization. Pets do not get this serialization.
|
||||
if (!m_Parent->HasComponent(eReplicaComponentType::PET)) {
|
||||
outBitStream.Write1();
|
||||
outBitStream.Write<LWOOBJID>(m_userModelID != LWOOBJID_EMPTY ? m_userModelID : m_Parent->GetObjectID());
|
||||
outBitStream.Write<int>(0);
|
||||
outBitStream.Write0();
|
||||
}
|
||||
|
||||
//actual model component:
|
||||
outBitStream.Write1(); // Yes we are writing model info
|
||||
outBitStream.Write0(); // Is pickable
|
||||
@@ -96,42 +55,10 @@ void ModelComponent::AddBehavior(AddMessage& msg) {
|
||||
for (auto& behavior : m_Behaviors) if (behavior.GetBehaviorId() == msg.GetBehaviorId()) return;
|
||||
m_Behaviors.insert(m_Behaviors.begin() + msg.GetBehaviorIndex(), PropertyBehavior());
|
||||
m_Behaviors.at(msg.GetBehaviorIndex()).HandleMsg(msg);
|
||||
auto* const simplePhysComponent = m_Parent->GetComponent<SimplePhysicsComponent>();
|
||||
if (simplePhysComponent) {
|
||||
simplePhysComponent->SetPhysicsMotionState(1);
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelComponent::MoveToInventory(MoveToInventoryMessage& msg) {
|
||||
if (msg.GetBehaviorIndex() >= m_Behaviors.size() || m_Behaviors.at(msg.GetBehaviorIndex()).GetBehaviorId() != msg.GetBehaviorId()) return;
|
||||
m_Behaviors.erase(m_Behaviors.begin() + msg.GetBehaviorIndex());
|
||||
// TODO move to the inventory
|
||||
if (m_Behaviors.empty()) {
|
||||
auto* const simplePhysComponent = m_Parent->GetComponent<SimplePhysicsComponent>();
|
||||
if (simplePhysComponent) {
|
||||
simplePhysComponent->SetPhysicsMotionState(4);
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::pair<int32_t, std::string>, 5> ModelComponent::GetBehaviorsForSave() const {
|
||||
std::array<std::pair<int32_t, std::string>, 5> toReturn{};
|
||||
for (auto i = 0; i < m_Behaviors.size(); i++) {
|
||||
const auto& behavior = m_Behaviors.at(i);
|
||||
if (behavior.GetBehaviorId() == -1) continue;
|
||||
auto& [id, behaviorData] = toReturn[i];
|
||||
id = behavior.GetBehaviorId();
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
auto* root = doc.NewElement("Behavior");
|
||||
behavior.Serialize(*root);
|
||||
doc.InsertFirstChild(root);
|
||||
|
||||
tinyxml2::XMLPrinter printer(0, true, 0);
|
||||
doc.Print(&printer);
|
||||
behaviorData = printer.CStr();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
@@ -29,8 +28,6 @@ public:
|
||||
|
||||
ModelComponent(Entity* parent);
|
||||
|
||||
void LoadBehaviors();
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
/**
|
||||
@@ -66,8 +63,8 @@ public:
|
||||
template<typename Msg>
|
||||
void HandleControlBehaviorsMsg(const AMFArrayValue& args) {
|
||||
static_assert(std::is_base_of_v<BehaviorMessageBase, Msg>, "Msg must be a BehaviorMessageBase");
|
||||
Msg msg{ args };
|
||||
for (auto&& behavior : m_Behaviors) {
|
||||
Msg msg(args);
|
||||
for (auto& behavior : m_Behaviors) {
|
||||
if (behavior.GetBehaviorId() == msg.GetBehaviorId()) {
|
||||
behavior.HandleMsg(msg);
|
||||
return;
|
||||
@@ -112,8 +109,6 @@ public:
|
||||
|
||||
void VerifyBehaviors();
|
||||
|
||||
std::array<std::pair<int32_t, std::string>, 5> GetBehaviorsForSave() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The behaviors of the model
|
||||
@@ -131,9 +126,4 @@ private:
|
||||
* The rotation original of the model
|
||||
*/
|
||||
NiQuaternion m_OriginalRotation;
|
||||
|
||||
/**
|
||||
* The ID of the user that made the model
|
||||
*/
|
||||
LWOOBJID m_userModelID;
|
||||
};
|
||||
|
||||
@@ -88,7 +88,7 @@ PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Compone
|
||||
m_Ability = ePetAbilityType::Invalid;
|
||||
m_StartPosition = NiPoint3Constant::ZERO;
|
||||
m_MovementAI = nullptr;
|
||||
m_TreasureTime = 0;
|
||||
m_TresureTime = 0;
|
||||
|
||||
std::string checkPreconditions = GeneralUtils::UTF16ToWTF8(parentEntity->GetVar<std::u16string>(u"CheckPrecondition"));
|
||||
|
||||
@@ -319,27 +319,27 @@ void PetComponent::Update(float deltaTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_TreasureTime > 0) {
|
||||
auto* treasure = Game::entityManager->GetEntity(m_Interaction);
|
||||
if (m_TresureTime > 0) {
|
||||
auto* tresure = Game::entityManager->GetEntity(m_Interaction);
|
||||
|
||||
if (treasure == nullptr) {
|
||||
m_TreasureTime = 0;
|
||||
if (tresure == nullptr) {
|
||||
m_TresureTime = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_TreasureTime -= deltaTime;
|
||||
m_TresureTime -= deltaTime;
|
||||
|
||||
m_MovementAI->Stop();
|
||||
|
||||
if (m_TreasureTime <= 0) {
|
||||
if (m_TresureTime <= 0) {
|
||||
m_Parent->SetOwnerOverride(m_Owner);
|
||||
|
||||
treasure->Smash(m_Parent->GetObjectID());
|
||||
tresure->Smash(m_Parent->GetObjectID());
|
||||
|
||||
m_Interaction = LWOOBJID_EMPTY;
|
||||
|
||||
m_TreasureTime = 0;
|
||||
m_TresureTime = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -381,7 +381,7 @@ void PetComponent::Update(float deltaTime) {
|
||||
float distance = Vector3::DistanceSquared(position, switchPosition);
|
||||
if (distance < 3 * 3) {
|
||||
m_Interaction = closestSwitch->GetParentEntity()->GetObjectID();
|
||||
closestSwitch->OnUse(m_Parent);
|
||||
closestSwitch->EntityEnter(m_Parent);
|
||||
} else if (distance < 20 * 20) {
|
||||
haltDistance = 1;
|
||||
|
||||
@@ -396,30 +396,30 @@ void PetComponent::Update(float deltaTime) {
|
||||
// Determine if the "Lost Tags" mission has been completed and digging has been unlocked
|
||||
const bool digUnlocked = missionComponent->GetMissionState(842) == eMissionState::COMPLETE;
|
||||
|
||||
Entity* closestTreasure = PetDigServer::GetClosestTreasure(position);
|
||||
Entity* closestTresure = PetDigServer::GetClosestTresure(position);
|
||||
|
||||
if (closestTreasure != nullptr && digUnlocked) {
|
||||
if (closestTresure != nullptr && digUnlocked) {
|
||||
// Skeleton Dragon Pat special case for bone digging
|
||||
if (closestTreasure->GetLOT() == 12192 && m_Parent->GetLOT() != 13067) {
|
||||
goto skipTreasure;
|
||||
if (closestTresure->GetLOT() == 12192 && m_Parent->GetLOT() != 13067) {
|
||||
goto skipTresure;
|
||||
}
|
||||
|
||||
NiPoint3 treasurePosition = closestTreasure->GetPosition();
|
||||
float distance = Vector3::DistanceSquared(position, treasurePosition);
|
||||
NiPoint3 tresurePosition = closestTresure->GetPosition();
|
||||
float distance = Vector3::DistanceSquared(position, tresurePosition);
|
||||
if (distance < 5 * 5) {
|
||||
m_Interaction = closestTreasure->GetObjectID();
|
||||
m_Interaction = closestTresure->GetObjectID();
|
||||
|
||||
Command(NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 1, 202, true);
|
||||
|
||||
m_TreasureTime = 2;
|
||||
m_TresureTime = 2;
|
||||
} else if (distance < 10 * 10) {
|
||||
haltDistance = 1;
|
||||
|
||||
destination = treasurePosition;
|
||||
destination = tresurePosition;
|
||||
}
|
||||
}
|
||||
|
||||
skipTreasure:
|
||||
skipTresure:
|
||||
|
||||
m_MovementAI->SetHaltDistance(haltDistance);
|
||||
|
||||
@@ -795,6 +795,8 @@ void PetComponent::Wander() {
|
||||
}
|
||||
|
||||
void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) {
|
||||
AddDrainImaginationTimer(item, fromTaming);
|
||||
|
||||
m_ItemId = item->GetId();
|
||||
m_DatabaseId = item->GetSubKey();
|
||||
|
||||
@@ -805,7 +807,6 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) {
|
||||
inventoryComponent->DespawnPet();
|
||||
|
||||
m_Owner = inventoryComponent->GetParent()->GetObjectID();
|
||||
AddDrainImaginationTimer(fromTaming);
|
||||
|
||||
auto* owner = GetOwner();
|
||||
|
||||
@@ -858,14 +859,17 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) {
|
||||
}
|
||||
}
|
||||
|
||||
void PetComponent::AddDrainImaginationTimer(bool fromTaming) {
|
||||
void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) {
|
||||
if (Game::config->GetValue("pets_take_imagination") != "1") return;
|
||||
|
||||
auto* playerEntity = Game::entityManager->GetEntity(m_Owner);
|
||||
if (!playerEntity) {
|
||||
LOG("owner was null or didnt exist!");
|
||||
return;
|
||||
}
|
||||
auto playerInventory = item->GetInventory();
|
||||
if (!playerInventory) return;
|
||||
|
||||
auto playerInventoryComponent = playerInventory->GetComponent();
|
||||
if (!playerInventoryComponent) return;
|
||||
|
||||
auto playerEntity = playerInventoryComponent->GetParent();
|
||||
if (!playerEntity) return;
|
||||
|
||||
auto playerDestroyableComponent = playerEntity->GetComponent<DestroyableComponent>();
|
||||
if (!playerDestroyableComponent) return;
|
||||
@@ -874,16 +878,12 @@ void PetComponent::AddDrainImaginationTimer(bool fromTaming) {
|
||||
if (!fromTaming) playerDestroyableComponent->Imagine(-1);
|
||||
|
||||
// Set this to a variable so when this is called back from the player the timer doesn't fire off.
|
||||
m_Parent->AddCallbackTimer(m_PetInfo.imaginationDrainRate, [this]() {
|
||||
const auto* owner = Game::entityManager->GetEntity(m_Owner);
|
||||
if (!owner) {
|
||||
LOG("owner was null or didnt exist!");
|
||||
m_Parent->AddCallbackTimer(m_PetInfo.imaginationDrainRate, [playerDestroyableComponent, this, item]() {
|
||||
if (!playerDestroyableComponent) {
|
||||
LOG("No petComponent and/or no playerDestroyableComponent");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* playerDestroyableComponent = owner->GetComponent<DestroyableComponent>();
|
||||
if (!playerDestroyableComponent) return;
|
||||
|
||||
// If we are out of imagination despawn the pet.
|
||||
if (playerDestroyableComponent->GetImagination() == 0) {
|
||||
this->Deactivate();
|
||||
@@ -893,13 +893,15 @@ void PetComponent::AddDrainImaginationTimer(bool fromTaming) {
|
||||
GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), eUseItemResponse::NoImaginationForPet);
|
||||
}
|
||||
|
||||
this->AddDrainImaginationTimer();
|
||||
this->AddDrainImaginationTimer(item);
|
||||
});
|
||||
}
|
||||
|
||||
void PetComponent::Deactivate() {
|
||||
GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), -1, u"despawn", "", LWOOBJID_EMPTY, 1, 1, true);
|
||||
|
||||
GameMessages::SendMarkInventoryItemAsActive(m_Owner, false, eUnequippableActiveType::PET, m_ItemId, GetOwner()->GetSystemAddress());
|
||||
|
||||
activePets.erase(m_Owner);
|
||||
|
||||
m_Parent->Kill();
|
||||
@@ -908,8 +910,6 @@ void PetComponent::Deactivate() {
|
||||
|
||||
if (owner == nullptr) return;
|
||||
|
||||
GameMessages::SendMarkInventoryItemAsActive(m_Owner, false, eUnequippableActiveType::PET, m_ItemId, owner->GetSystemAddress());
|
||||
|
||||
GameMessages::SendAddPetToPlayer(m_Owner, 0, u"", LWOOBJID_EMPTY, LOT_NULL, owner->GetSystemAddress());
|
||||
|
||||
GameMessages::SendRegisterPetID(m_Owner, LWOOBJID_EMPTY, owner->GetSystemAddress());
|
||||
@@ -1034,7 +1034,6 @@ Entity* PetComponent::GetParentEntity() const {
|
||||
}
|
||||
|
||||
PetComponent::~PetComponent() {
|
||||
m_Owner = LWOOBJID_EMPTY;
|
||||
}
|
||||
|
||||
void PetComponent::SetPetNameForModeration(const std::string& petName) {
|
||||
|
||||
@@ -205,7 +205,7 @@ public:
|
||||
*
|
||||
* @param item The item that represents this pet in the inventory.
|
||||
*/
|
||||
void AddDrainImaginationTimer(bool fromTaming = false);
|
||||
void AddDrainImaginationTimer(Item* item, bool fromTaming = false);
|
||||
|
||||
private:
|
||||
|
||||
@@ -329,7 +329,7 @@ private:
|
||||
* Timer that tracks how long a pet has been digging up some treasure, required to spawn the treasure contents
|
||||
* on time
|
||||
*/
|
||||
float m_TreasureTime;
|
||||
float m_TresureTime;
|
||||
|
||||
/**
|
||||
* The position that this pet was spawned at
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "Component.h"
|
||||
#include "Item.h"
|
||||
#include "PossessorComponent.h"
|
||||
#include "eAnimationFlags.h"
|
||||
#include "eAninmationFlags.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include "Amf3.h"
|
||||
#include "eObjectBits.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "ePropertySortType.h"
|
||||
#include "User.h"
|
||||
|
||||
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) {
|
||||
this->propertyQueries = {};
|
||||
@@ -76,103 +74,261 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index,
|
||||
launcher->Launch(entity, launcher->GetTargetZone(), cloneId);
|
||||
}
|
||||
|
||||
void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr) {
|
||||
const auto* const character = entity->GetCharacter();
|
||||
if (!character) return;
|
||||
const auto* const user = character->GetParentUser();
|
||||
if (!user) return;
|
||||
PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) {
|
||||
property.CloneId = cloneId;
|
||||
property.OwnerName = ownerName;
|
||||
property.Name = propertyName;
|
||||
property.Description = propertyDescription;
|
||||
property.Reputation = reputation;
|
||||
property.IsBestFriend = isBFF;
|
||||
property.IsFriend = isFriend;
|
||||
property.IsModeratorApproved = isModeratorApproved;
|
||||
property.IsAlt = isAlt;
|
||||
property.IsOwned = isOwned;
|
||||
property.AccessType = privacyOption;
|
||||
property.DateLastPublished = timeLastUpdated;
|
||||
property.PerformanceCost = performanceCost;
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery, bool wantLimits) {
|
||||
std::string base;
|
||||
if (customQuery == "") {
|
||||
base = baseQueryForProperties;
|
||||
} else {
|
||||
base = customQuery;
|
||||
}
|
||||
std::string orderBy = "";
|
||||
if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) {
|
||||
std::string friendsList = " AND p.owner_id IN (";
|
||||
|
||||
auto friendsListQuery = Database::Get()->CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;");
|
||||
|
||||
friendsListQuery->setUInt(1, character->GetID());
|
||||
friendsListQuery->setUInt(2, character->GetID());
|
||||
|
||||
auto friendsListQueryResult = friendsListQuery->executeQuery();
|
||||
|
||||
while (friendsListQueryResult->next()) {
|
||||
auto playerIDToConvert = friendsListQueryResult->getInt(1);
|
||||
friendsList = friendsList + std::to_string(playerIDToConvert) + ",";
|
||||
}
|
||||
// Replace trailing comma with the closing parenthesis.
|
||||
if (friendsList.at(friendsList.size() - 1) == ',') friendsList.erase(friendsList.size() - 1, 1);
|
||||
friendsList += ") ";
|
||||
|
||||
// If we have no friends then use a -1 for the query.
|
||||
if (friendsList.find("()") != std::string::npos) friendsList = " AND p.owner_id IN (-1) ";
|
||||
|
||||
orderBy += friendsList + "ORDER BY ci.name ASC ";
|
||||
|
||||
delete friendsListQueryResult;
|
||||
friendsListQueryResult = nullptr;
|
||||
|
||||
delete friendsListQuery;
|
||||
friendsListQuery = nullptr;
|
||||
} else if (sortMethod == SORT_TYPE_RECENT) {
|
||||
orderBy = "ORDER BY p.last_updated DESC ";
|
||||
} else if (sortMethod == SORT_TYPE_REPUTATION) {
|
||||
orderBy = "ORDER BY p.reputation DESC, p.last_updated DESC ";
|
||||
} else {
|
||||
orderBy = "ORDER BY p.last_updated DESC ";
|
||||
}
|
||||
return base + orderBy + (wantLimits ? "LIMIT ? OFFSET ?;" : ";");
|
||||
}
|
||||
|
||||
void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr) {
|
||||
|
||||
std::vector<PropertySelectQueryProperty> entries{};
|
||||
PropertySelectQueryProperty playerEntry{};
|
||||
|
||||
auto character = entity->GetCharacter();
|
||||
if (!character) return;
|
||||
|
||||
auto& entries = propertyQueries[entity->GetObjectID()];
|
||||
entries.clear();
|
||||
// Player property goes in index 1 of the vector. This is how the client expects it.
|
||||
const auto playerProperty = Database::Get()->GetPropertyInfo(m_MapID, character->GetPropertyCloneID());
|
||||
auto playerPropertyLookup = Database::Get()->CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?");
|
||||
|
||||
playerPropertyLookup->setInt(1, character->GetID());
|
||||
playerPropertyLookup->setInt(2, this->m_MapID);
|
||||
|
||||
auto playerPropertyLookupResults = playerPropertyLookup->executeQuery();
|
||||
|
||||
// If the player has a property this query will have a single result.
|
||||
auto& playerEntry = entries.emplace_back();
|
||||
if (playerProperty.has_value()) {
|
||||
playerEntry.OwnerName = character->GetName();
|
||||
playerEntry.IsBestFriend = true;
|
||||
playerEntry.IsFriend = true;
|
||||
playerEntry.IsAlt = true;
|
||||
playerEntry.IsOwned = true;
|
||||
playerEntry.CloneId = playerProperty->cloneId;
|
||||
playerEntry.Name = playerProperty->name;
|
||||
playerEntry.Description = playerProperty->description;
|
||||
playerEntry.AccessType = playerProperty->privacyOption;
|
||||
playerEntry.IsModeratorApproved = playerProperty->modApproved;
|
||||
playerEntry.DateLastPublished = playerProperty->lastUpdatedTime;
|
||||
playerEntry.Reputation = playerProperty->reputation;
|
||||
playerEntry.PerformanceCost = playerProperty->performanceCost;
|
||||
auto& entry = playerEntry;
|
||||
if (playerPropertyLookupResults->next()) {
|
||||
const auto cloneId = playerPropertyLookupResults->getUInt64(4);
|
||||
const auto propertyName = std::string(playerPropertyLookupResults->getString(5).c_str());
|
||||
const auto propertyDescription = std::string(playerPropertyLookupResults->getString(6).c_str());
|
||||
const auto privacyOption = playerPropertyLookupResults->getInt(9);
|
||||
const auto modApproved = playerPropertyLookupResults->getBoolean(10);
|
||||
const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11);
|
||||
const auto reputation = playerPropertyLookupResults->getUInt(14);
|
||||
const auto performanceCost = playerPropertyLookupResults->getFloat(16);
|
||||
|
||||
playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), propertyName, propertyDescription, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost);
|
||||
} else {
|
||||
playerEntry.OwnerName = character->GetName();
|
||||
playerEntry.IsBestFriend = true;
|
||||
playerEntry.IsFriend = true;
|
||||
playerEntry.IsAlt = false;
|
||||
playerEntry.IsOwned = false;
|
||||
playerEntry.CloneId = character->GetPropertyCloneID();
|
||||
playerEntry.Name = "";
|
||||
playerEntry.Description = "";
|
||||
playerEntry.AccessType = 0;
|
||||
playerEntry.IsModeratorApproved = false;
|
||||
playerEntry.DateLastPublished = 0;
|
||||
playerEntry.Reputation = 0;
|
||||
playerEntry.PerformanceCost = 0.0f;
|
||||
playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true);
|
||||
}
|
||||
|
||||
IProperty::PropertyLookup propertyLookup;
|
||||
propertyLookup.mapId = m_MapID;
|
||||
propertyLookup.searchString = filterText;
|
||||
propertyLookup.sortChoice = static_cast<ePropertySortType>(sortMethod);
|
||||
propertyLookup.playerSort = static_cast<uint32_t>(sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? PropertyPrivacyOption::Friends : PropertyPrivacyOption::Public);
|
||||
propertyLookup.playerId = character->GetID();
|
||||
propertyLookup.numResults = numResults;
|
||||
propertyLookup.startIndex = startIndex;
|
||||
delete playerPropertyLookupResults;
|
||||
playerPropertyLookupResults = nullptr;
|
||||
|
||||
const auto lookupResult = Database::Get()->GetProperties(propertyLookup);
|
||||
delete playerPropertyLookup;
|
||||
playerPropertyLookup = nullptr;
|
||||
|
||||
entries.push_back(playerEntry);
|
||||
|
||||
const auto query = BuildQuery(entity, sortMethod, character);
|
||||
|
||||
auto propertyLookup = Database::Get()->CreatePreppedStmt(query);
|
||||
|
||||
const auto searchString = "%" + filterText + "%";
|
||||
propertyLookup->setUInt(1, this->m_MapID);
|
||||
propertyLookup->setString(2, searchString.c_str());
|
||||
propertyLookup->setString(3, searchString.c_str());
|
||||
propertyLookup->setString(4, searchString.c_str());
|
||||
propertyLookup->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? static_cast<uint32_t>(PropertyPrivacyOption::Friends) : static_cast<uint32_t>(PropertyPrivacyOption::Public));
|
||||
propertyLookup->setInt(6, numResults);
|
||||
propertyLookup->setInt(7, startIndex);
|
||||
|
||||
auto propertyEntry = propertyLookup->executeQuery();
|
||||
|
||||
while (propertyEntry->next()) {
|
||||
const auto propertyId = propertyEntry->getUInt64(1);
|
||||
const auto owner = propertyEntry->getInt(2);
|
||||
const auto cloneId = propertyEntry->getUInt64(4);
|
||||
const auto propertyNameFromDb = std::string(propertyEntry->getString(5).c_str());
|
||||
const auto propertyDescriptionFromDb = std::string(propertyEntry->getString(6).c_str());
|
||||
const auto privacyOption = propertyEntry->getInt(9);
|
||||
const auto modApproved = propertyEntry->getBoolean(10);
|
||||
const auto dateLastUpdated = propertyEntry->getInt(11);
|
||||
const float reputation = propertyEntry->getInt(14);
|
||||
const auto performanceCost = propertyEntry->getFloat(16);
|
||||
|
||||
PropertySelectQueryProperty entry{};
|
||||
|
||||
std::string ownerName = "";
|
||||
bool isOwned = true;
|
||||
auto nameLookup = Database::Get()->CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
|
||||
|
||||
nameLookup->setUInt64(1, cloneId);
|
||||
|
||||
auto nameResult = nameLookup->executeQuery();
|
||||
|
||||
if (!nameResult->next()) {
|
||||
delete nameLookup;
|
||||
nameLookup = nullptr;
|
||||
|
||||
LOG("Failed to find property owner name for %llu!", cloneId);
|
||||
|
||||
for (const auto& propertyEntry : lookupResult->entries) {
|
||||
const auto owner = propertyEntry.ownerId;
|
||||
const auto otherCharacter = Database::Get()->GetCharacterInfo(owner);
|
||||
if (!otherCharacter.has_value()) {
|
||||
LOG("Failed to find property owner name for %u!", owner);
|
||||
continue;
|
||||
} else {
|
||||
isOwned = cloneId == character->GetPropertyCloneID();
|
||||
ownerName = std::string(nameResult->getString(1).c_str());
|
||||
}
|
||||
auto& entry = entries.emplace_back();
|
||||
|
||||
entry.IsOwned = entry.CloneId == otherCharacter->cloneId;
|
||||
entry.OwnerName = otherCharacter->name;
|
||||
entry.CloneId = propertyEntry.cloneId;
|
||||
entry.Name = propertyEntry.name;
|
||||
entry.Description = propertyEntry.description;
|
||||
entry.AccessType = propertyEntry.privacyOption;
|
||||
entry.IsModeratorApproved = propertyEntry.modApproved;
|
||||
entry.DateLastPublished = propertyEntry.lastUpdatedTime;
|
||||
entry.Reputation = propertyEntry.reputation;
|
||||
entry.PerformanceCost = propertyEntry.performanceCost;
|
||||
entry.IsBestFriend = false;
|
||||
entry.IsFriend = false;
|
||||
delete nameResult;
|
||||
nameResult = nullptr;
|
||||
|
||||
delete nameLookup;
|
||||
nameLookup = nullptr;
|
||||
|
||||
std::string propertyName = propertyNameFromDb;
|
||||
std::string propertyDescription = propertyDescriptionFromDb;
|
||||
|
||||
bool isBestFriend = false;
|
||||
bool isFriend = false;
|
||||
|
||||
// Convert owner char id to LWOOBJID
|
||||
LWOOBJID ownerObjId = owner;
|
||||
GeneralUtils::SetBit(ownerObjId, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(ownerObjId, eObjectBits::PERSISTENT);
|
||||
|
||||
// Query to get friend and best friend fields
|
||||
const auto friendCheck = Database::Get()->GetBestFriendStatus(character->GetID(), owner);
|
||||
auto friendCheck = Database::Get()->CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)");
|
||||
|
||||
friendCheck->setUInt(1, character->GetID());
|
||||
friendCheck->setUInt(2, ownerObjId);
|
||||
friendCheck->setUInt(3, ownerObjId);
|
||||
friendCheck->setUInt(4, character->GetID());
|
||||
|
||||
auto friendResult = friendCheck->executeQuery();
|
||||
|
||||
// If we got a result than the two players are friends.
|
||||
if (friendCheck.has_value()) {
|
||||
entry.IsFriend = true;
|
||||
entry.IsBestFriend = friendCheck->bestFriendStatus == 3;
|
||||
if (friendResult->next()) {
|
||||
isFriend = true;
|
||||
if (friendResult->getInt(1) == 3) {
|
||||
isBestFriend = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry.IsModeratorApproved && entity->GetGMLevel() >= eGameMasterLevel::LEAD_MODERATOR) {
|
||||
entry.Name = "[AWAITING APPROVAL]";
|
||||
entry.Description = "[AWAITING APPROVAL]";
|
||||
entry.IsModeratorApproved = true;
|
||||
delete friendCheck;
|
||||
friendCheck = nullptr;
|
||||
|
||||
delete friendResult;
|
||||
friendResult = nullptr;
|
||||
|
||||
bool isModeratorApproved = propertyEntry->getBoolean(10);
|
||||
|
||||
if (!isModeratorApproved && entity->GetGMLevel() >= eGameMasterLevel::LEAD_MODERATOR) {
|
||||
propertyName = "[AWAITING APPROVAL]";
|
||||
propertyDescription = "[AWAITING APPROVAL]";
|
||||
isModeratorApproved = true;
|
||||
}
|
||||
|
||||
bool isAlt = false;
|
||||
// Query to determine whether this property is an alt character of the entity.
|
||||
for (const auto charid : Database::Get()->GetAccountCharacterIds(user->GetAccountID())) {
|
||||
entry.IsAlt = charid == owner;
|
||||
if (entry.IsAlt) break;
|
||||
auto isAltQuery = Database::Get()->CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;");
|
||||
|
||||
isAltQuery->setInt(1, character->GetID());
|
||||
isAltQuery->setInt(2, owner);
|
||||
|
||||
auto isAltQueryResults = isAltQuery->executeQuery();
|
||||
|
||||
if (isAltQueryResults->next()) {
|
||||
isAlt = true;
|
||||
}
|
||||
|
||||
delete isAltQueryResults;
|
||||
isAltQueryResults = nullptr;
|
||||
|
||||
delete isAltQuery;
|
||||
isAltQuery = nullptr;
|
||||
|
||||
entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost);
|
||||
|
||||
entries.push_back(entry);
|
||||
}
|
||||
|
||||
delete propertyEntry;
|
||||
propertyEntry = nullptr;
|
||||
|
||||
delete propertyLookup;
|
||||
propertyLookup = nullptr;
|
||||
|
||||
propertyQueries[entity->GetObjectID()] = entries;
|
||||
|
||||
// Query here is to figure out whether or not to display the button to go to the next page or not.
|
||||
GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, lookupResult->totalEntriesMatchingQuery - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr);
|
||||
int32_t numberOfProperties = 0;
|
||||
|
||||
auto buttonQuery = BuildQuery(entity, sortMethod, character, "SELECT COUNT(*) 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 >= ? ", false);
|
||||
auto propertiesLeft = Database::Get()->CreatePreppedStmt(buttonQuery);
|
||||
|
||||
propertiesLeft->setUInt(1, this->m_MapID);
|
||||
propertiesLeft->setString(2, searchString.c_str());
|
||||
propertiesLeft->setString(3, searchString.c_str());
|
||||
propertiesLeft->setString(4, searchString.c_str());
|
||||
propertiesLeft->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2);
|
||||
|
||||
auto result = propertiesLeft->executeQuery();
|
||||
result->next();
|
||||
numberOfProperties = result->getInt(1);
|
||||
|
||||
delete result;
|
||||
result = nullptr;
|
||||
|
||||
delete propertiesLeft;
|
||||
propertiesLeft = nullptr;
|
||||
|
||||
GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,11 @@ public:
|
||||
* Returns the map ID for this property
|
||||
* @return the map ID for this property
|
||||
*/
|
||||
[[nodiscard]] LWOMAPID GetMapID() const noexcept { return m_MapID; };
|
||||
[[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; };
|
||||
|
||||
PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f);
|
||||
|
||||
std::string BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery = "", bool wantLimits = true);
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -74,4 +78,13 @@ private:
|
||||
* The base map ID for this property (Avant Grove, etc).
|
||||
*/
|
||||
LWOMAPID m_MapID;
|
||||
|
||||
enum ePropertySortType : int32_t {
|
||||
SORT_TYPE_FRIENDS = 0,
|
||||
SORT_TYPE_REPUTATION = 1,
|
||||
SORT_TYPE_RECENT = 3,
|
||||
SORT_TYPE_FEATURED = 5
|
||||
};
|
||||
|
||||
std::string baseQueryForProperties = "SELECT p.* 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 >= ? ";
|
||||
};
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
#include "eObjectBits.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "ModelComponent.h"
|
||||
#include "ItemComponent.h"
|
||||
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
#include "CppScripts.h"
|
||||
#include <ranges>
|
||||
|
||||
PropertyManagementComponent* PropertyManagementComponent::instance = nullptr;
|
||||
|
||||
@@ -154,21 +154,49 @@ void PropertyManagementComponent::SetPrivacyOption(PropertyPrivacyOption value)
|
||||
Database::Get()->UpdatePropertyModerationInfo(info);
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::UpdatePropertyDetails(std::string name, std::string description) {
|
||||
void PropertyManagementComponent::UpdatePropertyDetails(UpdatePropertyWithFilterCheck& update) {
|
||||
if (owner == LWOOBJID_EMPTY) return;
|
||||
|
||||
propertyName = name;
|
||||
if (update.isProperty) {
|
||||
propertyName = update.name;
|
||||
|
||||
propertyDescription = description;
|
||||
propertyDescription = update.description;
|
||||
|
||||
IProperty::Info info;
|
||||
info.id = propertyId;
|
||||
info.name = propertyName;
|
||||
info.description = propertyDescription;
|
||||
IProperty::Info info;
|
||||
info.id = propertyId;
|
||||
info.name = propertyName;
|
||||
info.description = propertyDescription;
|
||||
|
||||
Database::Get()->UpdatePropertyDetails(info);
|
||||
Database::Get()->UpdatePropertyDetails(info);
|
||||
|
||||
OnQueryPropertyData(GetOwner(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
OnQueryPropertyData(GetOwner(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
} else {
|
||||
auto* entity = Game::entityManager->GetEntity(update.worldId);
|
||||
if (!entity) return;
|
||||
|
||||
if (update.name.empty()) {
|
||||
entity->EraseVar(u"userModelName");
|
||||
} else {
|
||||
entity->SetVar<std::string>(u"userModelName", update.name);
|
||||
}
|
||||
|
||||
if (update.description.empty()) {
|
||||
entity->EraseVar(u"userModelDesc");
|
||||
} else {
|
||||
entity->SetVar<std::string>(u"userModelDesc", update.description);
|
||||
}
|
||||
|
||||
auto* owner = GetOwner();
|
||||
if (!owner) return;
|
||||
|
||||
GameMessages::SendSetName(update.worldId, GeneralUtils::ASCIIToUTF16(update.name), owner->GetSystemAddress());
|
||||
auto* itemComponent = entity->GetComponent<ItemComponent>();
|
||||
if (itemComponent) {
|
||||
itemComponent->UpdateDescription(GeneralUtils::ASCIIToUTF16(update.description));
|
||||
}
|
||||
|
||||
Game::entityManager->SerializeEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
|
||||
@@ -197,7 +225,7 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
|
||||
|
||||
auto prop_path = zone->GetPath(m_Parent->GetVarAsString(u"propertyName"));
|
||||
|
||||
if (prop_path){
|
||||
if (prop_path) {
|
||||
if (!prop_path->property.displayName.empty()) name = prop_path->property.displayName;
|
||||
description = prop_path->property.displayDesc;
|
||||
}
|
||||
@@ -327,12 +355,15 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
||||
return;
|
||||
}
|
||||
|
||||
item->SetCount(item->GetCount() - 1);
|
||||
|
||||
auto* node = new SpawnerNode();
|
||||
|
||||
node->position = position;
|
||||
node->rotation = rotation;
|
||||
for (const auto config : item->GetConfig()) {
|
||||
node->config.push_back(config->Copy());
|
||||
}
|
||||
|
||||
item->SetCount(item->GetCount() - 1);
|
||||
|
||||
ObjectIDManager::RequestPersistentID([this, node, modelLOT, entity, position, rotation, originalRotation](uint32_t persistentId) {
|
||||
SpawnerInfo info{};
|
||||
@@ -354,11 +385,27 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
||||
|
||||
auto* spawner = Game::zoneManager->GetSpawner(spawnerId);
|
||||
|
||||
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0));
|
||||
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"userModelID", info.spawnerID));
|
||||
info.nodes[0]->config.push_back(new LDFData<int>(u"modelType", 2));
|
||||
info.nodes[0]->config.push_back(new LDFData<bool>(u"propertyObjectID", true));
|
||||
info.nodes[0]->config.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
// If empty, insert the default config data since it doesn't exist yet
|
||||
|
||||
if (!node->HasVar(u"modelBehaviors")) {
|
||||
node->config.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0));
|
||||
}
|
||||
|
||||
if (!node->HasVar(u"userModelID")) {
|
||||
node->config.push_back(new LDFData<LWOOBJID>(u"userModelID", info.spawnerID));
|
||||
}
|
||||
|
||||
if (!node->HasVar(u"modelType")) {
|
||||
node->config.push_back(new LDFData<int>(u"modelType", 2));
|
||||
}
|
||||
|
||||
if (!node->HasVar(u"propertyObjectID")) {
|
||||
node->config.push_back(new LDFData<bool>(u"propertyObjectID", true));
|
||||
}
|
||||
|
||||
if (!node->HasVar(u"componentWhitelist")) {
|
||||
node->config.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
}
|
||||
|
||||
auto* model = spawner->Spawn();
|
||||
|
||||
@@ -438,7 +485,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
||||
std::vector<LDFBaseData*> settings;
|
||||
|
||||
//fill our settings with BBB gurbage
|
||||
LDFBaseData* ldfBlueprintID = new LDFData<LWOOBJID>(u"blueprintid", model->GetVar<LWOOBJID>(u"blueprintid"));
|
||||
LDFBaseData* ldfBlueprintID = new LDFData<LWOOBJID>(u"blueprintID", model->GetVar<LWOOBJID>(u"blueprintID"));
|
||||
LDFBaseData* userModelDesc = new LDFData<std::u16string>(u"userModelDesc", u"A cool model you made!");
|
||||
LDFBaseData* userModelHasBhvr = new LDFData<bool>(u"userModelHasBhvr", false);
|
||||
LDFBaseData* userModelID = new LDFData<LWOOBJID>(u"userModelID", model->GetVar<LWOOBJID>(u"userModelID"));
|
||||
@@ -486,8 +533,9 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
||||
return;
|
||||
}
|
||||
|
||||
inventoryComponent->AddItem(model->GetLOT(), 1, eLootSourceType::DELETION, INVALID, {}, LWOOBJID_EMPTY, false);
|
||||
inventoryComponent->AddItem(model->GetLOT(), 1, eLootSourceType::DELETION, INVALID, model->GetSettings(), LWOOBJID_EMPTY, false);
|
||||
|
||||
// figure out how to get the actual item we picked up instead of just the first lot we find
|
||||
auto* item = inventoryComponent->FindItemByLot(model->GetLOT());
|
||||
|
||||
if (item == nullptr) {
|
||||
@@ -574,42 +622,21 @@ void PropertyManagementComponent::Load() {
|
||||
|
||||
info.spawnerID = databaseModel.id;
|
||||
|
||||
std::vector<LDFBaseData*> settings;
|
||||
|
||||
//BBB property models need to have extra stuff set for them:
|
||||
if (databaseModel.lot == 14) {
|
||||
LWOOBJID blueprintID = databaseModel.ugcId;
|
||||
GeneralUtils::SetBit(blueprintID, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(blueprintID, eObjectBits::PERSISTENT);
|
||||
|
||||
settings.push_back(new LDFData<LWOOBJID>(u"blueprintid", blueprintID));
|
||||
settings.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
settings.push_back(new LDFData<int>(u"modelType", 2));
|
||||
settings.push_back(new LDFData<bool>(u"propertyObjectID", true));
|
||||
settings.push_back(new LDFData<LWOOBJID>(u"userModelID", databaseModel.id));
|
||||
if (!node->HasVar(u"blueprintID")) node->config.push_back(new LDFData<LWOOBJID>(u"blueprintID", blueprintID));
|
||||
} else {
|
||||
settings.push_back(new LDFData<int>(u"modelType", 2));
|
||||
settings.push_back(new LDFData<LWOOBJID>(u"userModelID", databaseModel.id));
|
||||
settings.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0));
|
||||
settings.push_back(new LDFData<bool>(u"propertyObjectID", true));
|
||||
settings.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
if (!node->HasVar(u"modelBehaviors")) node->config.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0));
|
||||
}
|
||||
|
||||
std::ostringstream userModelBehavior;
|
||||
bool firstAdded = false;
|
||||
for (auto behavior : databaseModel.behaviors) {
|
||||
if (behavior < 0) {
|
||||
LOG("Invalid behavior ID: %d, removing behavior reference from model", behavior);
|
||||
behavior = 0;
|
||||
}
|
||||
if (firstAdded) userModelBehavior << ",";
|
||||
userModelBehavior << behavior;
|
||||
firstAdded = true;
|
||||
}
|
||||
|
||||
settings.push_back(new LDFData<std::string>(u"userModelBehaviors", userModelBehavior.str()));
|
||||
|
||||
node->config = settings;
|
||||
if (!node->HasVar(u"modelType")) node->config.push_back(new LDFData<int>(u"modelType", 2));
|
||||
if (!node->HasVar(u"componentWhitelist")) node->config.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
if (!node->HasVar(u"propertyObjectID")) node->config.push_back(new LDFData<bool>(u"propertyObjectID", true));
|
||||
if (!node->HasVar(u"userModelID")) node->config.push_back(new LDFData<LWOOBJID>(u"userModelID", databaseModel.id));
|
||||
|
||||
const auto spawnerId = Game::zoneManager->MakeSpawner(info);
|
||||
|
||||
@@ -626,12 +653,6 @@ void PropertyManagementComponent::Save() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* const owner = GetOwner();
|
||||
if (!owner) return;
|
||||
|
||||
const auto* const character = owner->GetCharacter();
|
||||
if (!character) return;
|
||||
|
||||
auto present = Database::Get()->GetPropertyModels(propertyId);
|
||||
|
||||
std::vector<LWOOBJID> modelIds;
|
||||
@@ -646,20 +667,6 @@ void PropertyManagementComponent::Save() {
|
||||
if (entity == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto* modelComponent = entity->GetComponent<ModelComponent>();
|
||||
if (!modelComponent) continue;
|
||||
const auto modelBehaviors = modelComponent->GetBehaviorsForSave();
|
||||
|
||||
// save the behaviors of the model
|
||||
for (const auto& [behaviorId, behaviorStr] : modelBehaviors) {
|
||||
if (behaviorStr.empty() || behaviorId == -1 || behaviorId == 0) continue;
|
||||
IBehaviors::Info info {
|
||||
.behaviorId = behaviorId,
|
||||
.characterId = character->GetID(),
|
||||
.behaviorInfo = behaviorStr
|
||||
};
|
||||
Database::Get()->AddBehavior(info);
|
||||
}
|
||||
|
||||
const auto position = entity->GetPosition();
|
||||
const auto rotation = entity->GetRotation();
|
||||
@@ -671,13 +678,10 @@ void PropertyManagementComponent::Save() {
|
||||
model.position = position;
|
||||
model.rotation = rotation;
|
||||
model.ugcId = 0;
|
||||
for (auto i = 0; i < model.behaviors.size(); i++) {
|
||||
model.behaviors[i] = modelBehaviors[i].first;
|
||||
}
|
||||
|
||||
Database::Get()->InsertNewPropertyModel(propertyId, model, "Objects_" + std::to_string(model.lot) + "_name");
|
||||
} else {
|
||||
Database::Get()->UpdateModel(id, position, rotation, modelBehaviors);
|
||||
Database::Get()->UpdateModelPositionRotation(id, position, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ enum class PropertyPrivacyOption {
|
||||
/**
|
||||
* Your friends can visit your property
|
||||
*/
|
||||
Friends = 1,
|
||||
Friends = 1,
|
||||
|
||||
/**
|
||||
* Requires Mythran approval, everyone can visit your property
|
||||
*/
|
||||
Public = 2
|
||||
/**
|
||||
* Requires Mythran approval, everyone can visit your property
|
||||
*/
|
||||
Public = 2
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -30,6 +30,13 @@ enum class PropertyPrivacyOption {
|
||||
*/
|
||||
class PropertyManagementComponent final : public Component {
|
||||
public:
|
||||
struct UpdatePropertyWithFilterCheck {
|
||||
LWOOBJID objectId;
|
||||
LWOOBJID worldId;
|
||||
bool isProperty;
|
||||
std::string name;
|
||||
std::string description;
|
||||
};
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT;
|
||||
PropertyManagementComponent(Entity* parent);
|
||||
static PropertyManagementComponent* Instance();
|
||||
@@ -95,7 +102,7 @@ public:
|
||||
* @param name the name to set for the property
|
||||
* @param description the description to set for the property
|
||||
*/
|
||||
void UpdatePropertyDetails(std::string name, std::string description);
|
||||
void UpdatePropertyDetails(UpdatePropertyWithFilterCheck& update);
|
||||
|
||||
/**
|
||||
* Makes this property owned by the passed player ID, storing it in the database
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "LeaderboardManager.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "CDActivitiesTable.h"
|
||||
#include "eStateChangeType.h"
|
||||
#include <ctime>
|
||||
|
||||
#ifndef M_PI
|
||||
@@ -45,6 +44,7 @@ RacingControlComponent::RacingControlComponent(Entity* parent)
|
||||
m_LoadedPlayers = 0;
|
||||
m_LoadTimer = 0;
|
||||
m_Finished = 0;
|
||||
m_StartTime = 0;
|
||||
m_EmptyTimer = 0;
|
||||
m_SoloRacing = Game::config->GetValue("solo_racing") == "1";
|
||||
|
||||
@@ -77,9 +77,6 @@ void RacingControlComponent::OnPlayerLoaded(Entity* player) {
|
||||
|
||||
m_LoadedPlayers++;
|
||||
|
||||
// not live accurate to stun the player but prevents them from using skills during the race that are not meant to be used.
|
||||
GameMessages::SendSetStunned(player->GetObjectID(), eStateChangeType::PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY, true, true, true, true, true, true, true, true, true);
|
||||
|
||||
LOG("Loading player %i",
|
||||
m_LoadedPlayers);
|
||||
m_LobbyPlayers.push_back(player->GetObjectID());
|
||||
@@ -397,6 +394,25 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t bu
|
||||
GameMessages::SendNotifyRacingClient(
|
||||
m_Parent->GetObjectID(), 2, 0, LWOOBJID_EMPTY, u"",
|
||||
player->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
|
||||
if (missionComponent == nullptr) return;
|
||||
|
||||
missionComponent->Progress(eMissionTaskType::RACING, 0, static_cast<LWOOBJID>(eRacingTaskParam::COMPETED_IN_RACE)); // Progress task for competing in a race
|
||||
missionComponent->Progress(eMissionTaskType::RACING, data->smashedTimes, static_cast<LWOOBJID>(eRacingTaskParam::SAFE_DRIVER)); // Finish a race without being smashed.
|
||||
|
||||
// If solo racing is enabled OR if there are 3 players in the race, progress placement tasks.
|
||||
if (m_SoloRacing || m_LoadedPlayers > 2) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, data->finished, static_cast<LWOOBJID>(eRacingTaskParam::FINISH_WITH_PLACEMENT)); // Finish in 1st place on a race
|
||||
if (data->finished == 1) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::FIRST_PLACE_MULTIPLE_TRACKS)); // Finish in 1st place on multiple tracks.
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::WIN_RACE_IN_WORLD)); // Finished first place in specific world.
|
||||
}
|
||||
if (data->finished == m_LoadedPlayers) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::LAST_PLACE_FINISH)); // Finished first place in specific world.
|
||||
}
|
||||
}
|
||||
} else if ((id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") && button == m_ActivityExitConfirm) {
|
||||
auto* vehicle = Game::entityManager->GetEntity(data->vehicleID);
|
||||
|
||||
@@ -426,9 +442,9 @@ void RacingControlComponent::Serialize(RakNet::BitStream& outBitStream, bool bIs
|
||||
outBitStream.Write(player.playerID);
|
||||
|
||||
outBitStream.Write(player.data[0]);
|
||||
if (player.finished != 0) outBitStream.Write<float>(player.raceTime.count() / 1000.0f);
|
||||
if (player.finished != 0) outBitStream.Write<float>(player.raceTime);
|
||||
else outBitStream.Write(player.data[1]);
|
||||
if (player.finished != 0) outBitStream.Write<float>(player.bestLapTime.count() / 1000.0f);
|
||||
if (player.finished != 0) outBitStream.Write<float>(player.bestLapTime);
|
||||
else outBitStream.Write(player.data[2]);
|
||||
if (player.finished == 1) outBitStream.Write<float>(1.0f);
|
||||
else outBitStream.Write(player.data[3]);
|
||||
@@ -489,8 +505,8 @@ void RacingControlComponent::Serialize(RakNet::BitStream& outBitStream, bool bIs
|
||||
if (player.finished == 0) continue;
|
||||
outBitStream.Write1(); // Has more data
|
||||
outBitStream.Write(player.playerID);
|
||||
outBitStream.Write<float>(player.bestLapTime.count() / 1000.0f);
|
||||
outBitStream.Write<float>(player.raceTime.count() / 1000.0f);
|
||||
outBitStream.Write<float>(player.bestLapTime);
|
||||
outBitStream.Write<float>(player.raceTime);
|
||||
}
|
||||
|
||||
outBitStream.Write0(); // No more data
|
||||
@@ -720,7 +736,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
|
||||
m_StartTime = std::chrono::high_resolution_clock::now();
|
||||
m_StartTime = std::time(nullptr);
|
||||
}
|
||||
|
||||
m_StartTimer += deltaTime;
|
||||
@@ -809,60 +825,46 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
|
||||
// Reached the start point, lapped
|
||||
if (respawnIndex == 0) {
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
const auto lapTime = std::chrono::duration_cast<std::chrono::milliseconds>(now - (player.lap == 0 ? m_StartTime : player.lapTime));
|
||||
time_t lapTime = std::time(nullptr) - (player.lap == 0 ? m_StartTime : player.lapTime);
|
||||
|
||||
// Cheating check
|
||||
if (lapTime.count() < 40000) {
|
||||
if (lapTime < 40) {
|
||||
continue;
|
||||
}
|
||||
|
||||
player.lapTime = now;
|
||||
player.lap++;
|
||||
|
||||
if (player.bestLapTime > lapTime || player.lap == 0) {
|
||||
player.lapTime = std::time(nullptr);
|
||||
|
||||
if (player.bestLapTime == 0 || player.bestLapTime > lapTime) {
|
||||
player.bestLapTime = lapTime;
|
||||
|
||||
LOG("Best lap time (%llu)", lapTime);
|
||||
}
|
||||
|
||||
player.lap++;
|
||||
|
||||
auto* missionComponent =
|
||||
playerEntity->GetComponent<MissionComponent>();
|
||||
|
||||
if (missionComponent != nullptr) {
|
||||
|
||||
// Progress lap time tasks
|
||||
missionComponent->Progress(eMissionTaskType::RACING, lapTime.count(), static_cast<LWOOBJID>(eRacingTaskParam::LAP_TIME));
|
||||
missionComponent->Progress(eMissionTaskType::RACING, (lapTime) * 1000, static_cast<LWOOBJID>(eRacingTaskParam::LAP_TIME));
|
||||
|
||||
if (player.lap == 3) {
|
||||
m_Finished++;
|
||||
player.finished = m_Finished;
|
||||
|
||||
const auto raceTime = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_StartTime);
|
||||
const auto raceTime =
|
||||
(std::time(nullptr) - m_StartTime);
|
||||
|
||||
player.raceTime = raceTime;
|
||||
|
||||
LOG("Completed time %llums %fs", raceTime.count(), raceTime.count() / 1000.0f);
|
||||
LOG("Completed time %llu, %llu",
|
||||
raceTime, raceTime * 1000);
|
||||
|
||||
LeaderboardManager::SaveScore(playerEntity->GetObjectID(), m_ActivityID, static_cast<float>(player.raceTime.count()) / 1000, static_cast<float>(player.bestLapTime.count()) / 1000, static_cast<float>(player.finished == 1));
|
||||
LeaderboardManager::SaveScore(playerEntity->GetObjectID(), m_ActivityID, static_cast<float>(player.raceTime), static_cast<float>(player.bestLapTime), static_cast<float>(player.finished == 1));
|
||||
// Entire race time
|
||||
missionComponent->Progress(eMissionTaskType::RACING, player.raceTime.count(), static_cast<LWOOBJID>(eRacingTaskParam::TOTAL_TRACK_TIME));
|
||||
|
||||
missionComponent->Progress(eMissionTaskType::RACING, 0, static_cast<LWOOBJID>(eRacingTaskParam::COMPETED_IN_RACE)); // Progress task for competing in a race
|
||||
missionComponent->Progress(eMissionTaskType::RACING, player.smashedTimes, static_cast<LWOOBJID>(eRacingTaskParam::SAFE_DRIVER)); // Finish a race without being smashed.
|
||||
|
||||
// If solo racing is enabled OR if there are 3 players in the race, progress placement tasks.
|
||||
if (m_SoloRacing || m_RacingPlayers.size() > 2) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, player.finished, static_cast<LWOOBJID>(eRacingTaskParam::FINISH_WITH_PLACEMENT)); // Finish in 1st place on a race
|
||||
if (player.finished == 1) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::FIRST_PLACE_MULTIPLE_TRACKS)); // Finish in 1st place on multiple tracks.
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::WIN_RACE_IN_WORLD)); // Finished first place in specific world.
|
||||
}
|
||||
if (player.finished == m_RacingPlayers.size()) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::LAST_PLACE_FINISH)); // Finished first place in specific world.
|
||||
}
|
||||
}
|
||||
missionComponent->Progress(eMissionTaskType::RACING, (raceTime) * 1000, static_cast<LWOOBJID>(eRacingTaskParam::TOTAL_TRACK_TIME));
|
||||
|
||||
auto* characterComponent = playerEntity->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
@@ -871,8 +873,8 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
}
|
||||
}
|
||||
|
||||
LOG("Lapped (%i) in (%llums %fs)", player.lap,
|
||||
lapTime.count(), lapTime.count() / 1000.0f);
|
||||
LOG("Lapped (%i) in (%llu)", player.lap,
|
||||
lapTime);
|
||||
}
|
||||
|
||||
LOG("Reached point (%i)/(%i)", player.respawnIndex,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
* Information for each player in the race
|
||||
@@ -73,12 +72,12 @@ struct RacingPlayerInfo {
|
||||
/**
|
||||
* The fastest lap time of the player
|
||||
*/
|
||||
std::chrono::milliseconds bestLapTime;
|
||||
time_t bestLapTime = 0;
|
||||
|
||||
/**
|
||||
* The current lap time of the player
|
||||
*/
|
||||
std::chrono::high_resolution_clock::time_point lapTime;
|
||||
time_t lapTime = 0;
|
||||
|
||||
/**
|
||||
* The number of times this player smashed their car
|
||||
@@ -98,7 +97,7 @@ struct RacingPlayerInfo {
|
||||
/**
|
||||
* Unused
|
||||
*/
|
||||
std::chrono::milliseconds raceTime;
|
||||
time_t raceTime = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -232,7 +231,7 @@ private:
|
||||
/**
|
||||
* The time the race was started
|
||||
*/
|
||||
std::chrono::high_resolution_clock::time_point m_StartTime;
|
||||
time_t m_StartTime;
|
||||
|
||||
/**
|
||||
* Timer for tracking how long a player was alone in this race
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "BitStreamUtils.h"
|
||||
#include "eObjectWorldState.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "MessageType/Master.h"
|
||||
#include "eMasterMessageType.h"
|
||||
|
||||
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) {
|
||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||
@@ -137,7 +137,7 @@ LWOCLONEID RocketLaunchpadControlComponent::GetSelectedCloneId(LWOOBJID player)
|
||||
|
||||
void RocketLaunchpadControlComponent::TellMasterToPrepZone(int zoneID) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, MessageType::Master::PREP_ZONE);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PREP_ZONE);
|
||||
bitStream.Write(zoneID);
|
||||
Game::server->SendToMaster(bitStream);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, uint32_t componen
|
||||
} else {
|
||||
SetClimbableType(eClimbableType::CLIMBABLE_TYPE_NOT);
|
||||
}
|
||||
m_PhysicsMotionState = m_Parent->GetVarAs<uint32_t>(u"motionType");
|
||||
}
|
||||
|
||||
SimplePhysicsComponent::~SimplePhysicsComponent() {
|
||||
@@ -48,10 +47,11 @@ void SimplePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIs
|
||||
}
|
||||
|
||||
// Physics motion state
|
||||
outBitStream.Write(m_DirtyPhysicsMotionState || bIsInitialUpdate);
|
||||
if (m_DirtyPhysicsMotionState || bIsInitialUpdate) {
|
||||
if (m_PhysicsMotionState != 0) {
|
||||
outBitStream.Write1();
|
||||
outBitStream.Write<uint32_t>(m_PhysicsMotionState);
|
||||
m_DirtyPhysicsMotionState = false;
|
||||
} else {
|
||||
outBitStream.Write0();
|
||||
}
|
||||
PhysicsComponent::Serialize(outBitStream, bIsInitialUpdate);
|
||||
}
|
||||
@@ -61,6 +61,5 @@ uint32_t SimplePhysicsComponent::GetPhysicsMotionState() const {
|
||||
}
|
||||
|
||||
void SimplePhysicsComponent::SetPhysicsMotionState(uint32_t value) {
|
||||
m_DirtyPhysicsMotionState = m_PhysicsMotionState != value;
|
||||
m_PhysicsMotionState = value;
|
||||
}
|
||||
|
||||
@@ -102,9 +102,7 @@ private:
|
||||
/**
|
||||
* The current physics motion state
|
||||
*/
|
||||
uint32_t m_PhysicsMotionState = 5;
|
||||
|
||||
bool m_DirtyPhysicsMotionState = true;
|
||||
uint32_t m_PhysicsMotionState = 0;
|
||||
|
||||
/**
|
||||
* Whether or not the entity is climbable
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "CDClientManager.h"
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "MessageType/Client.h"
|
||||
#include "eClientMessageType.h"
|
||||
|
||||
ProjectileSyncEntry::ProjectileSyncEntry() {
|
||||
}
|
||||
@@ -38,7 +38,7 @@ bool SkillComponent::CastPlayerSkill(const uint32_t behaviorId, const uint32_t s
|
||||
|
||||
context->skillID = skillID;
|
||||
|
||||
this->m_managedBehaviors.insert({ skillUid, context });
|
||||
this->m_managedBehaviors.insert_or_assign(skillUid, context);
|
||||
|
||||
auto* behavior = Behavior::CreateBehavior(behaviorId);
|
||||
|
||||
@@ -52,24 +52,17 @@ bool SkillComponent::CastPlayerSkill(const uint32_t behaviorId, const uint32_t s
|
||||
}
|
||||
|
||||
void SkillComponent::SyncPlayerSkill(const uint32_t skillUid, const uint32_t syncId, RakNet::BitStream& bitStream) {
|
||||
const auto index = this->m_managedBehaviors.equal_range(skillUid);
|
||||
const auto index = this->m_managedBehaviors.find(skillUid);
|
||||
|
||||
if (index.first == this->m_managedBehaviors.end()) {
|
||||
if (index == this->m_managedBehaviors.end()) {
|
||||
LOG("Failed to find skill with uid (%i)!", skillUid, syncId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool foundSyncId = false;
|
||||
for (auto it = index.first; it != index.second && !foundSyncId; ++it) {
|
||||
const auto& context = it->second;
|
||||
auto* context = index->second;
|
||||
|
||||
foundSyncId = context->SyncBehavior(syncId, bitStream);
|
||||
}
|
||||
|
||||
if (!foundSyncId) {
|
||||
LOG("Failed to find sync id (%i) for skill with uid (%i)!", syncId, skillUid);
|
||||
}
|
||||
context->SyncBehavior(syncId, bitStream);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +138,7 @@ void SkillComponent::Update(const float deltaTime) {
|
||||
for (const auto& pair : this->m_managedBehaviors) pair.second->UpdatePlayerSyncs(deltaTime);
|
||||
}
|
||||
|
||||
std::multimap<uint32_t, BehaviorContext*> keep{};
|
||||
std::map<uint32_t, BehaviorContext*> keep{};
|
||||
|
||||
for (const auto& pair : this->m_managedBehaviors) {
|
||||
auto* context = pair.second;
|
||||
@@ -183,7 +176,7 @@ void SkillComponent::Update(const float deltaTime) {
|
||||
}
|
||||
}
|
||||
|
||||
keep.insert({ pair.first, context });
|
||||
keep.insert_or_assign(pair.first, context);
|
||||
}
|
||||
|
||||
this->m_managedBehaviors = keep;
|
||||
@@ -292,7 +285,7 @@ SkillExecutionResult SkillComponent::CalculateBehavior(
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
this->m_managedBehaviors.insert({ context->skillUId, context });
|
||||
this->m_managedBehaviors.insert_or_assign(context->skillUId, context);
|
||||
|
||||
if (!clientInitalized) {
|
||||
// Echo start skill
|
||||
@@ -320,7 +313,7 @@ SkillExecutionResult SkillComponent::CalculateBehavior(
|
||||
// Write message
|
||||
RakNet::BitStream message;
|
||||
|
||||
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, MessageType::Client::GAME_MSG);
|
||||
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||
message.Write(this->m_Parent->GetObjectID());
|
||||
start.Serialize(message);
|
||||
|
||||
@@ -451,7 +444,7 @@ void SkillComponent::SyncProjectileCalculation(const ProjectileSyncEntry& entry)
|
||||
|
||||
RakNet::BitStream message;
|
||||
|
||||
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, MessageType::Client::GAME_MSG);
|
||||
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||
message.Write(this->m_Parent->GetObjectID());
|
||||
projectileImpact.Serialize(message);
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ private:
|
||||
/**
|
||||
* All of the active skills mapped by their unique ID.
|
||||
*/
|
||||
std::multimap<uint32_t, BehaviorContext*> m_managedBehaviors;
|
||||
std::map<uint32_t, BehaviorContext*> m_managedBehaviors;
|
||||
|
||||
/**
|
||||
* All active projectiles.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user