Compare commits

..

1 Commits

Author SHA1 Message Date
jadebenn
7b819d508b Squashed commit of the following:
commit f4311e593f
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Nov 16 22:16:50 2024 -0600

    temp fix for MSVC debug builds

commit 0e81c69de8
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Nov 16 21:11:04 2024 -0600

    CMakePresets indentation

commit d7aa52a0fc
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Nov 16 21:03:37 2024 -0600

    use DLU_CONFIG_DIR envvar

commit d1bfe9f15d
Merge: 6e781da2 de3fe931
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Sat Nov 16 20:24:05 2024 -0600

    Merge branch 'main' into MSVCCompilerFlags

commit 6e781da2e7
Merge: 6ccd72c6 3a6123fe
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Sat Apr 13 18:15:16 2024 -0500

    Merge remote-tracking branch 'upstream/main' into MSVCCompilerFlags

commit 6ccd72c6a9
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Sat Apr 13 17:48:58 2024 -0500

    add RelWithDebInfo presets and move -Werror flag into presets.json

commit b96cfd71a4
Merge: c4adcee8 1ee45639
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Apr 9 01:47:17 2024 -0500

    Merge remote-tracking branch 'upstream/main' into MSVCCompilerFlags

commit c4adcee8e8
Merge: 7f9fcb5b 28ce8ac5
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Mon Apr 8 22:30:35 2024 -0500

    Merge remote-tracking branch 'upstream/main' into MSVCCompilerFlags

commit 7f9fcb5b75
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Mon Apr 8 22:10:01 2024 -0500

    change gnu and clang build directories to enable consistent artifact generation

commit 553740e8a0
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Mon Apr 8 21:38:34 2024 -0500

    update build presets

commit 39a8029fda
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Mon Apr 8 20:30:06 2024 -0500

    update github actions

commit 7eae64f8a6
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Mon Apr 8 20:18:46 2024 -0500

    disable /WX on MSVC

commit 24d3bc0ce6
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Mon Apr 8 20:11:59 2024 -0500

    altered cmake configuration scripts

commit 368f4ccabf
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Sat Apr 6 23:00:04 2024 -0500

    change defaults

commit 7d7ea68bf9
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 22:23:32 2024 -0500

    fix preset

commit 57d0b12f9b
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Sat Apr 6 21:50:32 2024 -0500

    expand cmake presets

commit aa62d357bb
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 20:50:26 2024 -0500

    rename gcc to gnu

commit d6e4edd886
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 20:27:20 2024 -0500

    change runtime output dir

commit abe413f239
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 20:22:47 2024 -0500

    debug try 2

commit c6c771b892
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 20:16:00 2024 -0500

    add debug messages (again)

commit 6c6966afd2
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 19:46:58 2024 -0500

    was not actually fixed

commit fab74c90b6
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 19:37:02 2024 -0500

    are these messages actually somehow fixing the issue?

commit a4b6b7c0d9
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 19:27:34 2024 -0500

    see if this re-breaks mac

commit 07626f8ebb
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 19:04:59 2024 -0500

    back to debug messages

commit bdf9adc0e8
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:55 2024 -0500

    Revert "try disabling an apple-specific build rule"

    This reverts commit 45ec66e976.

commit 8154207848
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:53 2024 -0500

    Revert "more fiddling with mac test builds"

    This reverts commit 0f843c02c9.

commit 8f5c10d158
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:52 2024 -0500

    Revert "try and narrow down the macos build failure cause"

    This reverts commit 5fd86833fa.

commit 54876bf886
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:50 2024 -0500

    Revert "try stripping out all the custom macos test logic again"

    This reverts commit cc15a26ce8.

commit 8af35727a6
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:48 2024 -0500

    Revert "I'm really just throwing everything to the wall and seeing what sticks"

    This reverts commit 1a05b027fe.

commit e143f22ada
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:46 2024 -0500

    Revert "more macos tinkering"

    This reverts commit 829ec35b57.

commit 495e70c376
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:44 2024 -0500

    Revert "implib"

    This reverts commit d41349d6ed.

commit 37dbb52104
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:42 2024 -0500

    Revert "try manual link directory specification"

    This reverts commit 0c2d40632e.

commit ce568189fc
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:40 2024 -0500

    Revert "save me"

    This reverts commit bd73aa21a9.

commit c420a72016
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:36 2024 -0500

    Revert "aaaaaaaaa"

    This reverts commit 338279c396.

commit dccac945bb
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:47:08 2024 -0500

    Revert "paths paths paths"

    This reverts commit 9a7d86aa6c.

commit 9a7d86aa6c
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:39:08 2024 -0500

    paths paths paths

commit 338279c396
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:29:01 2024 -0500

    aaaaaaaaa

commit bd73aa21a9
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:21:16 2024 -0500

    save me

commit 0c2d40632e
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 18:09:03 2024 -0500

    try manual link directory specification

commit d41349d6ed
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 17:52:20 2024 -0500

    implib

commit 829ec35b57
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 17:43:47 2024 -0500

    more macos tinkering

commit 1a05b027fe
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 17:18:41 2024 -0500

    I'm really just throwing everything to the wall and seeing what sticks

commit cc15a26ce8
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 17:09:45 2024 -0500

    try stripping out all the custom macos test logic again

commit 5fd86833fa
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 16:54:53 2024 -0500

    try and narrow down the macos build failure cause

commit 0f843c02c9
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 16:47:19 2024 -0500

    more fiddling with mac test builds

commit 45ec66e976
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 16:29:29 2024 -0500

    try disabling an apple-specific build rule

commit 6e41423dc3
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 04:01:07 2024 -0500

    one last MacOS try for the night

commit bc79a17ddb
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 03:50:41 2024 -0500

    try fixing macos build

commit d6031ce9f5
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 03:04:52 2024 -0500

    try zero-initializinng this struct to solve docker issue

commit 24cbd94a80
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Apr 6 02:34:36 2024 -0500

    attempted docker fix

commit 7812f27330
Merge: ef8029d4 18c27b14
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Fri Apr 5 23:32:29 2024 -0500

    Merge branch 'main' into MSVCCompilerFlags

commit ef8029d46f
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Fri Apr 5 23:30:26 2024 -0500

    update cmake configs

commit 04a7bc2b8d
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Fri Apr 5 21:00:23 2024 -0500

    edit build script

commit 9fc6b4e973
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Fri Apr 5 18:10:09 2024 -0500

    fix build directory issue

commit a19afaaab0
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Fri Apr 5 18:06:37 2024 -0500

    update .gitignore

commit 426d34a0aa
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Fri Apr 5 17:58:19 2024 -0500

    unexclude toolchain dir

commit 9ce7d9043c
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Fri Apr 5 17:55:02 2024 -0500

    updated cmake workflows

commit db5c10c331
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Fri Apr 5 16:58:00 2024 -0500

    temporarily remove macos build for testing purposes

commit f7da00ff89
Merge: 145f97cf 661e0939
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Fri Apr 5 16:51:39 2024 -0500

    Merge branch 'MSVCCompilerFlags' of https://github.com/jadebenn/DarkflameServer into MSVCCompilerFlags

commit 145f97cfdc
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Fri Apr 5 16:50:39 2024 -0500

    build reorganization and experimental clang support

commit 661e0939b7
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Wed Apr 3 22:13:11 2024 -0500

    fix typo in windows preset

commit 018e5707d7
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Wed Apr 3 20:30:33 2024 -0500

    try using compiler flags for mac instead

commit 81e5f059d5
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Wed Apr 3 20:20:31 2024 -0500

    macos refuses to work :(

commit a3d70197f2
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Wed Apr 3 20:13:37 2024 -0500

    try adding build types back to mac

commit 005d439a4a
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Wed Apr 3 19:58:44 2024 -0500

    edit macos presets

commit bba825f0c8
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Wed Apr 3 19:48:20 2024 -0500

    update CMake presets

commit 199c8224a5
Merge: 1116ba83 c1c5db65
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Wed Apr 3 19:00:39 2024 -0500

    Merge remote-tracking branch 'upstream/main' into MSVCCompilerFlags

commit 1116ba8306
Merge: 9316bd6e c7b3d9e8
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sun Feb 11 21:03:02 2024 -0600

    Merge branch 'DarkflameUniverse:main' into MSVCCompilerFlags

commit 9316bd6eeb
Merge: 62fb8ad0 29666a1f
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Feb 10 21:02:52 2024 -0600

    Merge branch 'DarkflameUniverse:main' into MSVCCompilerFlags

commit 62fb8ad071
Merge: d5089b72 24f94edf
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Thu Feb 8 21:41:50 2024 -0600

    Merge branch 'DarkflameUniverse:main' into MSVCCompilerFlags

commit d5089b72cc
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Sun Feb 4 16:26:38 2024 -0600

    add Linux debug preset

commit 7c9f56ff76
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Sat Feb 3 16:02:53 2024 -0600

    move out g++ O2 flag

commit 6cc99fae42
Merge: 96276391 050184c5
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Sat Feb 3 02:41:43 2024 -0600

    Merge branch 'DarkflameUniverse:main' into MSVCCompilerFlags

commit 962763916d
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 22:00:49 2024 -0600

    export the compile commands so I can see if they're having any effect

commit 4b7d1d6593
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 21:49:24 2024 -0600

    trying 'init' flags instead

commit 3fa80063e9
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 21:13:47 2024 -0600

    ONE MORE TIME

commit ae2115c68d
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 20:52:33 2024 -0600

    final(?) try for now

commit 119937f5d9
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 20:34:44 2024 -0600

    ditto

commit ab39754597
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 20:34:41 2024 -0600

    testing if these even have any effect

commit e7058be3dc
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 20:28:05 2024 -0600

    third test

commit 10d7776fb2
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 19:33:59 2024 -0600

    trying more variations on the flags

commit 70f3756098
Author: jadebenn <jonahbenn@yahoo.com>
Date:   Tue Jan 30 18:49:46 2024 -0600

    testing

commit 9b7c593ae9
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Tue Jan 30 08:49:53 2024 -0600

    Update CMakePresets.json

commit 8a34544d0e
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Tue Jan 30 08:44:29 2024 -0600

    test moving flags to json

commit b682f13fa9
Merge: 2239507d d78b5087
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Mon Jan 29 22:49:29 2024 -0600

    Merge branch 'DarkflameUniverse:main' into MSVCCompilerFlags

commit 2239507d3c
Author: jadebenn <jadebenn@users.noreply.github.com>
Date:   Mon Jan 29 06:14:47 2024 -0600

    Add MSVC optimization flags
2024-11-17 12:33:15 -06:00
163 changed files with 45694 additions and 120630 deletions

View File

@@ -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

View File

@@ -1,4 +1,4 @@
name: Build and Update Docker
name: CI
on:
push:

View File

@@ -1,4 +1,4 @@
name: Build And Test
name: CI
on:
push:
@@ -14,13 +14,6 @@ jobs:
strategy:
matrix:
os: [ windows-2022, ubuntu-22.04, macos-13 ]
include:
- os: windows-2022
configureType: windows-msvc
- os: ubuntu-22.04
configureType: linux-gnu
- os: macos-13
configureType: macos
steps:
- uses: actions/checkout@v4
@@ -40,13 +33,19 @@ jobs:
- name: cmake
uses: lukka/run-cmake@v10
with:
configurePreset: "${{matrix.configureType}}"
buildPreset: "ci-${{matrix.os}}"
testPreset: "ci-${{matrix.os}}"
workflowPreset: "ci-${{matrix.os}}"
- name: artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{matrix.os}}
path: |
build/*
build/*/*Server*
build/*/*.ini
build/*/*.so
build/*/*.dll
build/*/vanity/
build/*/navmeshes/
build/*/migrations/
build/*/*.dcf
!build/*/*.pdb
!build/*/d*/

3
.gitignore vendored
View File

@@ -95,7 +95,6 @@ ipch/
# Exceptions:
CMakeSettings.json
CMakeUserPresets.json
*.vcxproj
*.filters
*.cmake
@@ -113,8 +112,6 @@ CMakeFiles/TargetDirectories.txt
*.sln
*.recipe
CMakeUserPresets.json
# clangd
.cache
thirdparty/zlib-1.2.11/

View File

@@ -19,14 +19,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debuggi
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")
if (${CMAKE_BUILD_TYPE} MATCHES "") # CI likes to set CMAKE_BUILD_TYPE to an empty string
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
endif()
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)
@@ -74,17 +66,16 @@ set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE)
# Disabled no-register
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
if(UNIX)
add_link_options("-Wl,-rpath,$ORIGIN/")
add_compile_options("-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")
add_compile_options("-static-libgcc" "-lstdc++fs")
endif()
if(${DYNAMIC} AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_link_options("-export-dynamic")
add_compile_options("-rdynamic")
endif()
if(${GGDB})
@@ -98,11 +89,10 @@ elseif(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
# Set the output directories
# ./build/<platform + architecture (x64, x86, aarch64)>/<compiler>/<build_mode>/
set(CMAKE_BINARY_DIR ${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_CXX_COMPILER_ID}/${CMAKE_BUILD_TYPE})
# Our output 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
# TODO make this not have to override the build type directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
@@ -117,15 +107,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
@@ -134,11 +115,18 @@ make_directory(${CMAKE_BINARY_DIR}/resServer)
# Create a /logs directory
make_directory(${CMAKE_BINARY_DIR}/logs)
# Get DLU config directory
if(DEFINED ENV{DLU_CONFIG_DIR})
set(DLU_CONFIG_DIR $ENV{DLU_CONFIG_DIR})
else()
set(DLU_CONFIG_DIR ${PROJECT_BINARY_DIR})
endif()
message(STATUS "Variable: DLU_CONFIG_DIR = ${DLU_CONFIG_DIR}")
# Copy resource files on first build
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")
@@ -207,15 +195,15 @@ endforeach()
message(STATUS "Resource file integrity check complete")
# if navmeshes directory does not exist, create it
if(NOT EXISTS ${CMAKE_BINARY_DIR}/navmeshes)
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/navmeshes)
if(NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/navmeshes)
endif()
# Copy navmesh data on first build and extract it
configure_file(${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${CMAKE_BINARY_DIR}/navmeshes.zip COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${PROJECT_BINARY_DIR}/navmeshes.zip COPYONLY)
file(ARCHIVE_EXTRACT INPUT ${CMAKE_BINARY_DIR}/navmeshes.zip DESTINATION ${CMAKE_BINARY_DIR}/navmeshes)
file(REMOVE ${CMAKE_BINARY_DIR}/navmeshes.zip)
file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip DESTINATION ${PROJECT_BINARY_DIR}/navmeshes)
file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip)
# Copy vanity files on first build
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "root.xml" "dev-tribute.xml" "atm.xml" "demo.xml")
@@ -225,20 +213,20 @@ foreach(file ${VANITY_FILES})
endforeach()
# Move our migrations for MasterServer to run
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/migrations/dlu/)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/dlu/)
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql)
foreach(file ${SQL_FILES})
get_filename_component(file ${file} NAME)
configure_file(${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${CMAKE_BINARY_DIR}/migrations/dlu/${file})
configure_file(${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/dlu/${file})
endforeach()
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/migrations/cdserver/)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/cdserver/)
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/cdserver/*.sql)
foreach(file ${SQL_FILES})
get_filename_component(file ${file} NAME)
configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${CMAKE_BINARY_DIR}/migrations/cdserver/${file})
configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file})
endforeach()
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
@@ -324,7 +312,7 @@ add_subdirectory(dPhysics)
add_subdirectory(dServer)
# Create a list of common libraries shared between all binaries
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "MariaDB::ConnCpp" "magic_enum")
# Add platform specific common libraries
if(UNIX)

View File

@@ -11,37 +11,75 @@
"displayName": "Default configure step",
"description": "Use 'build' dir and Unix makefiles",
"binaryDir": "${sourceDir}/build",
"generator": "Unix Makefiles",
"hidden": true
"environment": {
"DLU_CONFIG_DIR": "${sourceDir}/build"
},
"generator": "Unix Makefiles"
},
{
"name": "debug-config",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "relwithdebinfo-config",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "release-config",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "clang-config",
"hidden": true,
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-clang.cmake"
},
{
"name": "gnu-config",
"hidden": true,
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-gnu.cmake"
},
{
"name": "windows-msvc",
"inherits": "default",
"displayName": "[Multi] Windows (MSVC)",
"description": "Set architecture to 64-bit (b/c RakNet)",
"generator": "Visual Studio 17 2022",
"binaryDir": "${sourceDir}/build/msvc",
"architecture": {
"value": "x64"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "windows-default",
"inherits": "default",
"displayName": "Windows Default Configure Settings",
"inherits": "windows-msvc",
"displayName": "Windows only Configure Settings",
"description": "Sets build and install directories",
"generator": "Visual Studio 17 2022",
"generator": "Ninja",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"hidden": true
"architecture": {
"value": "x64"
}
},
{
"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",
"name": "linux-config",
"inherits": "default",
"hidden": true,
"condition": {
@@ -51,74 +89,553 @@
}
},
{
"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-clang-debug",
"inherits": [
"linux-config",
"clang-config",
"debug-config"
],
"displayName": "EXPERIMENTAL - [Debug] Linux (Clang)",
"description": "Create a debug build using the Clang toolchain for Linux",
"binaryDir": "${sourceDir}/build/clang-debug"
},
{
"name": "linux-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": "linux-clang-relwithdebinfo",
"inherits": [
"linux-config",
"clang-config",
"relwithdebinfo-config"
],
"displayName": "EXPERIMENTAL - [RelWithDebInfo] Linux (Clang)",
"description": "Create a release build with debug info using the Clang toolchain for Linux",
"binaryDir": "${sourceDir}/build/clang-relwithdebinfo"
},
{
"name": "linux-clang-release",
"inherits": [
"linux-config",
"clang-config",
"release-config"
],
"displayName": "EXPERIMENTAL - [Release] Linux (Clang)",
"description": "Create a release build using the Clang toolchain for Linux",
"binaryDir": "${sourceDir}/build/clang-release"
},
{
"name": "linux-gnu-debug",
"inherits": [
"linux-config",
"gnu-config",
"debug-config"
],
"displayName": "[Debug] Linux (GNU)",
"description": "Create a debug build using the GNU toolchain for Linux",
"binaryDir": "${sourceDir}/build/gnu-debug"
},
{
"name": "linux-gnu-relwithdebinfo",
"inherits": [
"linux-config",
"gnu-config",
"relwithdebinfo-config"
],
"displayName": "[RelWithDebInfo] Linux (GNU)",
"description": "Create a release build with debug info using the GNU toolchain for Linux",
"binaryDir": "${sourceDir}/build/gnu-relwithdebinfo"
},
{
"name": "linux-gnu-release",
"inherits": [
"linux-config",
"gnu-config",
"release-config"
],
"displayName": "[Release] Linux (GNU)",
"description": "Create a release build using the GNU toolchain for Linux",
"binaryDir": "${sourceDir}/build/gnu-release"
},
{
"name": "macos",
"inherits": "default",
"displayName": "MacOS",
"displayName": "[Multi] MacOS",
"description": "Create a build for MacOS",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
}
},
"binaryDir": "${sourceDir}/build/macos"
}
],
"buildPresets": [
{ "name": "ci-ubuntu-22.04", "configurePreset": "linux-gnu" },
{ "name": "ci-macos-13", "configurePreset": "macos" },
{ "name": "ci-windows-2022", "configurePreset": "windows-msvc" }
{
"name": "default",
"configurePreset": "default",
"displayName": "Default Build",
"description": "Default Build",
"jobs": 2
},
{
"name": "windows-msvc-debug",
"inherits": "default",
"configurePreset": "windows-msvc",
"displayName": "[Debug] Windows (MSVC)",
"description": "This preset is used to build in debug mode using the MSVC toolchain on Windows",
"configuration": "Debug"
},
{
"name": "windows-msvc-relwithdebinfo",
"inherits": "default",
"configurePreset": "windows-msvc",
"displayName": "[RelWithDebInfo] Windows (MSVC)",
"description": "This preset is used to build in debug mode using the MSVC toolchain on Windows",
"configuration": "RelWithDebInfo"
},
{
"name": "windows-msvc-release",
"inherits": "default",
"configurePreset": "windows-msvc",
"displayName": "[Release] Windows (MSVC)",
"description": "This preset is used to build in release mode using the MSVC toolchain on Windows",
"configuration": "Release"
},
{
"name": "linux-clang-debug",
"inherits": "default",
"configurePreset": "linux-clang-debug",
"displayName": "EXPERIMENTAL - [Debug] Linux (Clang)",
"description": "This preset is used to build in debug mode using the Clang toolchain on Linux",
"configuration": "Debug"
},
{
"name": "linux-clang-relwithdebinfo",
"inherits": "default",
"configurePreset": "linux-clang-relwithdebinfo",
"displayName": "EXPERIMENTAL - [RelWithDebInfo] Linux (Clang)",
"description": "This preset is used to build in release mode with debug info using the Clang toolchain on Linux",
"configuration": "RelWithDebInfo"
},
{
"name": "linux-clang-release",
"inherits": "default",
"configurePreset": "linux-clang-release",
"displayName": "EXPERIMENTAL - [Release] Linux (Clang)",
"description": "This preset is used to build in release mode using the Clang toolchain on Linux",
"configuration": "Release"
},
{
"name": "linux-gnu-debug",
"inherits": "default",
"configurePreset": "linux-gnu-debug",
"displayName": "[Debug] Linux (GNU)",
"description": "This preset is used to build in debug mode using the GNU toolchain on Linux",
"configuration": "Debug"
},
{
"name": "linux-gnu-relwithdebinfo",
"inherits": "default",
"configurePreset": "linux-gnu-relwithdebinfo",
"displayName": "[RelWithDebInfo] Linux (GNU)",
"description": "This preset is used to build in release mode with debug info using the GNU toolchain on Linux",
"configuration": "RelWithDebInfo"
},
{
"name": "linux-gnu-release",
"inherits": "default",
"configurePreset": "linux-gnu-release",
"displayName": "[Release] Linux (GNU)",
"description": "This preset is used to build in release mode using the GNU toolchain on Linux",
"configuration": "Release"
},
{
"name": "macos-debug",
"inherits": "default",
"configurePreset": "macos",
"displayName": "[Debug] MacOS",
"description": "This preset is used to build in debug mode on MacOS",
"configuration": "Debug"
},
{
"name": "macos-relwithdebinfo",
"inherits": "default",
"configurePreset": "macos",
"displayName": "[RelWithDebInfo] MacOS",
"description": "This preset is used to build in release mode with debug info on MacOS",
"configuration": "RelWithDebInfo"
},
{
"name": "macos-release",
"inherits": "default",
"configurePreset": "macos",
"displayName": "[Release] MacOS",
"description": "This preset is used to build in release mode on MacOS",
"configuration": "Release"
}
],
"testPresets": [
{
"name": "default",
"hidden": true,
"execution": {
"jobs": 2
},
"output": {
"outputOnFailure": true
}
},
{
"name": "ci-ubuntu-22.04",
"configurePreset": "linux-gnu",
"displayName": "CI Tests on Linux",
"inherits": "default"
"name": "default",
"configurePreset": "default",
"execution": {
"jobs": 2
},
"output": {
"outputOnFailure": true
}
},
{
"name": "ci-macos-13",
"configurePreset": "macos",
"displayName": "CI Tests on MacOS",
"inherits": "default"
},
{
"name": "ci-windows-2022",
"name": "windows-msvc-test",
"inherits": "default",
"configurePreset": "windows-msvc",
"displayName": "CI Tests on windows",
"inherits": "default",
"configuration": "RelWithDebInfo",
"hidden": true,
"filter": {
"exclude": {
"name": "((example)|(minigzip))+"
}
}
},
{
"name": "windows-msvc-debug",
"inherits": "windows-msvc-test",
"configurePreset": "windows-msvc",
"displayName": "[Debug] Windows (MSVC)",
"description": "Runs all tests on a Windows configuration",
"configuration": "Debug"
},
{
"name": "windows-msvc-relwithdebinfo",
"inherits": "windows-msvc-test",
"configurePreset": "windows-msvc",
"displayName": "[RelWithDebInfo] Windows (MSVC)",
"description": "Runs all tests on a Windows configuration",
"configuration": "RelWithDebInfo"
},
{
"name": "windows-msvc-release",
"inherits": "windows-msvc-test",
"configurePreset": "windows-msvc",
"displayName": "[Release] Windows (MSVC)",
"description": "Runs all tests on a Windows configuration",
"configuration": "Release"
},
{
"name": "linux-clang-debug",
"inherits": "default",
"configurePreset": "linux-clang-debug",
"displayName": "EXPERIMENTAL - [Debug] Linux (Clang)",
"description": "Runs all tests on a Linux Clang configuration",
"configuration": "Release"
},
{
"name": "linux-clang-relwithdebinfo",
"inherits": "default",
"configurePreset": "linux-clang-relwithdebinfo",
"displayName": "EXPERIMENTAL - [RelWithDebInfo] Linux (Clang)",
"description": "Runs all tests on a Linux Clang configuration",
"configuration": "RelWithDebInfo"
},
{
"name": "linux-clang-release",
"inherits": "default",
"configurePreset": "linux-clang-release",
"displayName": "EXPERIMENTAL - [Release] Linux (Clang)",
"description": "Runs all tests on a Linux Clang configuration",
"configuration": "Release"
},
{
"name": "linux-gnu-debug",
"inherits": "default",
"configurePreset": "linux-gnu-debug",
"displayName": "[Debug] Linux (GNU)",
"description": "Runs all tests on a Linux GNU configuration",
"configuration": "Release"
},
{
"name": "linux-gnu-relwithdebinfo",
"inherits": "default",
"configurePreset": "linux-gnu-relwithdebinfo",
"displayName": "[RelWithDebInfo] Linux (GNU)",
"description": "Runs all tests on a Linux GNU configuration",
"configuration": "RelWithDebInfo"
},
{
"name": "linux-gnu-release",
"inherits": "default",
"configurePreset": "linux-gnu-release",
"displayName": "[Release] Linux (GNU)",
"description": "Runs all tests on a Linux GNU configuration",
"configuration": "Release"
},
{
"name": "macos-debug",
"inherits": "default",
"configurePreset": "macos",
"displayName": "[Debug] MacOS",
"description": "Runs all tests on a MacOS configuration",
"configuration": "Debug"
},
{
"name": "macos-relwithdebinfo",
"inherits": "default",
"configurePreset": "macos",
"displayName": "[RelWithDebInfo] MacOS",
"description": "Runs all tests on a MacOS configuration",
"configuration": "RelWithDebInfo"
},
{
"name": "macos-release",
"inherits": "default",
"configurePreset": "macos",
"displayName": "[Release] MacOS",
"description": "Runs all tests on a MacOS configuration",
"configuration": "Release"
}
],
"workflowPresets": [
{
"name": "default",
"steps": [
{
"type": "configure",
"name": "default"
},
{
"type": "build",
"name": "default"
},
{
"type": "test",
"name": "default"
}
]
},
{
"name": "windows-msvc-debug",
"displayName": "[Debug] Windows (MSVC)",
"description": "MSVC debug workflow preset for Windows",
"steps": [
{
"type": "configure",
"name": "windows-msvc"
},
{
"type": "build",
"name": "windows-msvc-debug"
},
{
"type": "test",
"name": "windows-msvc-debug"
}
]
},
{
"name": "windows-msvc-relwithdebinfo",
"displayName": "[RelWithDebInfo] Windows (MSVC)",
"description": "MSVC release with debug info workflow preset for Windows",
"steps": [
{
"type": "configure",
"name": "windows-msvc"
},
{
"type": "build",
"name": "windows-msvc-relwithdebinfo"
},
{
"type": "test",
"name": "windows-msvc-relwithdebinfo"
}
]
},
{
"name": "ci-windows-2022",
"displayName": "[Release] Windows (MSVC)",
"description": "CI workflow preset for Windows",
"steps": [
{
"type": "configure",
"name": "windows-msvc"
},
{
"type": "build",
"name": "windows-msvc-release"
},
{
"type": "test",
"name": "windows-msvc-release"
}
]
},
{
"name": "linux-gnu-debug",
"displayName": "[Debug] Linux (GNU)",
"description": "GNU debug workflow preset for Linux",
"steps": [
{
"type": "configure",
"name": "linux-gnu-debug"
},
{
"type": "build",
"name": "linux-gnu-debug"
},
{
"type": "test",
"name": "linux-gnu-debug"
}
]
},
{
"name": "linux-gnu-relwithdebinfo",
"displayName": "[RelWithDebInfo] Linux (GNU)",
"description": "GNU release with debug info workflow preset for Linux",
"steps": [
{
"type": "configure",
"name": "linux-gnu-relwithdebinfo"
},
{
"type": "build",
"name": "linux-gnu-relwithdebinfo"
},
{
"type": "test",
"name": "linux-gnu-relwithdebinfo"
}
]
},
{
"name": "ci-ubuntu-22.04",
"displayName": "[Release] Linux (GNU)",
"description": "CI workflow preset for Ubuntu",
"steps": [
{
"type": "configure",
"name": "linux-gnu-release"
},
{
"type": "build",
"name": "linux-gnu-release"
},
{
"type": "test",
"name": "linux-gnu-release"
}
]
},
{
"name": "linux-clang-debug",
"displayName": "EXPERIMENTAL - [Debug] Linux (Clang)",
"description": "Clang debug workflow preset for Linux",
"steps": [
{
"type": "configure",
"name": "linux-clang-debug"
},
{
"type": "build",
"name": "linux-clang-debug"
},
{
"type": "test",
"name": "linux-clang-debug"
}
]
},
{
"name": "linux-clang-relwithdebinfo",
"displayName": "EXPERIMENTAL - [RelWithDebInfo] Linux (Clang)",
"description": "Clang release with debug info workflow preset for Linux",
"steps": [
{
"type": "configure",
"name": "linux-clang-relwithdebinfo"
},
{
"type": "build",
"name": "linux-clang-relwithdebinfo"
},
{
"type": "test",
"name": "linux-clang-relwithdebinfo"
}
]
},
{
"name": "linux-clang-release",
"displayName": "EXPERIMENTAL - [Release] Linux (Clang)",
"description": "Clang release workflow preset for Linux",
"steps": [
{
"type": "configure",
"name": "linux-clang-release"
},
{
"type": "build",
"name": "linux-clang-release"
},
{
"type": "test",
"name": "linux-clang-release"
}
]
},
{
"name": "macos-debug",
"displayName": "[Debug] MacOS",
"description": "Release workflow preset for MacOS",
"steps": [
{
"type": "configure",
"name": "macos"
},
{
"type": "build",
"name": "macos-debug"
},
{
"type": "test",
"name": "macos-debug"
}
]
},
{
"name": "macos-relwithdebinfo",
"displayName": "[RelWithDebInfo] MacOS",
"description": "Release with debug info workflow preset for MacOS",
"steps": [
{
"type": "configure",
"name": "macos"
},
{
"type": "build",
"name": "macos-relwithdebinfo"
},
{
"type": "test",
"name": "macos-relwithdebinfo"
}
]
},
{
"name": "ci-macos-13",
"displayName": "[Release] MacOS",
"description": "CI workflow preset for MacOS",
"steps": [
{
"type": "configure",
"name": "macos"
},
{
"type": "build",
"name": "macos-release"
},
{
"type": "test",
"name": "macos-release"
}
]
}
]
}

View File

@@ -23,23 +23,23 @@ RUN --mount=type=cache,id=build-apt-cache,target=/var/cache/apt \
rm -rf /var/lib/apt/lists/*
# Grab libraries and load them
COPY --from=build /app/build/Linux-x86_64/GNU/Release/mariadbcpp/libmariadbcpp.so /usr/local/lib/
COPY --from=build /app/build/mariadbcpp/libmariadbcpp.so /usr/local/lib/
RUN ldconfig
# Server bins
COPY --from=build /app/build/Linux-x86_64/GNU/Release/*Server /app/
COPY --from=build /app/build/*Server /app/
# Necessary suplimentary files
COPY --from=build /app/build/Linux-x86_64/GNU/Release/*.ini /app/configs/
COPY --from=build /app/build/Linux-x86_64/GNU/Release/vanity/*.* /app/vanity/
COPY --from=build /app/build/Linux-x86_64/GNU/Release/navmeshes /app/navmeshes
COPY --from=build /app/build/Linux-x86_64/GNU/Release/migrations /app/migrations
COPY --from=build /app/build/Linux-x86_64/GNU/Release/*.dcf /app/
COPY --from=build /app/build/*.ini /app/configs/
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/
# 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/Linux-x86_64/GNU/Release/*.ini /app/default-configs/
COPY --from=build /app/build/Linux-x86_64/GNU/Release/vanity/*.* /app/default-vanity/
COPY --from=build /app/build/*.ini /app/default-configs/
COPY --from=build /app/build/vanity/*.* /app/default-vanity/
# needed as the container runs with the root user
# and therefore sudo doesn't exist

View File

@@ -2,8 +2,8 @@
# On Windows ClangCL can't compile the connector from source but can link to an msvc compiled one,
# so prefer the prebuilt binaries unless MARIADB_BUILD_SOURCE is specified
if(WIN32 AND NOT MARIADB_BUILD_SOURCE)
set(MARIADB_MSI_DIR "${CMAKE_BINARY_DIR}/msi")
set(MARIADB_CONNECTOR_DIR "${CMAKE_BINARY_DIR}/mariadbcpp")
set(MARIADB_MSI_DIR "${PROJECT_BINARY_DIR}/msi")
set(MARIADB_CONNECTOR_DIR "${PROJECT_BINARY_DIR}/mariadbcpp")
set(MARIADB_C_CONNECTOR_DIR "${MARIADB_CONNECTOR_DIR}/MariaDB/MariaDB Connector C 64-bit")
set(MARIADB_CPP_CONNECTOR_DIR "${MARIADB_CONNECTOR_DIR}/MariaDB/MariaDB C++ Connector 64-bit")
@@ -59,7 +59,7 @@ if(WIN32 AND NOT MARIADB_BUILD_SOURCE)
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${MARIADBCPP_SHARED_LIBRARY_LOCATION}"
"${MARIADBC_SHARED_LIBRARY_LOCATION}"
"${CMAKE_BINARY_DIR}")
"${PROJECT_BINARY_DIR}")
# MariaDB uses plugins that the database needs to load, the prebuilt binaries by default will try to find the libraries in system directories,
# so set this define and the servers will set the MARIADB_PLUGIN_DIR environment variable to the appropriate directory.
@@ -86,13 +86,13 @@ else() # Build from source
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0)
endif()
set(MARIADBCPP_INSTALL_DIR ${CMAKE_BINARY_DIR}/prefix)
set(MARIADBCPP_LIBRARY_DIR ${CMAKE_BINARY_DIR}/mariadbcpp)
set(MARIADBCPP_INSTALL_DIR ${PROJECT_BINARY_DIR}/prefix)
set(MARIADBCPP_LIBRARY_DIR ${PROJECT_BINARY_DIR}/mariadbcpp)
set(MARIADBCPP_PLUGIN_DIR ${MARIADBCPP_LIBRARY_DIR}/plugin)
set(MARIADBCPP_SOURCE_DIR ${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp)
set(MARIADB_INCLUDE_DIR "${MARIADBCPP_SOURCE_DIR}/include")
ExternalProject_Add(mariadb_connector_cpp
PREFIX "${CMAKE_BINARY_DIR}/thirdparty/mariadb-connector-cpp"
PREFIX "${PROJECT_BINARY_DIR}/thirdparty/mariadb-connector-cpp"
SOURCE_DIR ${MARIADBCPP_SOURCE_DIR}
INSTALL_DIR ${MARIADBCPP_INSTALL_DIR}
CMAKE_ARGS -Wno-dev
@@ -127,20 +127,20 @@ else() # Build from source
endif()
# Create mariadb connector library object
add_library(mariadb_cpp_connector SHARED IMPORTED GLOBAL)
add_dependencies(mariadb_cpp_connector mariadb_connector_cpp)
set_target_properties(mariadb_cpp_connector PROPERTIES
add_library(MariaDB::ConnCpp SHARED IMPORTED GLOBAL)
add_dependencies(MariaDB::ConnCpp mariadb_connector_cpp)
set_target_properties(MariaDB::ConnCpp PROPERTIES
IMPORTED_LOCATION "${MARIADBCPP_SHARED_LIBRARY_LOCATION}")
if(WIN32)
set_target_properties(mariadb_cpp_connector PROPERTIES
set_target_properties(MariaDB::ConnCpp PROPERTIES
IMPORTED_IMPLIB "${MARIADB_IMPLIB_LOCATION}")
elseif(APPLE)
set_target_properties(mariadb_cpp_connector PROPERTIES
set_target_properties(MariaDB::ConnCpp PROPERTIES
IMPORTED_SONAME "libmariadbcpp")
endif()
# Add directories to include lists
target_include_directories(mariadb_cpp_connector SYSTEM INTERFACE ${MARIADB_INCLUDE_DIR})
target_include_directories(MariaDB::ConnCpp SYSTEM INTERFACE ${MARIADB_INCLUDE_DIR})
set(mariadb_found TRUE)
set(MariaDB_FOUND TRUE)

View File

@@ -6,9 +6,9 @@ find_program(CLANG_CXX_COMPILER clang++-16 | clang++ REQUIRED)
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 compilers to clang
set(CMAKE_C_COMPILER ${CLANG_C_COMPILER})
set(CMAKE_CXX_COMPILER ${CLANG_CXX_COMPILER})
# Set linker to lld
add_link_options("-fuse-ld=lld")

View File

@@ -4,8 +4,8 @@ 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}")
message(DEBUG "GNU_CXX_COMPILER = ${GNU_C_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")
# Set compilers to clang
set(CMAKE_C_COMPILER ${GNU_C_COMPILER})
set(CMAKE_CXX_COMPILER ${GNU_CXX_COMPILER})

View File

@@ -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"
@@ -60,7 +60,7 @@ int main(int argc, char** argv) {
try {
Database::Connect();
} catch (std::exception& ex) {
} catch (sql::SQLException& ex) {
LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("AuthServer");
delete Game::server;
@@ -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);
}
}

View File

@@ -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:

View File

@@ -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));

View File

@@ -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"
@@ -81,7 +81,7 @@ int main(int argc, char** argv) {
//Connect to the MySQL Database
try {
Database::Connect();
} catch (std::exception& ex) {
} catch (sql::SQLException& ex) {
LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("ChatServer");
delete Game::server;
@@ -108,7 +108,7 @@ int main(int argc, char** argv) {
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
Game::randomEngine = std::mt19937(time(0));
Game::playerContainer.Initialize();
@@ -190,154 +190,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:

View File

@@ -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 =
@@ -148,13 +148,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 +362,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);

View File

@@ -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));
}

View File

@@ -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.

View File

@@ -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:

View File

@@ -123,7 +123,7 @@ uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
Database::Get()->UpdateUgcModelData(model.id, outputStringStream);
LOG("Updated model %i to sd0", model.id);
updatedModels++;
} catch (std::exception& exception) {
} catch (sql::SQLException exception) {
LOG("Failed to update model %i. This model should be inspected manually to see why."
"The database error is %s", model.id, exception.what());
}

View File

@@ -45,15 +45,11 @@ if (UNIX)
elseif (WIN32)
include(FetchContent)
set(WITH_GTEST OFF CACHE BOOL "" FORCE)
set(ZLIB_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
set(ZLIB_COMPAT ON CACHE BOOL "Enable ZLIB compatibility mode" 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.
@@ -64,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(

View File

@@ -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>;

View File

@@ -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__

View File

@@ -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__

View File

@@ -9,7 +9,6 @@ namespace ZCompression {
}
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst) {
z_stream zInfo = { 0 };
zInfo.total_in = zInfo.avail_in = nLenSrc;
zInfo.total_out = zInfo.avail_out = nLenDst;

View File

@@ -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) {

View File

@@ -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
};
}

View File

@@ -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,
};
}

View File

@@ -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

View File

@@ -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
};
}

View File

@@ -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
};
}

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -8,8 +8,6 @@
#define DARKFLAME_PLATFORM_IOS
#elif TARGET_OS_MAC
#define DARKFLAME_PLATFORM_MACOS
#pragma clang diagnostic push // prevent pragma messages being counted as a warning
#pragma clang diagnostic ignored "-W#pragma-messages"
#else
#error unknown Apple operating system
#endif

View 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__

View File

@@ -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__

View 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__

View 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__

File diff suppressed because it is too large Load Diff

View 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__

View File

@@ -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

View 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__

View 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__

View File

@@ -2,12 +2,6 @@ add_subdirectory(CDClientDatabase)
add_subdirectory(GameDatabase)
add_library(dDatabase STATIC "MigrationRunner.cpp")
add_custom_target(conncpp_dylib
${CMAKE_COMMAND} -E copy $<TARGET_FILE:mariadb_cpp_connector> ${CMAKE_BINARY_DIR})
add_dependencies(dDatabase conncpp_dylib)
target_include_directories(dDatabase PUBLIC ".")
target_link_libraries(dDatabase
PUBLIC dDatabaseCDClient dDatabaseGame)

View File

@@ -8,20 +8,14 @@ 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"
)
target_link_libraries(dDatabaseGame
PUBLIC mariadb_cpp_connector
PUBLIC MariaDB::ConnCpp
INTERFACE dCommon)
# Glob together all headers that need to be precompiled

View File

@@ -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;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <conncpp.hpp>
#include "GameDatabase.h"
@@ -8,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);
};

View File

@@ -24,7 +24,6 @@
#include "IIgnoreList.h"
#include "IAccountsRewardCodes.h"
#include "IBehaviors.h"
#include "IUgcModularBuild.h"
namespace sql {
class Statement;
@@ -43,7 +42,7 @@ class GameDatabase :
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 IUgcModularBuild {
public IBehaviors {
public:
virtual ~GameDatabase() = default;
// TODO: These should be made private.

View File

@@ -3,45 +3,12 @@
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
class ILeaderboard {
public:
struct Entry {
uint32_t charId{};
uint32_t lastPlayedTimestamp{};
float primaryScore{};
float secondaryScore{};
uint32_t tertiaryScore{};
uint32_t numWins{};
uint32_t numTimesPlayed{};
uint32_t ranking{};
std::string name{};
};
struct Score {
auto operator<=>(const Score& rhs) const = default;
float primaryScore{ 0.0f };
float secondaryScore{ 0.0f };
float tertiaryScore{ 0.0f };
};
// Get the donation total for the given activity id.
virtual std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) = 0;
virtual std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) = 0;
virtual std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) = 0;
virtual std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) = 0;
virtual std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) = 0;
virtual std::optional<Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) = 0;
virtual void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
virtual void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
virtual void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) = 0;
virtual void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) = 0;
};
#endif //!__ILEADERBOARD__H__

View File

@@ -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;

View File

@@ -1,14 +0,0 @@
#ifndef IUGCMODULARBUILD_H
#define IUGCMODULARBUILD_H
#include <cstdint>
#include <optional>
#include <string>
class IUgcModularBuild {
public:
virtual void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) = 0;
virtual void DeleteUgcBuild(const LWOOBJID bigId) = 0;
};
#endif //!IUGCMODULARBUILD_H

View File

@@ -7,7 +7,6 @@
#include "GameDatabase.h"
typedef std::unique_ptr<sql::PreparedStatement>& UniquePreppedStmtRef;
typedef std::unique_ptr<sql::ResultSet> UniqueResultSet;
// Purposefully no definition for this to provide linker errors in the case someone tries to
// bind a parameter to a type that isn't defined.
@@ -113,18 +112,6 @@ public:
std::string GetBehavior(const int32_t behaviorId) override;
void RemoveBehavior(const int32_t characterId) override;
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override;
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override;
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
void DeleteUgcBuild(const LWOOBJID bigId) override;
private:
// Generic query functions that can be used for any query.

View File

@@ -20,7 +20,6 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
"PropertyContents.cpp"
"Servers.cpp"
"Ugc.cpp"
"UgcModularBuild.cpp"
PARENT_SCOPE
)

View File

@@ -1,9 +1,5 @@
#include "MySQLDatabase.h"
#include "Game.h"
#include "Logger.h"
#include "dConfig.h"
std::optional<uint32_t> MySQLDatabase::GetDonationTotal(const uint32_t activityId) {
auto donation_total = ExecuteSelect("SELECT SUM(primaryScore) as donation_total FROM leaderboard WHERE game_id = ?;", activityId);
@@ -13,79 +9,3 @@ std::optional<uint32_t> MySQLDatabase::GetDonationTotal(const uint32_t activityI
return donation_total->getUInt("donation_total");
}
std::vector<ILeaderboard::Entry> ProcessQuery(UniqueResultSet& rows) {
std::vector<ILeaderboard::Entry> entries;
entries.reserve(rows->rowsCount());
while (rows->next()) {
auto& entry = entries.emplace_back();
entry.charId = rows->getUInt("character_id");
entry.lastPlayedTimestamp = rows->getUInt("lp_unix");
entry.primaryScore = rows->getFloat("primaryScore");
entry.secondaryScore = rows->getFloat("secondaryScore");
entry.tertiaryScore = rows->getFloat("tertiaryScore");
entry.numWins = rows->getUInt("numWins");
entry.numTimesPlayed = rows->getUInt("timesPlayed");
entry.name = rows->getString("char_name");
// entry.ranking is never set because its calculated in leaderboard in code.
}
return entries;
}
std::vector<ILeaderboard::Entry> MySQLDatabase::GetDescendingLeaderboard(const uint32_t activityId) {
auto leaderboard = ExecuteSelect("SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore DESC, tertiaryScore DESC, last_played ASC;", activityId);
return ProcessQuery(leaderboard);
}
std::vector<ILeaderboard::Entry> MySQLDatabase::GetAscendingLeaderboard(const uint32_t activityId) {
auto leaderboard = ExecuteSelect("SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore ASC, secondaryscore ASC, tertiaryScore ASC, last_played ASC;", activityId);
return ProcessQuery(leaderboard);
}
std::vector<ILeaderboard::Entry> MySQLDatabase::GetAgsLeaderboard(const uint32_t activityId) {
auto query = Game::config->GetValue("classic_survival_scoring") != "1" ?
"SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore DESC, tertiaryScore DESC, last_played ASC;" :
"SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY secondaryscore DESC, primaryscore DESC, tertiaryScore DESC, last_played ASC;";
auto leaderboard = ExecuteSelect(query, activityId);
return ProcessQuery(leaderboard);
}
std::vector<ILeaderboard::Entry> MySQLDatabase::GetNsLeaderboard(const uint32_t activityId) {
auto leaderboard = ExecuteSelect("SELECT *, UNIX_TIMESTAMP(last_played) as lp_unix, ci.name as char_name FROM leaderboard lb JOIN charinfo ci on ci.id = lb.character_id where game_id = ? ORDER BY primaryscore DESC, secondaryscore ASC, tertiaryScore DESC, last_played ASC;", activityId);
return ProcessQuery(leaderboard);
}
void MySQLDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
ExecuteInsert("INSERT leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, character_id = ?, game_id = ?;",
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
}
void MySQLDatabase::UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;",
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
}
void MySQLDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) {
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
}
std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
auto res = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
if (res->next()) {
toReturn = ILeaderboard::Score{
.primaryScore = res->getFloat("primaryScore"),
.secondaryScore = res->getFloat("secondaryScore"),
.tertiaryScore = res->getFloat("tertiaryScore")
};
}
return toReturn;
}
void MySQLDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t gameId) {
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
}

View File

@@ -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;
}

View File

@@ -1,9 +0,0 @@
#include "MySQLDatabase.h"
void MySQLDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) {
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
}
void MySQLDatabase::DeleteUgcBuild(const LWOOBJID bigId) {
ExecuteDelete("DELETE FROM ugc_modular_build WHERE ugc_id = ?;", bigId);
}

View File

@@ -1,4 +0,0 @@
SET(DDATABSE_DATABSES_TEST_SQL_SOURCES
"TestSQLDatabase.cpp"
PARENT_SCOPE
)

View File

@@ -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) {
}

View File

@@ -1,107 +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 {}; };
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override { return {}; };
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override { return {}; };
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override { return {}; };
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override { return {}; };
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override {};
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override {};
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override { return {}; };
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override {};
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override {};
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override {};
void DeleteUgcBuild(const LWOOBJID bigId) override {};
};
#endif //!TESTSQLDATABASE_H

View File

@@ -34,7 +34,7 @@ Migration LoadMigration(std::string path) {
void MigrationRunner::RunMigrations() {
Database::Get()->CreateMigrationHistoryTable();
std::string finalSQL = "";
sql::SQLString finalSQL = "";
bool runSd0Migrations = false;
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "./migrations/dlu/").string())) {
auto migration = LoadMigration("dlu/" + entry);
@@ -61,12 +61,12 @@ void MigrationRunner::RunMigrations() {
}
if (!finalSQL.empty()) {
auto migration = GeneralUtils::SplitString(finalSQL, ';');
auto migration = GeneralUtils::SplitString(static_cast<std::string>(finalSQL), ';');
for (auto& query : migration) {
try {
if (query.empty()) continue;
Database::Get()->ExecuteCustomQuery(query);
} catch (std::exception& e) {
Database::Get()->ExecuteCustomQuery(query.c_str());
} catch (sql::SQLException& e) {
LOG("Encountered error running migration: %s", e.what());
}
}

View File

@@ -40,8 +40,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 +76,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;
}

View File

@@ -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,10 +459,6 @@ public:
User* GetParentUser() const { return m_ParentUser; }
void _doQuickXMLDataParse() { DoQuickXMLDataParse(); }
void _setXmlData(const std::string& xmlData) { m_XMLData = xmlData; }
private:
void UpdateInfoFromDatabase();
/**

View File

@@ -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:
@@ -83,7 +83,6 @@
#include "ItemComponent.h"
#include "GhostComponent.h"
#include "AchievementVendorComponent.h"
#include "VanityUtilities.h"
// Table includes
#include "CDComponentsRegistryTable.h"
@@ -97,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;
@@ -884,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);
@@ -1272,7 +1269,6 @@ void Entity::Update(const float deltaTime) {
auto timerName = timer.GetName();
m_Timers.erase(m_Timers.begin() + timerPosition);
GetScript()->OnTimerDone(this, timerName);
VanityUtilities::OnTimerDone(this, timerName);
TriggerEvent(eTriggerEventType::TIMER_DONE, this);
} else {
@@ -1336,7 +1332,6 @@ void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxN
if (!other) return;
GetScript()->OnProximityUpdate(this, other, proxName, status);
VanityUtilities::OnProximityUpdate(this, other, proxName, status);
RocketLaunchpadControlComponent* rocketComp = GetComponent<RocketLaunchpadControlComponent>();
if (!rocketComp) return;
@@ -1356,7 +1351,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
SwitchComponent* switchComp = GetComponent<SwitchComponent>();
if (switchComp) {
switchComp->OnUse(other);
switchComp->EntityEnter(other);
}
TriggerEvent(eTriggerEventType::ENTER, other);
@@ -2138,8 +2133,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 {

View File

@@ -11,7 +11,6 @@
#include "NiQuaternion.h"
#include "LDFFormat.h"
#include "eKillType.h"
#include "Observable.h"
namespace Loot {
class Info;
@@ -300,11 +299,6 @@ 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;
protected:
LWOOBJID m_ObjectID;

View File

@@ -1,6 +1,5 @@
#include "LeaderboardManager.h"
#include <ranges>
#include <sstream>
#include <utility>
@@ -73,191 +72,197 @@ void Leaderboard::Serialize(RakNet::BitStream& bitStream) const {
bitStream.Write0();
}
// Takes the resulting query from a leaderboard lookup and converts it to the LDF we need
// to send it to a client.
void QueryToLdf(Leaderboard& leaderboard, const std::vector<ILeaderboard::Entry>& leaderboardEntries) {
using enum Leaderboard::Type;
leaderboard.Clear();
if (leaderboardEntries.empty()) return;
void Leaderboard::QueryToLdf(std::unique_ptr<sql::ResultSet>& rows) {
Clear();
if (rows->rowsCount() == 0) return;
for (const auto& leaderboardEntry : leaderboardEntries) {
this->entries.reserve(rows->rowsCount());
while (rows->next()) {
constexpr int32_t MAX_NUM_DATA_PER_ROW = 9;
auto& entry = leaderboard.PushBackEntry();
this->entries.push_back(std::vector<LDFBaseData*>());
auto& entry = this->entries.back();
entry.reserve(MAX_NUM_DATA_PER_ROW);
entry.push_back(new LDFData<uint64_t>(u"CharacterID", leaderboardEntry.charId));
entry.push_back(new LDFData<uint64_t>(u"LastPlayed", leaderboardEntry.lastPlayedTimestamp));
entry.push_back(new LDFData<int32_t>(u"NumPlayed", leaderboardEntry.numTimesPlayed));
entry.push_back(new LDFData<std::u16string>(u"name", GeneralUtils::ASCIIToUTF16(leaderboardEntry.name)));
entry.push_back(new LDFData<uint64_t>(u"RowNumber", leaderboardEntry.ranking));
switch (leaderboard.GetLeaderboardType()) {
case ShootingGallery:
entry.push_back(new LDFData<int32_t>(u"Score", leaderboardEntry.primaryScore));
entry.push_back(new LDFData<uint64_t>(u"CharacterID", rows->getInt("character_id")));
entry.push_back(new LDFData<uint64_t>(u"LastPlayed", rows->getUInt64("lastPlayed")));
entry.push_back(new LDFData<int32_t>(u"NumPlayed", rows->getInt("timesPlayed")));
entry.push_back(new LDFData<std::u16string>(u"name", GeneralUtils::ASCIIToUTF16(rows->getString("name").c_str())));
entry.push_back(new LDFData<uint64_t>(u"RowNumber", rows->getInt("ranking")));
switch (leaderboardType) {
case Type::ShootingGallery:
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("primaryScore")));
// Score:1
entry.push_back(new LDFData<int32_t>(u"Streak", leaderboardEntry.secondaryScore));
entry.push_back(new LDFData<int32_t>(u"Streak", rows->getInt("secondaryScore")));
// Streak:1
entry.push_back(new LDFData<float>(u"HitPercentage", (leaderboardEntry.tertiaryScore / 100.0f)));
entry.push_back(new LDFData<float>(u"HitPercentage", (rows->getInt("tertiaryScore") / 100.0f)));
// HitPercentage:3 between 0 and 1
break;
case Racing:
entry.push_back(new LDFData<float>(u"BestTime", leaderboardEntry.primaryScore));
case Type::Racing:
entry.push_back(new LDFData<float>(u"BestTime", rows->getDouble("primaryScore")));
// BestLapTime:3
entry.push_back(new LDFData<float>(u"BestLapTime", leaderboardEntry.secondaryScore));
entry.push_back(new LDFData<float>(u"BestLapTime", rows->getDouble("secondaryScore")));
// BestTime:3
entry.push_back(new LDFData<int32_t>(u"License", 1));
// License:1 - 1 if player has completed mission 637 and 0 otherwise
entry.push_back(new LDFData<int32_t>(u"NumWins", leaderboardEntry.numWins));
entry.push_back(new LDFData<int32_t>(u"NumWins", rows->getInt("numWins")));
// NumWins:1
break;
case UnusedLeaderboard4:
entry.push_back(new LDFData<int32_t>(u"Points", leaderboardEntry.primaryScore));
case Type::UnusedLeaderboard4:
entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("primaryScore")));
// Points:1
break;
case MonumentRace:
entry.push_back(new LDFData<int32_t>(u"Time", leaderboardEntry.primaryScore));
case Type::MonumentRace:
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("primaryScore")));
// Time:1(?)
break;
case FootRace:
entry.push_back(new LDFData<int32_t>(u"Time", leaderboardEntry.primaryScore));
case Type::FootRace:
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("primaryScore")));
// Time:1
break;
case Survival:
entry.push_back(new LDFData<int32_t>(u"Points", leaderboardEntry.primaryScore));
case Type::Survival:
entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("primaryScore")));
// Points:1
entry.push_back(new LDFData<int32_t>(u"Time", leaderboardEntry.secondaryScore));
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("secondaryScore")));
// Time:1
break;
case SurvivalNS:
entry.push_back(new LDFData<int32_t>(u"Wave", leaderboardEntry.primaryScore));
case Type::SurvivalNS:
entry.push_back(new LDFData<int32_t>(u"Wave", rows->getInt("primaryScore")));
// Wave:1
entry.push_back(new LDFData<int32_t>(u"Time", leaderboardEntry.secondaryScore));
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("secondaryScore")));
// Time:1
break;
case Donations:
entry.push_back(new LDFData<int32_t>(u"Score", leaderboardEntry.primaryScore));
case Type::Donations:
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("primaryScore")));
// Score:1
break;
case None:
[[fallthrough]];
case Type::None:
// This type is included here simply to resolve a compiler warning on mac about unused enum types
break;
default:
break;
}
}
}
std::vector<ILeaderboard::Entry> FilterTo10(const std::vector<ILeaderboard::Entry>& leaderboard, const uint32_t relatedPlayer, const Leaderboard::InfoType infoType) {
std::vector<ILeaderboard::Entry> toReturn;
int32_t index = 0;
// for friends and top, we dont need to find this players index.
if (infoType == Leaderboard::InfoType::MyStanding || infoType == Leaderboard::InfoType::Friends) {
for (; index < leaderboard.size(); index++) {
if (leaderboard[index].charId == relatedPlayer) break;
}
}
if (leaderboard.size() < 10) {
toReturn.assign(leaderboard.begin(), leaderboard.end());
index = 0;
} else if (index < 10) {
toReturn.assign(leaderboard.begin(), leaderboard.begin() + 10); // get the top 10 since we are in the top 10
index = 0;
} else if (index > leaderboard.size() - 10) {
toReturn.assign(leaderboard.end() - 10, leaderboard.end()); // get the bottom 10 since we are in the bottom 10
index = leaderboard.size() - 10;
} else {
toReturn.assign(leaderboard.begin() + index - 5, leaderboard.begin() + index + 5); // get the 5 above and below
index -= 5;
}
int32_t i = index;
for (auto& entry : toReturn) {
entry.ranking = ++i;
}
return toReturn;
}
std::vector<ILeaderboard::Entry> FilterWeeklies(const std::vector<ILeaderboard::Entry>& leaderboard) {
// Filter the leaderboard to only include entries from the last week
const auto currentTime = std::chrono::system_clock::now();
auto epochTime = currentTime.time_since_epoch().count();
constexpr auto SECONDS_IN_A_WEEK = 60 * 60 * 24 * 7; // if you think im taking leap seconds into account thats cute.
std::vector<ILeaderboard::Entry> weeklyLeaderboard;
for (const auto& entry : leaderboard) {
if (epochTime - entry.lastPlayedTimestamp < SECONDS_IN_A_WEEK) {
weeklyLeaderboard.push_back(entry);
}
}
return weeklyLeaderboard;
}
std::vector<ILeaderboard::Entry> FilterFriends(const std::vector<ILeaderboard::Entry>& leaderboard, const uint32_t relatedPlayer) {
// Filter the leaderboard to only include friends of the player
auto friendOfPlayer = Database::Get()->GetFriendsList(relatedPlayer);
std::vector<ILeaderboard::Entry> friendsLeaderboard;
for (const auto& entry : leaderboard) {
const auto res = std::ranges::find_if(friendOfPlayer, [&entry, relatedPlayer](const FriendData& data) {
return entry.charId == data.friendID || entry.charId == relatedPlayer;
});
if (res != friendOfPlayer.cend()) {
friendsLeaderboard.push_back(entry);
}
}
return friendsLeaderboard;
}
std::vector<ILeaderboard::Entry> ProcessLeaderboard(
const std::vector<ILeaderboard::Entry>& leaderboard,
const bool weekly,
const Leaderboard::InfoType infoType,
const uint32_t relatedPlayer) {
std::vector<ILeaderboard::Entry> toReturn;
if (infoType == Leaderboard::InfoType::Friends) {
const auto friendsLeaderboard = FilterFriends(leaderboard, relatedPlayer);
toReturn = FilterTo10(weekly ? FilterWeeklies(friendsLeaderboard) : friendsLeaderboard, relatedPlayer, infoType);
} else {
toReturn = FilterTo10(weekly ? FilterWeeklies(leaderboard) : leaderboard, relatedPlayer, infoType);
}
return toReturn;
}
void Leaderboard::SetupLeaderboard(bool weekly) {
const auto leaderboardType = LeaderboardManager::GetLeaderboardType(gameID);
std::vector<ILeaderboard::Entry> leaderboardRes;
const std::string_view Leaderboard::GetOrdering(Leaderboard::Type leaderboardType) {
// Use a switch case and return desc for all 3 columns if higher is better and asc if lower is better
switch (leaderboardType) {
case Type::SurvivalNS:
leaderboardRes = Database::Get()->GetNsLeaderboard(gameID);
break;
case Type::Survival:
leaderboardRes = Database::Get()->GetAgsLeaderboard(gameID);
break;
case Type::Racing:
[[fallthrough]];
case Type::MonumentRace:
leaderboardRes = Database::Get()->GetAscendingLeaderboard(gameID);
break;
return "primaryScore ASC, secondaryScore ASC, tertiaryScore ASC";
case Type::Survival:
return Game::config->GetValue("classic_survival_scoring") == "1" ?
"secondaryScore DESC, primaryScore DESC, tertiaryScore DESC" :
"primaryScore DESC, secondaryScore DESC, tertiaryScore DESC";
case Type::SurvivalNS:
return "primaryScore DESC, secondaryScore ASC, tertiaryScore DESC";
case Type::ShootingGallery:
[[fallthrough]];
case Type::FootRace:
[[fallthrough]];
case Type::UnusedLeaderboard4:
case Type::Donations:
[[fallthrough]];
case Type::None:
[[fallthrough]];
default:
leaderboardRes = Database::Get()->GetDescendingLeaderboard(gameID);
break;
return "primaryScore DESC, secondaryScore DESC, tertiaryScore DESC";
}
}
const auto processedLeaderboard = ProcessLeaderboard(leaderboardRes, weekly, infoType, relatedPlayer);
void Leaderboard::SetupLeaderboard(bool weekly, uint32_t resultStart, uint32_t resultEnd) {
resultStart++;
resultEnd++;
// We need everything except 1 column so i'm selecting * from leaderboard
const std::string queryBase =
R"QUERY(
WITH leaderboardsRanked AS (
SELECT leaderboard.*, charinfo.name,
RANK() OVER
(
ORDER BY %s, UNIX_TIMESTAMP(last_played) ASC, id DESC
) AS ranking
FROM leaderboard JOIN charinfo on charinfo.id = leaderboard.character_id
WHERE game_id = ? %s
),
myStanding AS (
SELECT
ranking as myRank
FROM leaderboardsRanked
WHERE id = ?
),
lowestRanking AS (
SELECT MAX(ranking) AS lowestRank
FROM leaderboardsRanked
)
SELECT leaderboardsRanked.*, character_id, UNIX_TIMESTAMP(last_played) as lastPlayed, leaderboardsRanked.name, leaderboardsRanked.ranking FROM leaderboardsRanked, myStanding, lowestRanking
WHERE leaderboardsRanked.ranking
BETWEEN
LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), CAST(lowestRanking.lowestRank AS SIGNED) - 9)
AND
LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank)
ORDER BY ranking ASC;
)QUERY";
QueryToLdf(*this, processedLeaderboard);
std::string friendsFilter =
R"QUERY(
AND (
character_id IN (
SELECT fr.requested_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
)
OR character_id = ?
)
)QUERY";
std::string weeklyFilter = " AND UNIX_TIMESTAMP(last_played) BETWEEN UNIX_TIMESTAMP(date_sub(now(),INTERVAL 1 WEEK)) AND UNIX_TIMESTAMP(now()) ";
std::string filter;
// Setup our filter based on the query type
if (this->infoType == InfoType::Friends) filter += friendsFilter;
if (this->weekly) filter += weeklyFilter;
const auto orderBase = GetOrdering(this->leaderboardType);
// For top query, we want to just rank all scores, but for all others we need the scores around a specific player
std::string baseLookup;
if (this->infoType == InfoType::Top) {
baseLookup = "SELECT id, last_played FROM leaderboard WHERE game_id = ? " + (this->weekly ? weeklyFilter : std::string("")) + " ORDER BY ";
baseLookup += orderBase.data();
} else {
baseLookup = "SELECT id, last_played FROM leaderboard WHERE game_id = ? " + (this->weekly ? weeklyFilter : std::string("")) + " AND character_id = ";
baseLookup += std::to_string(static_cast<uint32_t>(this->relatedPlayer));
}
baseLookup += " LIMIT 1";
LOG_DEBUG("query is %s", baseLookup.c_str());
std::unique_ptr<sql::PreparedStatement> baseQuery(Database::Get()->CreatePreppedStmt(baseLookup));
baseQuery->setInt(1, this->gameID);
std::unique_ptr<sql::ResultSet> baseResult(baseQuery->executeQuery());
if (!baseResult->next()) return; // In this case, there are no entries in the leaderboard for this game.
uint32_t relatedPlayerLeaderboardId = baseResult->getInt("id");
// Create and execute the actual save here. Using a heap allocated buffer to avoid stack overflow
constexpr uint16_t STRING_LENGTH = 4096;
std::unique_ptr<char[]> lookupBuffer = std::make_unique<char[]>(STRING_LENGTH);
int32_t res = snprintf(lookupBuffer.get(), STRING_LENGTH, queryBase.c_str(), orderBase.data(), filter.c_str(), resultStart, resultEnd);
DluAssert(res != -1);
std::unique_ptr<sql::PreparedStatement> query(Database::Get()->CreatePreppedStmt(lookupBuffer.get()));
LOG_DEBUG("Query is %s vars are %i %i %i", lookupBuffer.get(), this->gameID, this->relatedPlayer, relatedPlayerLeaderboardId);
query->setInt(1, this->gameID);
if (this->infoType == InfoType::Friends) {
query->setInt(2, this->relatedPlayer);
query->setInt(3, this->relatedPlayer);
query->setInt(4, this->relatedPlayer);
query->setInt(5, relatedPlayerLeaderboardId);
} else {
query->setInt(2, relatedPlayerLeaderboardId);
}
std::unique_ptr<sql::ResultSet> result(query->executeQuery());
QueryToLdf(result);
}
void Leaderboard::Send(const LWOOBJID targetID) const {
@@ -267,43 +272,129 @@ void Leaderboard::Send(const LWOOBJID targetID) const {
}
}
std::string FormatInsert(const Leaderboard::Type& type, const Score& score, const bool useUpdate) {
std::string insertStatement;
if (useUpdate) {
insertStatement =
R"QUERY(
UPDATE leaderboard
SET primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;
)QUERY";
} else {
insertStatement =
R"QUERY(
INSERT leaderboard SET
primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
character_id = ?, game_id = ?;
)QUERY";
}
constexpr uint16_t STRING_LENGTH = 400;
// Then fill in our score
char finishedQuery[STRING_LENGTH];
int32_t res = snprintf(finishedQuery, STRING_LENGTH, insertStatement.c_str(), score.GetPrimaryScore(), score.GetSecondaryScore(), score.GetTertiaryScore());
DluAssert(res != -1);
return finishedQuery;
}
void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore, const float tertiaryScore) {
const Leaderboard::Type leaderboardType = GetLeaderboardType(activityId);
const auto oldScore = Database::Get()->GetPlayerScore(playerID, activityId);
std::unique_ptr<sql::PreparedStatement> query(Database::Get()->CreatePreppedStmt("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;"));
query->setInt(1, playerID);
query->setInt(2, activityId);
std::unique_ptr<sql::ResultSet> myScoreResult(query->executeQuery());
ILeaderboard::Score newScore{ .primaryScore = primaryScore, .secondaryScore = secondaryScore, .tertiaryScore = tertiaryScore };
if (oldScore.has_value()) {
bool lowerScoreBetter = leaderboardType == Leaderboard::Type::Racing || leaderboardType == Leaderboard::Type::MonumentRace;
std::string saveQuery("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;");
Score newScore(primaryScore, secondaryScore, tertiaryScore);
if (myScoreResult->next()) {
Score oldScore;
bool lowerScoreBetter = false;
switch (leaderboardType) {
// Higher score better
case Leaderboard::Type::ShootingGallery: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
oldScore.SetTertiaryScore(myScoreResult->getInt("tertiaryScore"));
break;
}
case Leaderboard::Type::FootRace: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
break;
}
case Leaderboard::Type::Survival: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
break;
}
case Leaderboard::Type::SurvivalNS: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
break;
}
case Leaderboard::Type::UnusedLeaderboard4:
case Leaderboard::Type::Donations: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
newScore.SetPrimaryScore(oldScore.GetPrimaryScore() + newScore.GetPrimaryScore());
break;
}
case Leaderboard::Type::Racing: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
// For wins we dont care about the score, just the time, so zero out the tertiary.
// Wins are updated later.
oldScore.SetTertiaryScore(0);
newScore.SetTertiaryScore(0);
lowerScoreBetter = true;
break;
}
case Leaderboard::Type::MonumentRace: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
lowerScoreBetter = true;
// Do score checking here
break;
}
case Leaderboard::Type::None:
default:
LOG("Unknown leaderboard type %i for game %i. Cannot save score!", leaderboardType, activityId);
return;
}
bool newHighScore = lowerScoreBetter ? newScore < oldScore : newScore > oldScore;
// Nimbus station has a weird leaderboard where we need a custom scoring system
if (leaderboardType == Leaderboard::Type::SurvivalNS) {
newHighScore = newScore.primaryScore > oldScore->primaryScore ||
(newScore.primaryScore == oldScore->primaryScore && newScore.secondaryScore < oldScore->secondaryScore);
newHighScore = newScore.GetPrimaryScore() > oldScore.GetPrimaryScore() ||
(newScore.GetPrimaryScore() == oldScore.GetPrimaryScore() && newScore.GetSecondaryScore() < oldScore.GetSecondaryScore());
} else if (leaderboardType == Leaderboard::Type::Survival && Game::config->GetValue("classic_survival_scoring") == "1") {
ILeaderboard::Score oldScoreFlipped{oldScore->secondaryScore, oldScore->primaryScore, oldScore->tertiaryScore};
ILeaderboard::Score newScoreFlipped{newScore.secondaryScore, newScore.primaryScore, newScore.tertiaryScore};
Score oldScoreFlipped(oldScore.GetSecondaryScore(), oldScore.GetPrimaryScore());
Score newScoreFlipped(newScore.GetSecondaryScore(), newScore.GetPrimaryScore());
newHighScore = newScoreFlipped > oldScoreFlipped;
}
if (newHighScore) {
Database::Get()->UpdateScore(playerID, activityId, newScore);
} else {
Database::Get()->IncrementTimesPlayed(playerID, activityId);
saveQuery = FormatInsert(leaderboardType, newScore, true);
}
} else {
Database::Get()->SaveScore(playerID, activityId, newScore);
saveQuery = FormatInsert(leaderboardType, newScore, false);
}
LOG("save query %s %i %i", saveQuery.c_str(), playerID, activityId);
std::unique_ptr<sql::PreparedStatement> saveStatement(Database::Get()->CreatePreppedStmt(saveQuery));
saveStatement->setInt(1, playerID);
saveStatement->setInt(2, activityId);
saveStatement->execute();
// track wins separately
if (leaderboardType == Leaderboard::Type::Racing && tertiaryScore != 0.0f) {
Database::Get()->IncrementNumWins(playerID, activityId);
std::unique_ptr<sql::PreparedStatement> winUpdate(Database::Get()->CreatePreppedStmt("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;"));
winUpdate->setInt(1, playerID);
winUpdate->setInt(2, activityId);
winUpdate->execute();
}
}
void LeaderboardManager::SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID) {
void LeaderboardManager::SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID, const uint32_t resultStart, const uint32_t resultEnd) {
Leaderboard leaderboard(gameID, infoType, weekly, playerID, GetLeaderboardType(gameID));
leaderboard.SetupLeaderboard(weekly);
leaderboard.SetupLeaderboard(weekly, resultStart, resultEnd);
leaderboard.Send(targetID);
}

View File

@@ -9,10 +9,46 @@
#include "dCommonVars.h"
#include "LDFFormat.h"
namespace sql {
class ResultSet;
};
namespace RakNet {
class BitStream;
};
class Score {
public:
Score() {
primaryScore = 0;
secondaryScore = 0;
tertiaryScore = 0;
}
Score(const float primaryScore, const float secondaryScore = 0, const float tertiaryScore = 0) {
this->primaryScore = primaryScore;
this->secondaryScore = secondaryScore;
this->tertiaryScore = tertiaryScore;
}
bool operator<(const Score& rhs) const {
return primaryScore < rhs.primaryScore || (primaryScore == rhs.primaryScore && secondaryScore < rhs.secondaryScore) || (primaryScore == rhs.primaryScore && secondaryScore == rhs.secondaryScore && tertiaryScore < rhs.tertiaryScore);
}
bool operator>(const Score& rhs) const {
return primaryScore > rhs.primaryScore || (primaryScore == rhs.primaryScore && secondaryScore > rhs.secondaryScore) || (primaryScore == rhs.primaryScore && secondaryScore == rhs.secondaryScore && tertiaryScore > rhs.tertiaryScore);
}
void SetPrimaryScore(const float score) { primaryScore = score; }
float GetPrimaryScore() const { return primaryScore; }
void SetSecondaryScore(const float score) { secondaryScore = score; }
float GetSecondaryScore() const { return secondaryScore; }
void SetTertiaryScore(const float score) { tertiaryScore = score; }
float GetTertiaryScore() const { return tertiaryScore; }
private:
float primaryScore;
float secondaryScore;
float tertiaryScore;
};
using GameID = uint32_t;
class Leaderboard {
@@ -43,7 +79,7 @@ public:
/**
* @brief Resets the leaderboard state and frees its allocated memory
*
*
*/
void Clear();
@@ -60,16 +96,20 @@ public:
* @param resultStart The index to start the leaderboard at. Zero indexed.
* @param resultEnd The index to end the leaderboard at. Zero indexed.
*/
void SetupLeaderboard(bool weekly);
void SetupLeaderboard(bool weekly, uint32_t resultStart = 0, uint32_t resultEnd = 10);
/**
* Sends the leaderboard to the client specified by targetID.
*/
void Send(const LWOOBJID targetID) const;
// Helper function to get the columns, ordering and insert format for a leaderboard
static const std::string_view GetOrdering(Type leaderboardType);
private:
// Takes the resulting query from a leaderboard lookup and converts it to the LDF we need
// to send it to a client.
void QueryToLdf(std::unique_ptr<sql::ResultSet>& rows);
using LeaderboardEntry = std::vector<LDFBaseData*>;
using LeaderboardEntries = std::vector<LeaderboardEntry>;
@@ -79,18 +119,10 @@ private:
InfoType infoType;
Leaderboard::Type leaderboardType;
bool weekly;
public:
LeaderboardEntry& PushBackEntry() {
return entries.emplace_back();
}
Type GetLeaderboardType() const {
return leaderboardType;
}
};
namespace LeaderboardManager {
void SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID);
void SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID, const uint32_t resultStart = 0, const uint32_t resultEnd = 10);
void SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore = 0, const float tertiaryScore = 0);

View File

@@ -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; }

View File

@@ -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);

View File

@@ -212,7 +212,7 @@ void BehaviorContext::UpdatePlayerSyncs(float deltaTime) {
echo.sBitStream.assign(reinterpret_cast<char*>(bitStream.GetData()), bitStream.GetNumberOfBytesUsed());
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);
@@ -285,7 +285,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);

View File

@@ -1,7 +1,7 @@
#pragma once
#include "Behavior.h"
#include "eAnimationFlags.h"
#include "eAninmationFlags.h"
class ChangeIdleFlagsBehavior final : public Behavior {
public:

View File

@@ -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());

View File

@@ -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.
*/

View File

@@ -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) {

View File

@@ -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

View File

@@ -7,7 +7,6 @@
#include "BehaviorStates.h"
#include "ControlBehaviorMsgs.h"
#include "tinyxml2.h"
#include "SimplePhysicsComponent.h"
#include "Database.h"
@@ -96,24 +95,12 @@ 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 {

View File

@@ -66,8 +66,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;

View File

@@ -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);

View File

@@ -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

View File

@@ -5,7 +5,7 @@
#include "Component.h"
#include "Item.h"
#include "PossessorComponent.h"
#include "eAnimationFlags.h"
#include "eAninmationFlags.h"
#include "eReplicaComponentType.h"
/**

View File

@@ -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);
}

View File

@@ -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 >= ? ";
};

View File

@@ -38,7 +38,7 @@ void ProximityMonitorComponent::SetProximityRadius(dpEntity* entity, const std::
m_ProximitiesData.insert(std::make_pair(name, entity));
}
const std::unordered_set<LWOOBJID>& ProximityMonitorComponent::GetProximityObjects(const std::string& name) const {
const std::unordered_set<LWOOBJID>& ProximityMonitorComponent::GetProximityObjects(const std::string& name) {
const auto iter = m_ProximitiesData.find(name);
if (iter == m_ProximitiesData.cend()) {

View File

@@ -46,7 +46,7 @@ public:
* @param name the proximity name to retrieve physics objects for
* @return a set of physics entity object IDs for this name
*/
const std::unordered_set<LWOOBJID>& GetProximityObjects(const std::string& name) const;
const std::unordered_set<LWOOBJID>& GetProximityObjects(const std::string& name);
/**
* Checks if the passed object is in proximity of the named proximity sensor

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -24,7 +24,7 @@
#include "CDClientManager.h"
#include "CDSkillBehaviorTable.h"
#include "eConnectionType.h"
#include "MessageType/Client.h"
#include "eClientMessageType.h"
ProjectileSyncEntry::ProjectileSyncEntry() {
}
@@ -320,7 +320,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 +451,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);

View File

@@ -2,7 +2,6 @@
#include "EntityManager.h"
#include "eTriggerEventType.h"
#include "RenderComponent.h"
#include "DestroyableComponent.h"
std::vector<SwitchComponent*> SwitchComponent::petSwitches;
@@ -12,13 +11,6 @@ SwitchComponent::SwitchComponent(Entity* parent) : Component(parent) {
m_ResetTime = m_Parent->GetVarAs<int32_t>(u"switch_reset_time");
m_QuickBuild = m_Parent->GetComponent<QuickBuildComponent>();
const auto factions = GeneralUtils::SplitString(m_Parent->GetVar<std::u16string>(u"respond_to_faction"), u':');
for (const auto& faction : factions) {
auto factionID = GeneralUtils::TryParse<int32_t>(GeneralUtils::UTF16ToWTF8(faction));
if (!factionID) continue;
m_FactionsToRespondTo.push_back(factionID.value());
}
}
SwitchComponent::~SwitchComponent() {
@@ -33,17 +25,6 @@ void SwitchComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitial
outBitStream.Write(m_Active);
}
void SwitchComponent::OnUse(Entity* originator) {
const auto* const destroyableComponent = originator->GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
for (const auto faction : m_FactionsToRespondTo) {
if (destroyableComponent->HasFaction(faction)) {
EntityEnter(originator);
break;
}
}
}
void SwitchComponent::SetActive(bool active) {
m_Active = active;

View File

@@ -22,7 +22,6 @@ public:
~SwitchComponent() override;
void Update(float deltaTime) override;
void OnUse(Entity* originator) override;
Entity* GetParentEntity() const;
@@ -102,8 +101,6 @@ private:
* Attached pet bouncer
*/
BouncerComponent* m_PetBouncer = nullptr;
std::vector<int32_t> m_FactionsToRespondTo{};
};
#endif // SWITCHCOMPONENT_H

View File

@@ -27,7 +27,7 @@ public:
}
void Serialize(RakNet::BitStream& stream) {
stream.Write(MessageType::Game::DO_CLIENT_PROJECTILE_IMPACT);
stream.Write(eGameMessageType::DO_CLIENT_PROJECTILE_IMPACT);
stream.Write(i64OrgID != LWOOBJID_EMPTY);
if (i64OrgID != LWOOBJID_EMPTY) stream.Write(i64OrgID);

View File

@@ -4,7 +4,7 @@
#include "dCommonVars.h"
#include "NiPoint3.h"
#include "NiQuaternion.h"
#include "MessageType/Game.h"
#include "eGameMessageType.h"
/* Same as start skill but with different network options. An echo down to other clients that need to play the skill. */
class EchoStartSkill {
@@ -40,7 +40,7 @@ public:
}
void Serialize(RakNet::BitStream& stream) {
stream.Write(MessageType::Game::ECHO_START_SKILL);
stream.Write(eGameMessageType::ECHO_START_SKILL);
stream.Write(bUsedMouse);

View File

@@ -4,7 +4,7 @@
#include <string>
#include "BitStream.h"
#include "MessageType/Game.h"
#include "eGameMessageType.h"
/* Message to synchronize a skill cast */
@@ -29,7 +29,7 @@ public:
}
void Serialize(RakNet::BitStream& stream) {
stream.Write(MessageType::Game::ECHO_SYNC_SKILL);
stream.Write(eGameMessageType::ECHO_SYNC_SKILL);
stream.Write(bDone);
uint32_t sBitStreamLength = sBitStream.length();

View File

@@ -33,13 +33,13 @@
#include "eMissionTaskType.h"
#include "eReplicaComponentType.h"
#include "eConnectionType.h"
#include "MessageType/Game.h"
#include "eGameMessageType.h"
#include "ePlayerFlag.h"
#include "dConfig.h"
#include "GhostComponent.h"
#include "StringifiedEnum.h"
void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, MessageType::Game messageID) {
void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, eGameMessageType messageID) {
CBITSTREAM;
@@ -53,58 +53,58 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
return;
}
if (messageID != MessageType::Game::READY_FOR_UPDATES) LOG_DEBUG("Received GM with ID and name: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
if (messageID != eGameMessageType::READY_FOR_UPDATES) LOG_DEBUG("Received GM with ID and name: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
switch (messageID) {
case MessageType::Game::UN_USE_BBB_MODEL: {
case eGameMessageType::UN_USE_BBB_MODEL: {
GameMessages::HandleUnUseModel(inStream, entity, sysAddr);
break;
}
case MessageType::Game::PLAY_EMOTE: {
case eGameMessageType::PLAY_EMOTE: {
GameMessages::HandlePlayEmote(inStream, entity);
break;
}
case MessageType::Game::MOVE_ITEM_IN_INVENTORY: {
case eGameMessageType::MOVE_ITEM_IN_INVENTORY: {
GameMessages::HandleMoveItemInInventory(inStream, entity);
break;
}
case MessageType::Game::REMOVE_ITEM_FROM_INVENTORY: {
case eGameMessageType::REMOVE_ITEM_FROM_INVENTORY: {
GameMessages::HandleRemoveItemFromInventory(inStream, entity, sysAddr);
break;
}
case MessageType::Game::EQUIP_INVENTORY:
case eGameMessageType::EQUIP_INVENTORY:
GameMessages::HandleEquipItem(inStream, entity);
break;
case MessageType::Game::UN_EQUIP_INVENTORY:
case eGameMessageType::UN_EQUIP_INVENTORY:
GameMessages::HandleUnequipItem(inStream, entity);
break;
case MessageType::Game::RESPOND_TO_MISSION: {
case eGameMessageType::RESPOND_TO_MISSION: {
GameMessages::HandleRespondToMission(inStream, entity);
break;
}
case MessageType::Game::REQUEST_USE: {
case eGameMessageType::REQUEST_USE: {
GameMessages::HandleRequestUse(inStream, entity, sysAddr);
break;
}
case MessageType::Game::SET_FLAG: {
case eGameMessageType::SET_FLAG: {
GameMessages::HandleSetFlag(inStream, entity);
break;
}
case MessageType::Game::HAS_BEEN_COLLECTED: {
case eGameMessageType::HAS_BEEN_COLLECTED: {
GameMessages::HandleHasBeenCollected(inStream, entity);
break;
}
case MessageType::Game::PLAYER_LOADED: {
case eGameMessageType::PLAYER_LOADED: {
GameMessages::SendRestoreToPostLoadStats(entity, sysAddr);
entity->SetPlayerReadyForUpdates();
@@ -183,82 +183,82 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
break;
}
case MessageType::Game::REQUEST_LINKED_MISSION: {
case eGameMessageType::REQUEST_LINKED_MISSION: {
GameMessages::HandleRequestLinkedMission(inStream, entity);
break;
}
case MessageType::Game::MISSION_DIALOGUE_OK: {
case eGameMessageType::MISSION_DIALOGUE_OK: {
GameMessages::HandleMissionDialogOK(inStream, entity);
break;
}
case MessageType::Game::MISSION_DIALOGUE_CANCELLED: {
case eGameMessageType::MISSION_DIALOGUE_CANCELLED: {
// This message is pointless for our implementation, as the client just carries on after
// rejecting a mission offer. We dont need to do anything. This is just here to remove a warning in our logs :)
break;
}
case MessageType::Game::REQUEST_PLATFORM_RESYNC: {
case eGameMessageType::REQUEST_PLATFORM_RESYNC: {
GameMessages::HandleRequestPlatformResync(inStream, entity, sysAddr);
break;
}
case MessageType::Game::FIRE_EVENT_SERVER_SIDE: {
case eGameMessageType::FIRE_EVENT_SERVER_SIDE: {
GameMessages::HandleFireEventServerSide(inStream, entity, sysAddr);
break;
}
case MessageType::Game::SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA: {
case eGameMessageType::SEND_ACTIVITY_SUMMARY_LEADERBOARD_DATA: {
GameMessages::HandleActivitySummaryLeaderboardData(inStream, entity, sysAddr);
break;
}
case MessageType::Game::REQUEST_ACTIVITY_SUMMARY_LEADERBOARD_DATA: {
case eGameMessageType::REQUEST_ACTIVITY_SUMMARY_LEADERBOARD_DATA: {
GameMessages::HandleRequestActivitySummaryLeaderboardData(inStream, entity, sysAddr);
break;
}
case MessageType::Game::ACTIVITY_STATE_CHANGE_REQUEST: {
case eGameMessageType::ACTIVITY_STATE_CHANGE_REQUEST: {
GameMessages::HandleActivityStateChangeRequest(inStream, entity);
break;
}
case MessageType::Game::PARSE_CHAT_MESSAGE: {
case eGameMessageType::PARSE_CHAT_MESSAGE: {
GameMessages::HandleParseChatMessage(inStream, entity, sysAddr);
break;
}
case MessageType::Game::NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE: {
case eGameMessageType::NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE: {
GameMessages::HandleNotifyServerLevelProcessingComplete(inStream, entity);
break;
}
case MessageType::Game::PICKUP_CURRENCY: {
case eGameMessageType::PICKUP_CURRENCY: {
GameMessages::HandlePickupCurrency(inStream, entity);
break;
}
case MessageType::Game::PICKUP_ITEM: {
case eGameMessageType::PICKUP_ITEM: {
GameMessages::HandlePickupItem(inStream, entity);
break;
}
case MessageType::Game::RESURRECT: {
case eGameMessageType::RESURRECT: {
GameMessages::HandleResurrect(inStream, entity);
break;
}
case MessageType::Game::REQUEST_RESURRECT: {
case eGameMessageType::REQUEST_RESURRECT: {
GameMessages::SendResurrect(entity);
break;
}
case MessageType::Game::GET_HOT_PROPERTY_DATA: {
case eGameMessageType::GET_HOT_PROPERTY_DATA: {
GameMessages::HandleGetHotPropertyData(inStream, entity, sysAddr);
break;
}
case MessageType::Game::REQUEST_SERVER_PROJECTILE_IMPACT:
case eGameMessageType::REQUEST_SERVER_PROJECTILE_IMPACT:
{
auto message = RequestServerProjectileImpact();
@@ -275,7 +275,7 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
break;
}
case MessageType::Game::START_SKILL: {
case eGameMessageType::START_SKILL: {
StartSkill startSkill = StartSkill();
startSkill.Deserialize(inStream); // inStream replaces &bitStream
@@ -311,7 +311,7 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
if (success) {
//Broadcast our startSkill:
RakNet::BitStream bitStreamLocal;
BitStreamUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, MessageType::Client::GAME_MSG);
BitStreamUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
bitStreamLocal.Write(entity->GetObjectID());
EchoStartSkill echoStartSkill;
@@ -331,9 +331,9 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
}
} break;
case MessageType::Game::SYNC_SKILL: {
case eGameMessageType::SYNC_SKILL: {
RakNet::BitStream bitStreamLocal;
BitStreamUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, MessageType::Client::GAME_MSG);
BitStreamUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
bitStreamLocal.Write(entity->GetObjectID());
SyncSkill sync = SyncSkill(inStream); // inStream replaced &bitStream
@@ -365,330 +365,330 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
Game::server->Send(bitStreamLocal, sysAddr, true);
} break;
case MessageType::Game::REQUEST_SMASH_PLAYER:
case eGameMessageType::REQUEST_SMASH_PLAYER:
entity->Smash(entity->GetObjectID());
break;
case MessageType::Game::MOVE_ITEM_BETWEEN_INVENTORY_TYPES:
case eGameMessageType::MOVE_ITEM_BETWEEN_INVENTORY_TYPES:
GameMessages::HandleMoveItemBetweenInventoryTypes(inStream, entity, sysAddr);
break;
case MessageType::Game::MODULAR_BUILD_FINISH:
case eGameMessageType::MODULAR_BUILD_FINISH:
GameMessages::HandleModularBuildFinish(inStream, entity, sysAddr);
break;
case MessageType::Game::PUSH_EQUIPPED_ITEMS_STATE:
case eGameMessageType::PUSH_EQUIPPED_ITEMS_STATE:
GameMessages::HandlePushEquippedItemsState(inStream, entity);
break;
case MessageType::Game::POP_EQUIPPED_ITEMS_STATE:
case eGameMessageType::POP_EQUIPPED_ITEMS_STATE:
GameMessages::HandlePopEquippedItemsState(inStream, entity);
break;
case MessageType::Game::BUY_FROM_VENDOR:
case eGameMessageType::BUY_FROM_VENDOR:
GameMessages::HandleBuyFromVendor(inStream, entity, sysAddr);
break;
case MessageType::Game::SELL_TO_VENDOR:
case eGameMessageType::SELL_TO_VENDOR:
GameMessages::HandleSellToVendor(inStream, entity, sysAddr);
break;
case MessageType::Game::BUYBACK_FROM_VENDOR:
case eGameMessageType::BUYBACK_FROM_VENDOR:
GameMessages::HandleBuybackFromVendor(inStream, entity, sysAddr);
break;
case MessageType::Game::MODULAR_BUILD_MOVE_AND_EQUIP:
case eGameMessageType::MODULAR_BUILD_MOVE_AND_EQUIP:
GameMessages::HandleModularBuildMoveAndEquip(inStream, entity, sysAddr);
break;
case MessageType::Game::DONE_ARRANGING_WITH_ITEM:
case eGameMessageType::DONE_ARRANGING_WITH_ITEM:
GameMessages::HandleDoneArrangingWithItem(inStream, entity, sysAddr);
break;
case MessageType::Game::MODULAR_BUILD_CONVERT_MODEL:
case eGameMessageType::MODULAR_BUILD_CONVERT_MODEL:
GameMessages::HandleModularBuildConvertModel(inStream, entity, sysAddr);
break;
case MessageType::Game::BUILD_MODE_SET:
case eGameMessageType::BUILD_MODE_SET:
GameMessages::HandleBuildModeSet(inStream, entity);
break;
case MessageType::Game::REBUILD_CANCEL:
case eGameMessageType::REBUILD_CANCEL:
GameMessages::HandleQuickBuildCancel(inStream, entity);
break;
case MessageType::Game::MATCH_REQUEST:
case eGameMessageType::MATCH_REQUEST:
GameMessages::HandleMatchRequest(inStream, entity);
break;
case MessageType::Game::USE_NON_EQUIPMENT_ITEM:
case eGameMessageType::USE_NON_EQUIPMENT_ITEM:
GameMessages::HandleUseNonEquipmentItem(inStream, entity);
break;
case MessageType::Game::CLIENT_ITEM_CONSUMED:
case eGameMessageType::CLIENT_ITEM_CONSUMED:
GameMessages::HandleClientItemConsumed(inStream, entity);
break;
case MessageType::Game::SET_CONSUMABLE_ITEM:
case eGameMessageType::SET_CONSUMABLE_ITEM:
GameMessages::HandleSetConsumableItem(inStream, entity, sysAddr);
break;
case MessageType::Game::VERIFY_ACK:
case eGameMessageType::VERIFY_ACK:
GameMessages::HandleVerifyAck(inStream, entity, sysAddr);
break;
// Trading
case MessageType::Game::CLIENT_TRADE_REQUEST:
case eGameMessageType::CLIENT_TRADE_REQUEST:
GameMessages::HandleClientTradeRequest(inStream, entity, sysAddr);
break;
case MessageType::Game::CLIENT_TRADE_CANCEL:
case eGameMessageType::CLIENT_TRADE_CANCEL:
GameMessages::HandleClientTradeCancel(inStream, entity, sysAddr);
break;
case MessageType::Game::CLIENT_TRADE_ACCEPT:
case eGameMessageType::CLIENT_TRADE_ACCEPT:
GameMessages::HandleClientTradeAccept(inStream, entity, sysAddr);
break;
case MessageType::Game::CLIENT_TRADE_UPDATE:
case eGameMessageType::CLIENT_TRADE_UPDATE:
GameMessages::HandleClientTradeUpdate(inStream, entity, sysAddr);
break;
// Pets
case MessageType::Game::PET_TAMING_TRY_BUILD:
case eGameMessageType::PET_TAMING_TRY_BUILD:
GameMessages::HandlePetTamingTryBuild(inStream, entity, sysAddr);
break;
case MessageType::Game::NOTIFY_TAMING_BUILD_SUCCESS:
case eGameMessageType::NOTIFY_TAMING_BUILD_SUCCESS:
GameMessages::HandleNotifyTamingBuildSuccess(inStream, entity, sysAddr);
break;
case MessageType::Game::REQUEST_SET_PET_NAME:
case eGameMessageType::REQUEST_SET_PET_NAME:
GameMessages::HandleRequestSetPetName(inStream, entity, sysAddr);
break;
case MessageType::Game::START_SERVER_PET_MINIGAME_TIMER:
case eGameMessageType::START_SERVER_PET_MINIGAME_TIMER:
GameMessages::HandleStartServerPetMinigameTimer(inStream, entity, sysAddr);
break;
case MessageType::Game::CLIENT_EXIT_TAMING_MINIGAME:
case eGameMessageType::CLIENT_EXIT_TAMING_MINIGAME:
GameMessages::HandleClientExitTamingMinigame(inStream, entity, sysAddr);
break;
case MessageType::Game::COMMAND_PET:
case eGameMessageType::COMMAND_PET:
GameMessages::HandleCommandPet(inStream, entity, sysAddr);
break;
case MessageType::Game::DESPAWN_PET:
case eGameMessageType::DESPAWN_PET:
GameMessages::HandleDespawnPet(inStream, entity, sysAddr);
break;
case MessageType::Game::MESSAGE_BOX_RESPOND:
case eGameMessageType::MESSAGE_BOX_RESPOND:
GameMessages::HandleMessageBoxResponse(inStream, entity, sysAddr);
break;
case MessageType::Game::CHOICE_BOX_RESPOND:
case eGameMessageType::CHOICE_BOX_RESPOND:
GameMessages::HandleChoiceBoxRespond(inStream, entity, sysAddr);
break;
// Property
case MessageType::Game::QUERY_PROPERTY_DATA:
case eGameMessageType::QUERY_PROPERTY_DATA:
GameMessages::HandleQueryPropertyData(inStream, entity, sysAddr);
break;
case MessageType::Game::START_BUILDING_WITH_ITEM:
case eGameMessageType::START_BUILDING_WITH_ITEM:
GameMessages::HandleStartBuildingWithItem(inStream, entity, sysAddr);
break;
case MessageType::Game::SET_BUILD_MODE:
case eGameMessageType::SET_BUILD_MODE:
GameMessages::HandleSetBuildMode(inStream, entity, sysAddr);
break;
case MessageType::Game::PROPERTY_EDITOR_BEGIN:
case eGameMessageType::PROPERTY_EDITOR_BEGIN:
GameMessages::HandlePropertyEditorBegin(inStream, entity, sysAddr);
break;
case MessageType::Game::PROPERTY_EDITOR_END:
case eGameMessageType::PROPERTY_EDITOR_END:
GameMessages::HandlePropertyEditorEnd(inStream, entity, sysAddr);
break;
case MessageType::Game::PROPERTY_CONTENTS_FROM_CLIENT:
case eGameMessageType::PROPERTY_CONTENTS_FROM_CLIENT:
GameMessages::HandlePropertyContentsFromClient(inStream, entity, sysAddr);
break;
case MessageType::Game::ZONE_PROPERTY_MODEL_EQUIPPED:
case eGameMessageType::ZONE_PROPERTY_MODEL_EQUIPPED:
GameMessages::HandlePropertyModelEquipped(inStream, entity, sysAddr);
break;
case MessageType::Game::PLACE_PROPERTY_MODEL:
case eGameMessageType::PLACE_PROPERTY_MODEL:
GameMessages::HandlePlacePropertyModel(inStream, entity, sysAddr);
break;
case MessageType::Game::UPDATE_MODEL_FROM_CLIENT:
case eGameMessageType::UPDATE_MODEL_FROM_CLIENT:
GameMessages::HandleUpdatePropertyModel(inStream, entity, sysAddr);
break;
case MessageType::Game::DELETE_MODEL_FROM_CLIENT:
case eGameMessageType::DELETE_MODEL_FROM_CLIENT:
GameMessages::HandleDeletePropertyModel(inStream, entity, sysAddr);
break;
case MessageType::Game::BBB_LOAD_ITEM_REQUEST:
case eGameMessageType::BBB_LOAD_ITEM_REQUEST:
GameMessages::HandleBBBLoadItemRequest(inStream, entity, sysAddr);
break;
case MessageType::Game::BBB_SAVE_REQUEST:
case eGameMessageType::BBB_SAVE_REQUEST:
GameMessages::HandleBBBSaveRequest(inStream, entity, sysAddr);
break;
case MessageType::Game::CONTROL_BEHAVIORS:
case eGameMessageType::CONTROL_BEHAVIORS:
GameMessages::HandleControlBehaviors(inStream, entity, sysAddr);
break;
case MessageType::Game::PROPERTY_ENTRANCE_SYNC:
case eGameMessageType::PROPERTY_ENTRANCE_SYNC:
GameMessages::HandlePropertyEntranceSync(inStream, entity, sysAddr);
break;
case MessageType::Game::ENTER_PROPERTY1:
case eGameMessageType::ENTER_PROPERTY1:
GameMessages::HandleEnterProperty(inStream, entity, sysAddr);
break;
case MessageType::Game::ZONE_PROPERTY_MODEL_ROTATED:
case eGameMessageType::ZONE_PROPERTY_MODEL_ROTATED:
Game::entityManager->GetZoneControlEntity()->OnZonePropertyModelRotated(usr->GetLastUsedChar()->GetEntity());
break;
case MessageType::Game::UPDATE_PROPERTY_OR_MODEL_FOR_FILTER_CHECK:
case eGameMessageType::UPDATE_PROPERTY_OR_MODEL_FOR_FILTER_CHECK:
GameMessages::HandleUpdatePropertyOrModelForFilterCheck(inStream, entity, sysAddr);
break;
case MessageType::Game::SET_PROPERTY_ACCESS:
case eGameMessageType::SET_PROPERTY_ACCESS:
GameMessages::HandleSetPropertyAccess(inStream, entity, sysAddr);
break;
// Racing
case MessageType::Game::MODULE_ASSEMBLY_QUERY_DATA:
case eGameMessageType::MODULE_ASSEMBLY_QUERY_DATA:
GameMessages::HandleModuleAssemblyQueryData(inStream, entity, sysAddr);
break;
case MessageType::Game::ACKNOWLEDGE_POSSESSION:
case eGameMessageType::ACKNOWLEDGE_POSSESSION:
GameMessages::HandleAcknowledgePossession(inStream, entity, sysAddr);
break;
case MessageType::Game::VEHICLE_SET_WHEEL_LOCK_STATE:
case eGameMessageType::VEHICLE_SET_WHEEL_LOCK_STATE:
GameMessages::HandleVehicleSetWheelLockState(inStream, entity, sysAddr);
break;
case MessageType::Game::MODULAR_ASSEMBLY_NIF_COMPLETED:
case eGameMessageType::MODULAR_ASSEMBLY_NIF_COMPLETED:
GameMessages::HandleModularAssemblyNIFCompleted(inStream, entity, sysAddr);
break;
case MessageType::Game::RACING_CLIENT_READY:
case eGameMessageType::RACING_CLIENT_READY:
GameMessages::HandleRacingClientReady(inStream, entity, sysAddr);
break;
case MessageType::Game::REQUEST_DIE:
case eGameMessageType::REQUEST_DIE:
GameMessages::HandleRequestDie(inStream, entity, sysAddr);
break;
case MessageType::Game::NOTIFY_SERVER_VEHICLE_ADD_PASSIVE_BOOST_ACTION:
case eGameMessageType::NOTIFY_SERVER_VEHICLE_ADD_PASSIVE_BOOST_ACTION:
GameMessages::HandleVehicleNotifyServerAddPassiveBoostAction(inStream, entity, sysAddr);
break;
case MessageType::Game::NOTIFY_SERVER_VEHICLE_REMOVE_PASSIVE_BOOST_ACTION:
case eGameMessageType::NOTIFY_SERVER_VEHICLE_REMOVE_PASSIVE_BOOST_ACTION:
GameMessages::HandleVehicleNotifyServerRemovePassiveBoostAction(inStream, entity, sysAddr);
break;
case MessageType::Game::RACING_PLAYER_INFO_RESET_FINISHED:
case eGameMessageType::RACING_PLAYER_INFO_RESET_FINISHED:
GameMessages::HandleRacingPlayerInfoResetFinished(inStream, entity, sysAddr);
break;
case MessageType::Game::VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER:
case eGameMessageType::VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER:
GameMessages::HandleVehicleNotifyHitImaginationServer(inStream, entity, sysAddr);
break;
case MessageType::Game::UPDATE_PROPERTY_PERFORMANCE_COST:
case eGameMessageType::UPDATE_PROPERTY_PERFORMANCE_COST:
GameMessages::HandleUpdatePropertyPerformanceCost(inStream, entity, sysAddr);
break;
// SG
case MessageType::Game::UPDATE_SHOOTING_GALLERY_ROTATION:
case eGameMessageType::UPDATE_SHOOTING_GALLERY_ROTATION:
GameMessages::HandleUpdateShootingGalleryRotation(inStream, entity, sysAddr);
break;
// NT
case MessageType::Game::REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES:
case eGameMessageType::REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES:
GameMessages::HandleRequestMoveItemBetweenInventoryTypes(inStream, entity, sysAddr);
break;
case MessageType::Game::TOGGLE_GHOST_REFERENCE_OVERRIDE:
case eGameMessageType::TOGGLE_GHOST_REFERENCE_OVERRIDE:
GameMessages::HandleToggleGhostReferenceOverride(inStream, entity, sysAddr);
break;
case MessageType::Game::SET_GHOST_REFERENCE_POSITION:
case eGameMessageType::SET_GHOST_REFERENCE_POSITION:
GameMessages::HandleSetGhostReferencePosition(inStream, entity, sysAddr);
break;
case MessageType::Game::READY_FOR_UPDATES:
case eGameMessageType::READY_FOR_UPDATES:
//We don't really care about this message, as it's simply here to inform us that the client is done loading an object.
//In the event we _do_ send an update to an object that hasn't finished loading, the client will handle it anyway.
break;
case MessageType::Game::REPORT_BUG:
case eGameMessageType::REPORT_BUG:
GameMessages::HandleReportBug(inStream, entity);
break;
case MessageType::Game::CLIENT_RAIL_MOVEMENT_READY:
case eGameMessageType::CLIENT_RAIL_MOVEMENT_READY:
GameMessages::HandleClientRailMovementReady(inStream, entity, sysAddr);
break;
case MessageType::Game::CANCEL_RAIL_MOVEMENT:
case eGameMessageType::CANCEL_RAIL_MOVEMENT:
GameMessages::HandleCancelRailMovement(inStream, entity, sysAddr);
break;
case MessageType::Game::PLAYER_RAIL_ARRIVED_NOTIFICATION:
case eGameMessageType::PLAYER_RAIL_ARRIVED_NOTIFICATION:
GameMessages::HandlePlayerRailArrivedNotification(inStream, entity, sysAddr);
break;
case MessageType::Game::CINEMATIC_UPDATE:
case eGameMessageType::CINEMATIC_UPDATE:
GameMessages::HandleCinematicUpdate(inStream, entity, sysAddr);
break;
case MessageType::Game::MODIFY_PLAYER_ZONE_STATISTIC:
case eGameMessageType::MODIFY_PLAYER_ZONE_STATISTIC:
GameMessages::HandleModifyPlayerZoneStatistic(inStream, entity);
break;
case MessageType::Game::UPDATE_PLAYER_STATISTIC:
case eGameMessageType::UPDATE_PLAYER_STATISTIC:
GameMessages::HandleUpdatePlayerStatistic(inStream, entity);
break;
case MessageType::Game::DISMOUNT_COMPLETE:
case eGameMessageType::DISMOUNT_COMPLETE:
GameMessages::HandleDismountComplete(inStream, entity, sysAddr);
break;
case MessageType::Game::DECTIVATE_BUBBLE_BUFF:
case eGameMessageType::DECTIVATE_BUBBLE_BUFF:
GameMessages::HandleDeactivateBubbleBuff(inStream, entity);
break;
case MessageType::Game::ACTIVATE_BUBBLE_BUFF:
case eGameMessageType::ACTIVATE_BUBBLE_BUFF:
GameMessages::HandleActivateBubbleBuff(inStream, entity);
break;
case MessageType::Game::ZONE_SUMMARY_DISMISSED:
case eGameMessageType::ZONE_SUMMARY_DISMISSED:
GameMessages::HandleZoneSummaryDismissed(inStream, entity);
break;
case MessageType::Game::REQUEST_ACTIVITY_EXIT:
case eGameMessageType::REQUEST_ACTIVITY_EXIT:
GameMessages::HandleRequestActivityExit(inStream, entity);
break;
case MessageType::Game::ADD_DONATION_ITEM:
case eGameMessageType::ADD_DONATION_ITEM:
GameMessages::HandleAddDonationItem(inStream, entity, sysAddr);
break;
case MessageType::Game::REMOVE_DONATION_ITEM:
case eGameMessageType::REMOVE_DONATION_ITEM:
GameMessages::HandleRemoveDonationItem(inStream, entity, sysAddr);
break;
case MessageType::Game::CONFIRM_DONATION_ON_PLAYER:
case eGameMessageType::CONFIRM_DONATION_ON_PLAYER:
GameMessages::HandleConfirmDonationOnPlayer(inStream, entity);
break;
case MessageType::Game::CANCEL_DONATION_ON_PLAYER:
case eGameMessageType::CANCEL_DONATION_ON_PLAYER:
GameMessages::HandleCancelDonationOnPlayer(inStream, entity);
break;
case MessageType::Game::REQUEST_VENDOR_STATUS_UPDATE:
case eGameMessageType::REQUEST_VENDOR_STATUS_UPDATE:
GameMessages::SendVendorStatusUpdate(entity, sysAddr, true);
break;
case MessageType::Game::UPDATE_INVENTORY_GROUP:
case eGameMessageType::UPDATE_INVENTORY_GROUP:
GameMessages::HandleUpdateInventoryGroup(inStream, entity, sysAddr);
break;
case MessageType::Game::UPDATE_INVENTORY_GROUP_CONTENTS:
case eGameMessageType::UPDATE_INVENTORY_GROUP_CONTENTS:
GameMessages::HandleUpdateInventoryGroupContents(inStream, entity, sysAddr);
break;

View File

@@ -19,10 +19,10 @@
#include "Logger.h"
#include "GameMessages.h"
#include "CDClientDatabase.h"
#include "MessageType/Game.h"
#include "eGameMessageType.h"
namespace GameMessageHandler {
void HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, MessageType::Game messageID);
void HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, eGameMessageType messageID);
};
#endif // GAMEMESSAGEHANDLER_H

File diff suppressed because it is too large Load Diff

View File

@@ -29,10 +29,10 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const {
stream.Write(IsOwned);
stream.Write(AccessType);
stream.Write(DateLastPublished);
stream.Write(PerformanceIndex);
stream.Write(PerformanceCost);
}
void PropertySelectQueryProperty::Deserialize(RakNet::BitStream& stream) const {
// Do we need this?
// no
}

View File

@@ -5,7 +5,8 @@
#include "Entity.h"
class PropertySelectQueryProperty final {
class PropertySelectQueryProperty final
{
public:
void Serialize(RakNet::BitStream& stream) const;
@@ -22,8 +23,9 @@ public:
bool IsAlt = false; // Whether or not the property is owned by an alt of the account owner
bool IsOwned = false; // Whether or not the property is owned
uint32_t AccessType = 0; // The privacy option of the property
uint64_t DateLastPublished = 0; // The last day the property was published
uint32_t DateLastPublished = 0; // The last day the property was published
float PerformanceCost = 0; // The performance cost of the property
uint32_t PerformanceIndex = 0; // The performance index of the property? Always 0?
};
#endif

View File

@@ -2,7 +2,7 @@
#define __REQUESTSERVERPROJECTILEIMPACT__H__
#include "dCommonVars.h"
#include "MessageType/Game.h"
#include "eGameMessageType.h"
/* Notifying the server that a locally owned projectile impacted. Sent to the caster of the projectile
should always be the local char. */
@@ -27,7 +27,7 @@ public:
}
void Serialize(RakNet::BitStream& stream) {
stream.Write(MessageType::Game::REQUEST_SERVER_PROJECTILE_IMPACT);
stream.Write(eGameMessageType::REQUEST_SERVER_PROJECTILE_IMPACT);
stream.Write(i64LocalID != LWOOBJID_EMPTY);
if (i64LocalID != LWOOBJID_EMPTY) stream.Write(i64LocalID);

View File

@@ -4,7 +4,7 @@
#include "dCommonVars.h"
#include "NiPoint3.h"
#include "NiQuaternion.h"
#include "MessageType/Game.h"
#include "eGameMessageType.h"
/**
* Same as sync skill but with different network options. An echo down to other clients that need to play the skill.
@@ -44,7 +44,7 @@ public:
}
void Serialize(RakNet::BitStream& stream) {
stream.Write(MessageType::Game::START_SKILL);
stream.Write(eGameMessageType::START_SKILL);
stream.Write(bUsedMouse);

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