Merge branch 'main' into chatpacketwhowhere

This commit is contained in:
Aaron Kimbre 2024-03-19 09:25:36 -05:00
commit 5d85b9ec2d
565 changed files with 7544 additions and 7456 deletions

View File

@ -13,7 +13,7 @@ jobs:
continue-on-error: true continue-on-error: true
strategy: strategy:
matrix: matrix:
os: [ windows-2022, ubuntu-20.04, macos-11 ] os: [ windows-2022, ubuntu-22.04, macos-13 ]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -25,9 +25,11 @@ jobs:
with: with:
vs-version: '[17,18)' vs-version: '[17,18)'
msbuild-architecture: x64 msbuild-architecture: x64
- name: Install libssl (Mac Only) - name: Install libssl and switch to XCode 15.2 (Mac Only)
if: ${{ matrix.os == 'macos-11' }} if: ${{ matrix.os == 'macos-13' }}
run: brew install openssl@3 run: |
brew install openssl@3
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
- name: cmake - name: cmake
uses: lukka/run-cmake@v10 uses: lukka/run-cmake@v10
with: with:

View File

@ -1,8 +1,11 @@
cmake_minimum_required(VERSION 3.18) cmake_minimum_required(VERSION 3.25)
project(Darkflame) project(Darkflame)
include(CTest) include(CTest)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
set(CMAKE_CXX_VISIBILITY_PRESET hidden) # Set C++ symbol visibility to default to hidden
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Read variables from file # Read variables from file
@ -76,6 +79,7 @@ endif()
# Our output dir # Our output dir
set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR}) set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR})
#set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) # unfortunately, forces all libraries to be built in series, which will slow down the build process
# TODO make this not have to override the build type directories # TODO make this not have to override the build type directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
@ -89,6 +93,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
find_package(MariaDB)
# Create a /resServer directory # Create a /resServer directory
make_directory(${CMAKE_BINARY_DIR}/resServer) make_directory(${CMAKE_BINARY_DIR}/resServer)
@ -178,7 +184,7 @@ file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip DESTINATION ${PRO
file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip) file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip)
# Copy vanity files on first build # Copy vanity files on first build
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml") set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "root.xml" "dev-tribute.xml" "atm.xml" "demo.xml")
foreach(file ${VANITY_FILES}) foreach(file ${VANITY_FILES})
configure_file("${CMAKE_SOURCE_DIR}/vanity/${file}" "${CMAKE_BINARY_DIR}/vanity/${file}" COPYONLY) configure_file("${CMAKE_SOURCE_DIR}/vanity/${file}" "${CMAKE_BINARY_DIR}/vanity/${file}" COPYONLY)
@ -201,88 +207,47 @@ foreach(file ${SQL_FILES})
configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file}) configure_file(${CMAKE_SOURCE_DIR}/migrations/cdserver/${file} ${PROJECT_BINARY_DIR}/migrations/cdserver/${file})
endforeach() endforeach()
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
if (APPLE)
include_directories("/usr/local/include/")
endif()
# Load all of our third party directories
add_subdirectory(thirdparty SYSTEM)
# Create our list of include directories # Create our list of include directories
set(INCLUDED_DIRECTORIES include_directories(
"dCommon"
"dCommon/dClient"
"dCommon/dEnums"
"dChatFilter"
"dGame"
"dGame/dBehaviors"
"dGame/dComponents"
"dGame/dGameMessages"
"dGame/dInventory"
"dGame/dMission"
"dGame/dEntity"
"dGame/dPropertyBehaviors"
"dGame/dPropertyBehaviors/ControlBehaviorMessages"
"dGame/dUtilities"
"dPhysics" "dPhysics"
"dNavigation" "dNavigation"
"dNavigation/dTerrain"
"dZoneManager"
"dDatabase"
"dDatabase/CDClientDatabase"
"dDatabase/CDClientDatabase/CDClientTables"
"dDatabase/GameDatabase"
"dDatabase/GameDatabase/ITables"
"dDatabase/GameDatabase/MySQL"
"dDatabase/GameDatabase/MySQL/Tables"
"dNet" "dNet"
"thirdparty/magic_enum/include/magic_enum"
"thirdparty/raknet/Source"
"thirdparty/tinyxml2"
"thirdparty/recastnavigation"
"thirdparty/SQLite"
"thirdparty/cpplinq"
"thirdparty/cpp-httplib"
"tests" "tests"
"tests/dCommonTests" "tests/dCommonTests"
"tests/dGameTests" "tests/dGameTests"
"tests/dGameTests/dComponentsTests" "tests/dGameTests/dComponentsTests"
SYSTEM "thirdparty/magic_enum/include/magic_enum"
SYSTEM "thirdparty/raknet/Source"
SYSTEM "thirdparty/tinyxml2"
SYSTEM "thirdparty/recastnavigation"
SYSTEM "thirdparty/SQLite"
SYSTEM "thirdparty/cpplinq"
SYSTEM "thirdparty/cpp-httplib"
SYSTEM "thirdparty/MD5"
) )
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux) # Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
# TODO: Should probably not do this.
if(APPLE) if(APPLE)
include_directories("/usr/local/include/") include_directories("/usr/local/include/")
endif() endif()
# Actually include the directories from our list
foreach(dir ${INCLUDED_DIRECTORIES})
include_directories(${PROJECT_SOURCE_DIR}/${dir})
endforeach()
if(NOT WIN32)
include_directories("${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include/bcrypt")
endif()
include_directories("${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include")
# Add linking directories: # Add linking directories:
link_directories(${PROJECT_BINARY_DIR}) if (UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast -Werror") # Warning flags
# Load all of our third party directories endif()
add_subdirectory(thirdparty)
# Glob together all headers that need to be precompiled
file(
GLOB HEADERS_DDATABASE
LIST_DIRECTORIES false
${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/*.h
${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables/*.h
${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables/*.h
${PROJECT_SOURCE_DIR}/thirdparty/SQLite/*.h
)
file( file(
GLOB HEADERS_DZONEMANAGER GLOB HEADERS_DZONEMANAGER
LIST_DIRECTORIES false LIST_DIRECTORIES false
@ -317,7 +282,7 @@ add_subdirectory(dPhysics)
add_subdirectory(dServer) add_subdirectory(dServer)
# Create a list of common libraries shared between all binaries # Create a list of common libraries shared between all binaries
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp" "magic_enum") set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "MariaDB::ConnCpp" "magic_enum")
# Add platform specific common libraries # Add platform specific common libraries
if(UNIX) if(UNIX)
@ -339,12 +304,6 @@ target_precompile_headers(
${HEADERS_DZONEMANAGER} ${HEADERS_DZONEMANAGER}
) )
# Need to specify to use the CXX compiler language here or else we get errors including <string>.
target_precompile_headers(
dDatabase PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:${HEADERS_DDATABASE}>"
)
target_precompile_headers( target_precompile_headers(
dCommon PRIVATE dCommon PRIVATE
${HEADERS_DCOMMON} ${HEADERS_DCOMMON}

View File

@ -14,13 +14,13 @@
"generator": "Unix Makefiles" "generator": "Unix Makefiles"
}, },
{ {
"name": "ci-ubuntu-20.04", "name": "ci-ubuntu-22.04",
"displayName": "CI configure step for Ubuntu", "displayName": "CI configure step for Ubuntu",
"description": "Same as default, Used in GitHub actions workflow", "description": "Same as default, Used in GitHub actions workflow",
"inherits": "default" "inherits": "default"
}, },
{ {
"name": "ci-macos-11", "name": "ci-macos-13",
"displayName": "CI configure step for MacOS", "displayName": "CI configure step for MacOS",
"description": "Same as default, Used in GitHub actions workflow", "description": "Same as default, Used in GitHub actions workflow",
"inherits": "default" "inherits": "default"
@ -67,15 +67,15 @@
"jobs": 2 "jobs": 2
}, },
{ {
"name": "ci-ubuntu-20.04", "name": "ci-ubuntu-22.04",
"configurePreset": "ci-ubuntu-20.04", "configurePreset": "ci-ubuntu-22.04",
"displayName": "Linux CI Build", "displayName": "Linux CI Build",
"description": "This preset is used by the CI build on linux", "description": "This preset is used by the CI build on linux",
"jobs": 2 "jobs": 2
}, },
{ {
"name": "ci-macos-11", "name": "ci-macos-13",
"configurePreset": "ci-macos-11", "configurePreset": "ci-macos-13",
"displayName": "MacOS CI Build", "displayName": "MacOS CI Build",
"description": "This preset is used by the CI build on MacOS", "description": "This preset is used by the CI build on MacOS",
"jobs": 2 "jobs": 2
@ -83,8 +83,8 @@
], ],
"testPresets": [ "testPresets": [
{ {
"name": "ci-ubuntu-20.04", "name": "ci-ubuntu-22.04",
"configurePreset": "ci-ubuntu-20.04", "configurePreset": "ci-ubuntu-22.04",
"displayName": "CI Tests on Linux", "displayName": "CI Tests on Linux",
"description": "Runs all tests on a linux configuration", "description": "Runs all tests on a linux configuration",
"execution": { "execution": {
@ -95,8 +95,8 @@
} }
}, },
{ {
"name": "ci-macos-11", "name": "ci-macos-13",
"configurePreset": "ci-macos-11", "configurePreset": "ci-macos-13",
"displayName": "CI Tests on MacOS", "displayName": "CI Tests on MacOS",
"description": "Runs all tests on a Mac configuration", "description": "Runs all tests on a Mac configuration",
"execution": { "execution": {

View File

@ -23,8 +23,7 @@ RUN --mount=type=cache,id=build-apt-cache,target=/var/cache/apt \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
# Grab libraries and load them # Grab libraries and load them
COPY --from=build /app/build/mariadbcpp/src/mariadb_connector_cpp-build/libmariadbcpp.so /usr/local/lib/ COPY --from=build /app/build/mariadbcpp/libmariadbcpp.so /usr/local/lib/
COPY --from=build /app/build/mariadbcpp/src/mariadb_connector_cpp-build/libmariadb/libmariadb/libmariadb.so.3 /usr/local/lib
RUN ldconfig RUN ldconfig
# Server bins # Server bins

View File

@ -51,7 +51,7 @@ git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
### Windows packages ### Windows packages
Ensure that you have either the [MSVC C++ compiler](https://visualstudio.microsoft.com/vs/features/cplusplus/) (recommended) or the [Clang compiler](https://github.com/llvm/llvm-project/releases/) installed. Ensure that you have either the [MSVC C++ compiler](https://visualstudio.microsoft.com/vs/features/cplusplus/) (recommended) or the [Clang compiler](https://github.com/llvm/llvm-project/releases/) installed.
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.18**</font> or later!). You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.25**</font> or later!).
### MacOS packages ### MacOS packages
Ensure you have [brew](https://brew.sh) installed. Ensure you have [brew](https://brew.sh) installed.
@ -356,6 +356,10 @@ The Darkflame Server is automatically built and published as a Docker Container
## Compose ## Compose
> [!WARNING]
> It seems that Docker Desktop on Windows with the WSL 2 backend has some issues with MariaDB (c.f. [mariadb-docker#331](https://github.com/MariaDB/mariadb-docker/issues/331)) triggered by NexusDashboard
> migrations, so this setup may not work for you. If that is the case, please tell us about your setup in [NexusDashboard#92](https://github.com/DarkflameUniverse/NexusDashboard/issues/92).
You can use the `docker-compose` tool to [setup a MariaDB database](#database-setup), run the Darkflame Server and manage it with [Nexus Dashboard](https://github.com/DarkflameUniverse/NexusDashboard) all You can use the `docker-compose` tool to [setup a MariaDB database](#database-setup), run the Darkflame Server and manage it with [Nexus Dashboard](https://github.com/DarkflameUniverse/NexusDashboard) all
at once. For that: at once. For that:

View File

@ -0,0 +1,17 @@
include(FetchContent)
message(STATUS "Fetching gtest...")
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(GoogleTest)
message(STATUS "gtest fetched and is now ready.")
set(GoogleTest_FOUND TRUE)

View File

@ -23,14 +23,14 @@ if(WIN32 AND NOT MARIADB_BUILD_SOURCE)
set(MARIADB_CONNECTOR_CPP_MSI "mariadb-connector-cpp-${MARIADB_CONNECTOR_CPP_VERSION}-win64.msi") set(MARIADB_CONNECTOR_CPP_MSI "mariadb-connector-cpp-${MARIADB_CONNECTOR_CPP_VERSION}-win64.msi")
if(NOT EXISTS "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_C_MSI}" ) if(NOT EXISTS "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_C_MSI}" )
message("Downloading mariadb connector/c") message(STATUS "Downloading mariadb connector/c")
file(DOWNLOAD https://dlm.mariadb.com/${MARIADB_CONNECTOR_C_BUCKET}/Connectors/c/connector-c-${MARIADB_CONNECTOR_C_VERSION}/${MARIADB_CONNECTOR_C_MSI} file(DOWNLOAD https://dlm.mariadb.com/${MARIADB_CONNECTOR_C_BUCKET}/Connectors/c/connector-c-${MARIADB_CONNECTOR_C_VERSION}/${MARIADB_CONNECTOR_C_MSI}
"${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_C_MSI}" "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_C_MSI}"
EXPECTED_HASH MD5=${MARIADB_CONNECTOR_C_MD5}) EXPECTED_HASH MD5=${MARIADB_CONNECTOR_C_MD5})
endif() endif()
if(NOT EXISTS "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_CPP_MSI}" ) if(NOT EXISTS "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_CPP_MSI}" )
message("Downloading mariadb connector/c++") message(STATUS "Downloading mariadb connector/c++")
file(DOWNLOAD https://dlm.mariadb.com/${MARIADB_CONNECTOR_CPP_BUCKET}/Connectors/cpp/connector-cpp-${MARIADB_CONNECTOR_CPP_VERSION}/${MARIADB_CONNECTOR_CPP_MSI} file(DOWNLOAD https://dlm.mariadb.com/${MARIADB_CONNECTOR_CPP_BUCKET}/Connectors/cpp/connector-cpp-${MARIADB_CONNECTOR_CPP_VERSION}/${MARIADB_CONNECTOR_CPP_MSI}
"${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_CPP_MSI}" "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_CPP_MSI}"
EXPECTED_HASH MD5=${MARIADB_CONNECTOR_CPP_MD5}) EXPECTED_HASH MD5=${MARIADB_CONNECTOR_CPP_MD5})
@ -43,27 +43,28 @@ if(WIN32 AND NOT MARIADB_BUILD_SOURCE)
file(TO_NATIVE_PATH "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_C_MSI}" MSI_DIR) file(TO_NATIVE_PATH "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_C_MSI}" MSI_DIR)
execute_process(COMMAND msiexec /a ${MSI_DIR} /qn TARGETDIR=${MSIEXEC_TARGETDIR}) execute_process(COMMAND msiexec /a ${MSI_DIR} /qn TARGETDIR=${MSIEXEC_TARGETDIR})
endif() endif()
set(MARIADBC_SHARED_LIBRARY_LOCATION "${MARIADB_C_CONNECTOR_DIR}/lib/libmariadb.dll")
if(NOT EXISTS "${MARIADB_CPP_CONNECTOR_DIR}") if(NOT EXISTS "${MARIADB_CPP_CONNECTOR_DIR}")
file(TO_NATIVE_PATH "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_CPP_MSI}" MSI_DIR) file(TO_NATIVE_PATH "${MARIADB_MSI_DIR}/${MARIADB_CONNECTOR_CPP_MSI}" MSI_DIR)
execute_process(COMMAND msiexec /a ${MSI_DIR} /qn TARGETDIR=${MSIEXEC_TARGETDIR}) execute_process(COMMAND msiexec /a ${MSI_DIR} /qn TARGETDIR=${MSIEXEC_TARGETDIR})
endif() endif()
set(MARIADB_SHARED_LIBRARY_LOCATION "${MARIADB_CPP_CONNECTOR_DIR}/mariadbcpp.dll") set(MARIADBCPP_SHARED_LIBRARY_LOCATION "${MARIADB_CPP_CONNECTOR_DIR}/mariadbcpp.dll")
set(MARIADB_IMPLIB_LOCATION "${MARIADB_CPP_CONNECTOR_DIR}/mariadbcpp.lib") set(MARIADB_IMPLIB_LOCATION "${MARIADB_CPP_CONNECTOR_DIR}/mariadbcpp.lib")
set(MARIADB_INCLUDE_DIR "${MARIADB_CPP_CONNECTOR_DIR}/include/mariadb") set(MARIADB_INCLUDE_DIR "${MARIADB_CPP_CONNECTOR_DIR}/include/mariadb")
add_custom_target(mariadb_connector_cpp) add_custom_target(mariadb_connector_cpp)
add_custom_command(TARGET mariadb_connector_cpp POST_BUILD add_custom_command(TARGET mariadb_connector_cpp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${MARIADB_CPP_CONNECTOR_DIR}/mariadbcpp.dll" "${MARIADBCPP_SHARED_LIBRARY_LOCATION}"
"${MARIADB_C_CONNECTOR_DIR}/lib/libmariadb.dll" "${MARIADBC_SHARED_LIBRARY_LOCATION}"
"${PROJECT_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, # 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. # so set this define and the servers will set the MARIADB_PLUGIN_DIR environment variable to the appropriate directory.
# Plugin directory is determined at dll load time (this will happen before main()) so we need to delay the dll load so that we can set the environment variable # Plugin directory is determined at dll load time (this will happen before main()) so we need to delay the dll load so that we can set the environment variable
add_link_options(/DELAYLOAD:${MARIADB_SHARED_LIBRARY_LOCATION}) add_link_options(/DELAYLOAD:${MARIADBCPP_SHARED_LIBRARY_LOCATION})
add_compile_definitions(MARIADB_PLUGIN_DIR_OVERRIDE="${MARIADB_CPP_CONNECTOR_DIR}/plugin") add_compile_definitions(MARIADB_PLUGIN_DIR_OVERRIDE="${MARIADB_CPP_CONNECTOR_DIR}/plugin")
else() # Build from source else() # Build from source
@ -85,77 +86,61 @@ else() # Build from source
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0) -DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0)
endif() endif()
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 ExternalProject_Add(mariadb_connector_cpp
SOURCE_DIR ${CMAKE_SOURCE_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 CMAKE_ARGS -Wno-dev
-DWITH_UNIT_TESTS=OFF
-DMARIADB_LINK_DYNAMIC=OFF
-DCMAKE_BUILD_RPATH_USE_ORIGIN=${CMAKE_BUILD_RPATH_USE_ORIGIN} -DCMAKE_BUILD_RPATH_USE_ORIGIN=${CMAKE_BUILD_RPATH_USE_ORIGIN}
-DCMAKE_INSTALL_PREFIX=./mariadbcpp # Points the connector to the correct plugin directory -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DINSTALL_PLUGINDIR=plugin -DINSTALL_LIBDIR=${MARIADBCPP_LIBRARY_DIR}
-DINSTALL_PLUGINDIR=${MARIADBCPP_PLUGIN_DIR}
${MARIADB_EXTRA_CMAKE_ARGS} ${MARIADB_EXTRA_CMAKE_ARGS}
PREFIX "${PROJECT_BINARY_DIR}/mariadbcpp" BUILD_ALWAYS true
BUILD_COMMAND cmake --build . --config RelWithDebInfo -j${MARIADB_CONNECTOR_COMPILE_JOBS} )
INSTALL_COMMAND "")
ExternalProject_Get_Property(mariadb_connector_cpp BINARY_DIR)
if(WIN32) if(WIN32)
set(MARIADB_SHARED_LIBRARY_NAME mariadbcpp.dll) set(MARIADB_SHARED_LIBRARY_NAME mariadbcpp.dll)
set(MARIADB_PLUGIN_SUFFIX .dll) set(MARIADB_PLUGIN_SUFFIX .dll)
set(MARIADB_IMPLIB_LOCATION "${BINARY_DIR}/RelWithDebInfo/mariadbcpp.lib") set(MARIADB_IMPLIB_LOCATION "${MARIADBCPP_LIBRARY_DIR}/mariadbcpp.lib")
# When built from source windows only seems to check same folder as exe instead specified folder, so use # When built from source windows only seems to check same folder as exe instead specified folder, so use
# environment variable to force it # environment variable to force it
add_link_options(/DELAYLOAD:mariadbcpp.dll) add_link_options(/DELAYLOAD:mariadbcpp.dll)
add_compile_definitions(MARIADB_PLUGIN_DIR_OVERRIDE="${PROJECT_BINARY_DIR}/mariadbcpp/plugin") add_compile_definitions(MARIADB_PLUGIN_DIR_OVERRIDE="${MARIADBCPP_PLUGIN_DIR}")
else() else()
set(MARIADB_SHARED_LIBRARY_NAME libmariadbcpp${CMAKE_SHARED_LIBRARY_SUFFIX}) set(MARIADB_SHARED_LIBRARY_NAME libmariadbcpp${CMAKE_SHARED_LIBRARY_SUFFIX})
set(MARIADB_PLUGIN_SUFFIX .so) set(MARIADB_PLUGIN_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
endif() endif()
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) set(MARIADBCPP_SHARED_LIBRARY_LOCATION "${MARIADBCPP_LIBRARY_DIR}/${MARIADB_SHARED_LIBRARY_NAME}")
if(isMultiConfig) if(WIN32)
set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/RelWithDebInfo/${MARIADB_SHARED_LIBRARY_NAME}") set(MARIADBC_SHARED_LIBRARY_LOCATION "${MARIADBCPP_LIBRARY_DIR}/libmariadb.lib")
set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}/$<CONFIG>")
set(MARIADB_PLUGINS_LOCATION "${BINARY_DIR}/libmariadb/RelWithDebInfo")
else()
set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/${MARIADB_SHARED_LIBRARY_NAME}")
set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}")
set(MARIADB_PLUGINS_LOCATION "${BINARY_DIR}/libmariadb")
endif() endif()
set(MARIADB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/include/")
add_custom_command(TARGET mariadb_connector_cpp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
${BINARY_DIR}/mariadbcpp/plugin
${MARIADB_SHARED_LIBRARY_COPY_LOCATION}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${MARIADB_SHARED_LIBRARY_LOCATION}
${MARIADB_SHARED_LIBRARY_COPY_LOCATION}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${MARIADB_PLUGINS_LOCATION}/caching_sha2_password${MARIADB_PLUGIN_SUFFIX}
${MARIADB_PLUGINS_LOCATION}/client_ed25519${MARIADB_PLUGIN_SUFFIX}
${MARIADB_PLUGINS_LOCATION}/dialog${MARIADB_PLUGIN_SUFFIX}
${MARIADB_PLUGINS_LOCATION}/mysql_clear_password${MARIADB_PLUGIN_SUFFIX}
${MARIADB_PLUGINS_LOCATION}/sha256_password${MARIADB_PLUGIN_SUFFIX}
${BINARY_DIR}/mariadbcpp/plugin)
endif()
# Remove the CMakeLists.txt file from the tests folder for the maria-db-connector so we dont compile the tests.
if(EXISTS "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/test/CMakeLists.txt")
file(REMOVE "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/test/CMakeLists.txt")
endif() endif()
# Create mariadb connector library object # Create mariadb connector library object
add_library(mariadbConnCpp SHARED IMPORTED GLOBAL) add_library(MariaDB::ConnCpp SHARED IMPORTED GLOBAL)
set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_LOCATION ${MARIADB_SHARED_LIBRARY_LOCATION}) add_dependencies(MariaDB::ConnCpp mariadb_connector_cpp)
set_target_properties(MariaDB::ConnCpp PROPERTIES
IMPORTED_LOCATION "${MARIADBCPP_SHARED_LIBRARY_LOCATION}")
if(WIN32) if(WIN32)
set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_IMPLIB ${MARIADB_IMPLIB_LOCATION}) set_target_properties(MariaDB::ConnCpp PROPERTIES
IMPORTED_IMPLIB "${MARIADB_IMPLIB_LOCATION}")
elseif(APPLE)
set_target_properties(MariaDB::ConnCpp PROPERTIES
IMPORTED_SONAME "libmariadbcpp")
endif() endif()
# Add directories to include lists # Add directories to include lists
target_include_directories(mariadbConnCpp INTERFACE ${MARIADB_INCLUDE_DIR}) target_include_directories(MariaDB::ConnCpp SYSTEM INTERFACE ${MARIADB_INCLUDE_DIR})
add_dependencies(mariadbConnCpp mariadb_connector_cpp)
set(MariaDB_FOUND TRUE)

View File

@ -82,11 +82,11 @@ int main(int argc, char** argv) {
Game::randomEngine = std::mt19937(time(0)); Game::randomEngine = std::mt19937(time(0));
//It's safe to pass 'localhost' here, as the IP is only used as the external IP. //It's safe to pass 'localhost' here, as the IP is only used as the external IP.
uint32_t maxClients = 999;
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
std::string ourIP = "localhost"; std::string ourIP = "localhost";
GeneralUtils::TryParse(Game::config->GetValue("max_clients"), maxClients); const uint32_t maxClients = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_clients")).value_or(999);
GeneralUtils::TryParse(Game::config->GetValue("auth_server_port"), ourPort);
//LU client is hardcoded to use this for auth port, so I'm making it the default.
const uint32_t ourPort = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("auth_server_port")).value_or(1001);
const auto externalIPString = Game::config->GetValue("external_ip"); const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString; if (!externalIPString.empty()) ourIP = externalIPString;

View File

@ -5,10 +5,12 @@ set(DCHATSERVER_SOURCES
) )
add_executable(ChatServer "ChatServer.cpp") add_executable(ChatServer "ChatServer.cpp")
add_library(dChatServer ${DCHATSERVER_SOURCES}) target_include_directories(ChatServer PRIVATE "${PROJECT_SOURCE_DIR}/dChatFilter")
target_include_directories(dChatServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"") add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
add_library(dChatServer ${DCHATSERVER_SOURCES})
target_include_directories(dChatServer PRIVATE "${PROJECT_SOURCE_DIR}/dServer")
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter) target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer) target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer)

View File

@ -59,7 +59,7 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
bitStream.Write(LUWString(ignoredPlayer.playerName, 36)); bitStream.Write(LUWString(ignoredPlayer.playerName, 36));
} }
Game::server->Send(&bitStream, packet->systemAddress, false); Game::server->Send(bitStream, packet->systemAddress, false);
} }
void ChatIgnoreList::AddIgnore(Packet* packet) { void ChatIgnoreList::AddIgnore(Packet* packet) {
@ -131,7 +131,7 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
bitStream.Write(playerNameSend); bitStream.Write(playerNameSend);
bitStream.Write(ignoredPlayerId); bitStream.Write(ignoredPlayerId);
Game::server->Send(&bitStream, packet->systemAddress, false); Game::server->Send(bitStream, packet->systemAddress, false);
} }
void ChatIgnoreList::RemoveIgnore(Packet* packet) { void ChatIgnoreList::RemoveIgnore(Packet* packet) {
@ -167,5 +167,5 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
LUWString playerNameSend(removedIgnoreStr, 33); LUWString playerNameSend(removedIgnoreStr, 33);
bitStream.Write(playerNameSend); bitStream.Write(playerNameSend);
Game::server->Send(&bitStream, packet->systemAddress, false); Game::server->Send(bitStream, packet->systemAddress, false);
} }

View File

@ -98,18 +98,15 @@ int main(int argc, char** argv) {
masterPort = masterInfo->port; masterPort = masterInfo->port;
} }
//It's safe to pass 'localhost' here, as the IP is only used as the external IP. //It's safe to pass 'localhost' here, as the IP is only used as the external IP.
uint32_t maxClients = 999;
uint32_t ourPort = 1501;
std::string ourIP = "localhost"; std::string ourIP = "localhost";
GeneralUtils::TryParse(Game::config->GetValue("max_clients"), maxClients); const uint32_t maxClients = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_clients")).value_or(999);
GeneralUtils::TryParse(Game::config->GetValue("chat_server_port"), ourPort); const uint32_t ourPort = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("chat_server_port")).value_or(2005);
const auto externalIPString = Game::config->GetValue("external_ip"); const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString; if (!externalIPString.empty()) ourIP = externalIPString;
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal); Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal);
bool dontGenerateDCF = false; const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
GeneralUtils::TryParse(Game::config->GetValue("dont_generate_dcf"), dontGenerateDCF);
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF); Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
Game::randomEngine = std::mt19937(time(0)); Game::randomEngine = std::mt19937(time(0));
@ -210,7 +207,6 @@ void HandlePacket(Packet* packet) {
// verif internal // verif internal
Game::playerContainer.CreateTeamServer(packet); Game::playerContainer.CreateTeamServer(packet);
break; break;
case eChatMessageType::GET_FRIENDS_LIST: case eChatMessageType::GET_FRIENDS_LIST:
ChatPacketHandler::HandleFriendlistRequest(packet); ChatPacketHandler::HandleFriendlistRequest(packet);
break; break;

View File

@ -14,16 +14,10 @@
#include "dConfig.h" #include "dConfig.h"
void PlayerContainer::Initialize() { void PlayerContainer::Initialize() {
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends"), m_MaxNumberOfBestFriends); m_MaxNumberOfBestFriends =
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_friends"), m_MaxNumberOfFriends); GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends")).value_or(m_MaxNumberOfBestFriends);
} m_MaxNumberOfFriends =
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_friends")).value_or(m_MaxNumberOfFriends);
PlayerContainer::~PlayerContainer() {
m_Players.clear();
}
PlayerData::PlayerData() {
gmLevel == eGameMasterLevel::CIVILIAN;
} }
TeamData::TeamData() { TeamData::TeamData() {
@ -158,7 +152,7 @@ void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
bitStream.Write(player); bitStream.Write(player);
bitStream.Write(time); bitStream.Write(time);
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
} }
TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members) { TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
@ -369,7 +363,7 @@ void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
} }
} }
Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
} }
std::u16string PlayerContainer::GetName(LWOOBJID playerID) { std::u16string PlayerContainer::GetName(LWOOBJID playerID) {

View File

@ -10,7 +10,7 @@
enum class eGameMasterLevel : uint8_t; enum class eGameMasterLevel : uint8_t;
struct IgnoreData { struct IgnoreData {
IgnoreData(const std::string& name, const LWOOBJID& id) : playerName(name), playerId(id) {} IgnoreData(const std::string& name, const LWOOBJID& id) : playerName{ name }, playerId{ id } {}
inline bool operator==(const std::string& other) const noexcept { inline bool operator==(const std::string& other) const noexcept {
return playerName == other; return playerName == other;
} }
@ -24,7 +24,6 @@ struct IgnoreData {
}; };
struct PlayerData { struct PlayerData {
PlayerData();
operator bool() const noexcept { operator bool() const noexcept {
return playerID != LWOOBJID_EMPTY; return playerID != LWOOBJID_EMPTY;
} }
@ -45,7 +44,7 @@ struct PlayerData {
std::string playerName; std::string playerName;
std::vector<FriendData> friends; std::vector<FriendData> friends;
std::vector<IgnoreData> ignoredPlayers; std::vector<IgnoreData> ignoredPlayers;
eGameMasterLevel gmLevel; eGameMasterLevel gmLevel = static_cast<eGameMasterLevel>(0); // CIVILLIAN
bool isFTP = false; bool isFTP = false;
}; };
@ -61,8 +60,6 @@ struct TeamData {
class PlayerContainer { class PlayerContainer {
public: public:
~PlayerContainer();
void Initialize(); void Initialize();
void InsertPlayer(Packet* packet); void InsertPlayer(Packet* packet);
void RemovePlayer(Packet* packet); void RemovePlayer(Packet* packet);

View File

@ -9,12 +9,11 @@
* AMF3 Deserializer written by EmosewaMC * AMF3 Deserializer written by EmosewaMC
*/ */
AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream* inStream) { AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream& inStream) {
if (!inStream) return nullptr;
AMFBaseValue* returnValue = nullptr; AMFBaseValue* returnValue = nullptr;
// Read in the value type from the bitStream // Read in the value type from the bitStream
eAmf marker; eAmf marker;
inStream->Read(marker); inStream.Read(marker);
// Based on the typing, create the value associated with that and return the base value class // Based on the typing, create the value associated with that and return the base value class
switch (marker) { switch (marker) {
case eAmf::Undefined: { case eAmf::Undefined: {
@ -79,13 +78,13 @@ AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream* inStream) {
return returnValue; return returnValue;
} }
uint32_t AMFDeserialize::ReadU29(RakNet::BitStream* inStream) { uint32_t AMFDeserialize::ReadU29(RakNet::BitStream& inStream) {
bool byteFlag = true; bool byteFlag = true;
uint32_t actualNumber{}; uint32_t actualNumber{};
uint8_t numberOfBytesRead{}; uint8_t numberOfBytesRead{};
while (byteFlag && numberOfBytesRead < 4) { while (byteFlag && numberOfBytesRead < 4) {
uint8_t byte{}; uint8_t byte{};
inStream->Read(byte); inStream.Read(byte);
// Parse the byte // Parse the byte
if (numberOfBytesRead < 3) { if (numberOfBytesRead < 3) {
byteFlag = byte & static_cast<uint8_t>(1 << 7); byteFlag = byte & static_cast<uint8_t>(1 << 7);
@ -101,7 +100,7 @@ uint32_t AMFDeserialize::ReadU29(RakNet::BitStream* inStream) {
return actualNumber; return actualNumber;
} }
const std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) { const std::string AMFDeserialize::ReadString(RakNet::BitStream& inStream) {
auto length = ReadU29(inStream); auto length = ReadU29(inStream);
// Check if this is a reference // Check if this is a reference
bool isReference = length % 2 == 1; bool isReference = length % 2 == 1;
@ -109,7 +108,7 @@ const std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
length = length >> 1; length = length >> 1;
if (isReference) { if (isReference) {
std::string value(length, 0); std::string value(length, 0);
inStream->Read(&value[0], length); inStream.Read(&value[0], length);
// Empty strings are never sent by reference // Empty strings are never sent by reference
if (!value.empty()) accessedElements.push_back(value); if (!value.empty()) accessedElements.push_back(value);
return value; return value;
@ -119,20 +118,20 @@ const std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
} }
} }
AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) { AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) {
double value; double value;
inStream->Read<double>(value); inStream.Read<double>(value);
return new AMFDoubleValue(value); return new AMFDoubleValue(value);
} }
AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) { AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) {
auto arrayValue = new AMFArrayValue(); auto arrayValue = new AMFArrayValue();
// Read size of dense array // Read size of dense array
auto sizeOfDenseArray = (ReadU29(inStream) >> 1); const auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
// Then read associative portion // Then read associative portion
while (true) { while (true) {
auto key = ReadString(inStream); const auto key = ReadString(inStream);
// No more associative values when we encounter an empty string key // No more associative values when we encounter an empty string key
if (key.size() == 0) break; if (key.size() == 0) break;
arrayValue->Insert(key, Read(inStream)); arrayValue->Insert(key, Read(inStream));
@ -144,10 +143,10 @@ AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) {
return arrayValue; return arrayValue;
} }
AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) { AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) {
return new AMFStringValue(ReadString(inStream)); return new AMFStringValue(ReadString(inStream));
} }
AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) { AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) {
return new AMFIntValue(ReadU29(inStream)); return new AMFIntValue(ReadU29(inStream));
} }

View File

@ -15,7 +15,7 @@ public:
* @param inStream inStream to read value from. * @param inStream inStream to read value from.
* @return Returns an AMFValue with all the information from the bitStream in it. * @return Returns an AMFValue with all the information from the bitStream in it.
*/ */
AMFBaseValue* Read(RakNet::BitStream* inStream); AMFBaseValue* Read(RakNet::BitStream& inStream);
private: private:
/** /**
* @brief Private method to read a U29 integer from a bitstream * @brief Private method to read a U29 integer from a bitstream
@ -23,7 +23,7 @@ private:
* @param inStream bitstream to read data from * @param inStream bitstream to read data from
* @return The number as an unsigned 29 bit integer * @return The number as an unsigned 29 bit integer
*/ */
uint32_t ReadU29(RakNet::BitStream* inStream); static uint32_t ReadU29(RakNet::BitStream& inStream);
/** /**
* @brief Reads a string from a bitstream * @brief Reads a string from a bitstream
@ -31,7 +31,7 @@ private:
* @param inStream bitStream to read data from * @param inStream bitStream to read data from
* @return The read string * @return The read string
*/ */
const std::string ReadString(RakNet::BitStream* inStream); const std::string ReadString(RakNet::BitStream& inStream);
/** /**
* @brief Read an AMFDouble value from a bitStream * @brief Read an AMFDouble value from a bitStream
@ -39,7 +39,7 @@ private:
* @param inStream bitStream to read data from * @param inStream bitStream to read data from
* @return Double value represented as an AMFValue * @return Double value represented as an AMFValue
*/ */
AMFBaseValue* ReadAmfDouble(RakNet::BitStream* inStream); AMFBaseValue* ReadAmfDouble(RakNet::BitStream& inStream);
/** /**
* @brief Read an AMFArray from a bitStream * @brief Read an AMFArray from a bitStream
@ -47,7 +47,7 @@ private:
* @param inStream bitStream to read data from * @param inStream bitStream to read data from
* @return Array value represented as an AMFValue * @return Array value represented as an AMFValue
*/ */
AMFBaseValue* ReadAmfArray(RakNet::BitStream* inStream); AMFBaseValue* ReadAmfArray(RakNet::BitStream& inStream);
/** /**
* @brief Read an AMFString from a bitStream * @brief Read an AMFString from a bitStream
@ -55,7 +55,7 @@ private:
* @param inStream bitStream to read data from * @param inStream bitStream to read data from
* @return String value represented as an AMFValue * @return String value represented as an AMFValue
*/ */
AMFBaseValue* ReadAmfString(RakNet::BitStream* inStream); AMFBaseValue* ReadAmfString(RakNet::BitStream& inStream);
/** /**
* @brief Read an AMFInteger from a bitStream * @brief Read an AMFInteger from a bitStream
@ -63,7 +63,7 @@ private:
* @param inStream bitStream to read data from * @param inStream bitStream to read data from
* @return Integer value represented as an AMFValue * @return Integer value represented as an AMFValue
*/ */
AMFBaseValue* ReadAmfInteger(RakNet::BitStream* inStream); AMFBaseValue* ReadAmfInteger(RakNet::BitStream& inStream);
/** /**
* List of strings read so far saved to be read by reference. * List of strings read so far saved to be read by reference.

View File

@ -31,54 +31,70 @@ enum class eAmf : uint8_t {
class AMFBaseValue { class AMFBaseValue {
public: public:
virtual eAmf GetValueType() { return eAmf::Undefined; }; [[nodiscard]] constexpr virtual eAmf GetValueType() const noexcept { return eAmf::Undefined; }
AMFBaseValue() {}; constexpr AMFBaseValue() noexcept = default;
virtual ~AMFBaseValue() {}; constexpr virtual ~AMFBaseValue() noexcept = default;
}; };
template<typename ValueType> // AMFValue template class instantiations
template <typename ValueType>
class AMFValue : public AMFBaseValue { class AMFValue : public AMFBaseValue {
public: public:
AMFValue() {}; AMFValue() = default;
AMFValue(ValueType value) { SetValue(value); }; AMFValue(const ValueType value) : m_Data{ value } {}
virtual ~AMFValue() override {};
eAmf GetValueType() override { return eAmf::Undefined; }; virtual ~AMFValue() override = default;
[[nodiscard]] constexpr eAmf GetValueType() const noexcept override;
[[nodiscard]] const ValueType& GetValue() const { return m_Data; }
void SetValue(const ValueType value) { m_Data = value; }
const ValueType& GetValue() { return data; };
void SetValue(ValueType value) { data = value; };
protected: protected:
ValueType data; ValueType m_Data;
}; };
// Explicit template class instantiations
template class AMFValue<std::nullptr_t>;
template class AMFValue<bool>;
template class AMFValue<int32_t>;
template class AMFValue<uint32_t>;
template class AMFValue<std::string>;
template class AMFValue<double>;
// AMFValue template class member function instantiations
template <> [[nodiscard]] constexpr eAmf AMFValue<std::nullptr_t>::GetValueType() const noexcept { return eAmf::Null; }
template <> [[nodiscard]] constexpr eAmf AMFValue<bool>::GetValueType() const noexcept { return m_Data ? eAmf::True : eAmf::False; }
template <> [[nodiscard]] constexpr eAmf AMFValue<int32_t>::GetValueType() const noexcept { return eAmf::Integer; }
template <> [[nodiscard]] constexpr eAmf AMFValue<uint32_t>::GetValueType() const noexcept { return eAmf::Integer; }
template <> [[nodiscard]] constexpr eAmf AMFValue<std::string>::GetValueType() const noexcept { return eAmf::String; }
template <> [[nodiscard]] constexpr eAmf AMFValue<double>::GetValueType() const noexcept { return eAmf::Double; }
template <typename ValueType>
[[nodiscard]] constexpr eAmf AMFValue<ValueType>::GetValueType() const noexcept { return eAmf::Undefined; }
// As a string this is much easier to write and read from a BitStream. // As a string this is much easier to write and read from a BitStream.
template<> template <>
class AMFValue<const char*> : public AMFBaseValue { class AMFValue<const char*> : public AMFBaseValue {
public: public:
AMFValue() {}; AMFValue() = default;
AMFValue(const char* value) { SetValue(std::string(value)); }; AMFValue(const char* value) { m_Data = value; }
virtual ~AMFValue() override {}; virtual ~AMFValue() override = default;
eAmf GetValueType() override { return eAmf::String; }; [[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::String; }
const std::string& GetValue() { return data; }; [[nodiscard]] const std::string& GetValue() const { return m_Data; }
void SetValue(std::string value) { data = value; }; void SetValue(const std::string& value) { m_Data = value; }
protected: protected:
std::string data; std::string m_Data;
}; };
typedef AMFValue<std::nullptr_t> AMFNullValue; using AMFNullValue = AMFValue<std::nullptr_t>;
typedef AMFValue<bool> AMFBoolValue; using AMFBoolValue = AMFValue<bool>;
typedef AMFValue<int32_t> AMFIntValue; using AMFIntValue = AMFValue<int32_t>;
typedef AMFValue<std::string> AMFStringValue; using AMFStringValue = AMFValue<std::string>;
typedef AMFValue<double> AMFDoubleValue; using AMFDoubleValue = AMFValue<double>;
template<> inline eAmf AMFValue<std::nullptr_t>::GetValueType() { return eAmf::Null; };
template<> inline eAmf AMFValue<bool>::GetValueType() { return this->data ? eAmf::True : eAmf::False; };
template<> inline eAmf AMFValue<int32_t>::GetValueType() { return eAmf::Integer; };
template<> inline eAmf AMFValue<uint32_t>::GetValueType() { return eAmf::Integer; };
template<> inline eAmf AMFValue<std::string>::GetValueType() { return eAmf::String; };
template<> inline eAmf AMFValue<double>::GetValueType() { return eAmf::Double; };
/** /**
* The AMFArrayValue object holds 2 types of lists: * The AMFArrayValue object holds 2 types of lists:
@ -89,15 +105,14 @@ template<> inline eAmf AMFValue<double>::GetValueType() { return eAmf::Double; }
* and are not to be deleted by a caller. * and are not to be deleted by a caller.
*/ */
class AMFArrayValue : public AMFBaseValue { class AMFArrayValue : public AMFBaseValue {
using AMFAssociative = std::unordered_map<std::string, AMFBaseValue*>;
typedef std::unordered_map<std::string, AMFBaseValue*> AMFAssociative; using AMFDense = std::vector<AMFBaseValue*>;
typedef std::vector<AMFBaseValue*> AMFDense;
public: public:
eAmf GetValueType() override { return eAmf::Array; }; [[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::Array; }
~AMFArrayValue() override { ~AMFArrayValue() override {
for (auto valueToDelete : GetDense()) { for (const auto* valueToDelete : GetDense()) {
if (valueToDelete) { if (valueToDelete) {
delete valueToDelete; delete valueToDelete;
valueToDelete = nullptr; valueToDelete = nullptr;
@ -109,17 +124,17 @@ public:
valueToDelete.second = nullptr; valueToDelete.second = nullptr;
} }
} }
}; }
/** /**
* Returns the Associative portion of the object * Returns the Associative portion of the object
*/ */
inline AMFAssociative& GetAssociative() { return this->associative; }; [[nodiscard]] inline const AMFAssociative& GetAssociative() const noexcept { return m_Associative; }
/** /**
* Returns the dense portion of the object * Returns the dense portion of the object
*/ */
inline AMFDense& GetDense() { return this->dense; }; [[nodiscard]] inline const AMFDense& GetDense() const noexcept { return m_Dense; }
/** /**
* Inserts an AMFValue into the associative portion with the given key. * Inserts an AMFValue into the associative portion with the given key.
@ -135,48 +150,48 @@ public:
* @return The inserted element if the type matched, * @return The inserted element if the type matched,
* or nullptr if a key existed and was not the same type * or nullptr if a key existed and was not the same type
*/ */
template<typename ValueType> template <typename ValueType>
std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, ValueType value) { [[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, const ValueType value) {
auto element = associative.find(key); const auto element = m_Associative.find(key);
AMFValue<ValueType>* val = nullptr; AMFValue<ValueType>* val = nullptr;
bool found = true; bool found = true;
if (element == associative.end()) { if (element == m_Associative.cend()) {
val = new AMFValue<ValueType>(value); val = new AMFValue<ValueType>(value);
associative.insert(std::make_pair(key, val)); m_Associative.emplace(key, val);
} else { } else {
val = dynamic_cast<AMFValue<ValueType>*>(element->second); val = dynamic_cast<AMFValue<ValueType>*>(element->second);
found = false; found = false;
} }
return std::make_pair(val, found); return std::make_pair(val, found);
}; }
// Associates an array with a string key // Associates an array with a string key
std::pair<AMFBaseValue*, bool> Insert(const std::string& key) { [[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
auto element = associative.find(key); const auto element = m_Associative.find(key);
AMFArrayValue* val = nullptr; AMFArrayValue* val = nullptr;
bool found = true; bool found = true;
if (element == associative.end()) { if (element == m_Associative.cend()) {
val = new AMFArrayValue(); val = new AMFArrayValue();
associative.insert(std::make_pair(key, val)); m_Associative.emplace(key, val);
} else { } else {
val = dynamic_cast<AMFArrayValue*>(element->second); val = dynamic_cast<AMFArrayValue*>(element->second);
found = false; found = false;
} }
return std::make_pair(val, found); return std::make_pair(val, found);
}; }
// Associates an array with an integer key // Associates an array with an integer key
std::pair<AMFBaseValue*, bool> Insert(const uint32_t& index) { [[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const size_t index) {
AMFArrayValue* val = nullptr; AMFArrayValue* val = nullptr;
bool inserted = false; bool inserted = false;
if (index >= dense.size()) { if (index >= m_Dense.size()) {
dense.resize(index + 1); m_Dense.resize(index + 1);
val = new AMFArrayValue(); val = new AMFArrayValue();
dense.at(index) = val; m_Dense.at(index) = val;
inserted = true; inserted = true;
} }
return std::make_pair(dynamic_cast<AMFArrayValue*>(dense.at(index)), inserted); return std::make_pair(dynamic_cast<AMFArrayValue*>(m_Dense.at(index)), inserted);
}; }
/** /**
* @brief Inserts an AMFValue into the AMFArray key'd by index. * @brief Inserts an AMFValue into the AMFArray key'd by index.
@ -188,18 +203,18 @@ public:
* @return The inserted element, or nullptr if the type did not match * @return The inserted element, or nullptr if the type did not match
* what was at the index. * what was at the index.
*/ */
template<typename ValueType> template <typename ValueType>
std::pair<AMFValue<ValueType>*, bool> Insert(const uint32_t& index, ValueType value) { [[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const size_t index, const ValueType value) {
AMFValue<ValueType>* val = nullptr; AMFValue<ValueType>* val = nullptr;
bool inserted = false; bool inserted = false;
if (index >= this->dense.size()) { if (index >= m_Dense.size()) {
this->dense.resize(index + 1); m_Dense.resize(index + 1);
val = new AMFValue<ValueType>(value); val = new AMFValue<ValueType>(value);
this->dense.at(index) = val; m_Dense.at(index) = val;
inserted = true; inserted = true;
} }
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(this->dense.at(index)), inserted); return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(m_Dense.at(index)), inserted);
}; }
/** /**
* Inserts an AMFValue into the associative portion with the given key. * Inserts an AMFValue into the associative portion with the given key.
@ -210,15 +225,15 @@ public:
* @param key The key to associate with the value * @param key The key to associate with the value
* @param value The value to insert * @param value The value to insert
*/ */
void Insert(const std::string& key, AMFBaseValue* value) { void Insert(const std::string& key, AMFBaseValue* const value) {
auto element = associative.find(key); const auto element = m_Associative.find(key);
if (element != associative.end() && element->second) { if (element != m_Associative.cend() && element->second) {
delete element->second; delete element->second;
element->second = value; element->second = value;
} else { } else {
associative.insert(std::make_pair(key, value)); m_Associative.emplace(key, value);
}
} }
};
/** /**
* Inserts an AMFValue into the associative portion with the given index. * Inserts an AMFValue into the associative portion with the given index.
@ -229,15 +244,15 @@ public:
* @param key The key to associate with the value * @param key The key to associate with the value
* @param value The value to insert * @param value The value to insert
*/ */
void Insert(const uint32_t index, AMFBaseValue* value) { void Insert(const size_t index, AMFBaseValue* const value) {
if (index < dense.size()) { if (index < m_Dense.size()) {
AMFDense::iterator itr = dense.begin() + index; const AMFDense::const_iterator itr = m_Dense.cbegin() + index;
if (*itr) delete dense.at(index); if (*itr) delete m_Dense.at(index);
} else { } else {
dense.resize(index + 1); m_Dense.resize(index + 1);
}
m_Dense.at(index) = value;
} }
dense.at(index) = value;
};
/** /**
* Pushes an AMFValue into the back of the dense portion. * Pushes an AMFValue into the back of the dense portion.
@ -249,10 +264,10 @@ public:
* *
* @return The inserted pointer, or nullptr should the key already be in use. * @return The inserted pointer, or nullptr should the key already be in use.
*/ */
template<typename ValueType> template <typename ValueType>
inline AMFValue<ValueType>* Push(ValueType value) { [[maybe_unused]] inline AMFValue<ValueType>* Push(const ValueType value) {
return Insert(this->dense.size(), value).first; return Insert(m_Dense.size(), value).first;
}; }
/** /**
* Removes the key from the associative portion * Removes the key from the associative portion
@ -261,52 +276,49 @@ public:
* *
* @param key The key to remove from the associative portion * @param key The key to remove from the associative portion
*/ */
void Remove(const std::string& key, bool deleteValue = true) { void Remove(const std::string& key, const bool deleteValue = true) {
AMFAssociative::iterator it = this->associative.find(key); const AMFAssociative::const_iterator it = m_Associative.find(key);
if (it != this->associative.end()) { if (it != m_Associative.cend()) {
if (deleteValue) delete it->second; if (deleteValue) delete it->second;
this->associative.erase(it); m_Associative.erase(it);
} }
} }
/** /**
* Pops the last element in the dense portion, deleting it in the process. * Pops the last element in the dense portion, deleting it in the process.
*/ */
void Remove(const uint32_t index) { void Remove(const size_t index) {
if (!this->dense.empty() && index < this->dense.size()) { if (!m_Dense.empty() && index < m_Dense.size()) {
auto itr = this->dense.begin() + index; const auto itr = m_Dense.cbegin() + index;
if (*itr) delete (*itr); if (*itr) delete (*itr);
this->dense.erase(itr); m_Dense.erase(itr);
} }
} }
void Pop() { void Pop() {
if (!this->dense.empty()) Remove(this->dense.size() - 1); if (!m_Dense.empty()) Remove(m_Dense.size() - 1);
} }
AMFArrayValue* GetArray(const std::string& key) { [[nodiscard]] AMFArrayValue* GetArray(const std::string& key) const {
AMFAssociative::const_iterator it = this->associative.find(key); const AMFAssociative::const_iterator it = m_Associative.find(key);
if (it != this->associative.end()) { return it != m_Associative.cend() ? dynamic_cast<AMFArrayValue*>(it->second) : nullptr;
return dynamic_cast<AMFArrayValue*>(it->second);
} }
return nullptr;
};
AMFArrayValue* GetArray(const uint32_t index) { [[nodiscard]] AMFArrayValue* GetArray(const size_t index) const {
return index >= this->dense.size() ? nullptr : dynamic_cast<AMFArrayValue*>(this->dense.at(index)); return index < m_Dense.size() ? dynamic_cast<AMFArrayValue*>(m_Dense.at(index)) : nullptr;
}; }
inline AMFArrayValue* InsertArray(const std::string& key) { [[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string& key) {
return static_cast<AMFArrayValue*>(Insert(key).first); return static_cast<AMFArrayValue*>(Insert(key).first);
}; }
inline AMFArrayValue* InsertArray(const uint32_t index) { [[maybe_unused]] inline AMFArrayValue* InsertArray(const size_t index) {
return static_cast<AMFArrayValue*>(Insert(index).first); return static_cast<AMFArrayValue*>(Insert(index).first);
}; }
inline AMFArrayValue* PushArray() { [[maybe_unused]] inline AMFArrayValue* PushArray() {
return static_cast<AMFArrayValue*>(Insert(this->dense.size()).first); return static_cast<AMFArrayValue*>(Insert(m_Dense.size()).first);
}; }
/** /**
* Gets an AMFValue by the key from the associative portion and converts it * Gets an AMFValue by the key from the associative portion and converts it
@ -318,18 +330,18 @@ public:
* @return The AMFValue * @return The AMFValue
*/ */
template <typename AmfType> template <typename AmfType>
AMFValue<AmfType>* Get(const std::string& key) const { [[nodiscard]] AMFValue<AmfType>* Get(const std::string& key) const {
AMFAssociative::const_iterator it = this->associative.find(key); const AMFAssociative::const_iterator it = m_Associative.find(key);
return it != this->associative.end() ? return it != m_Associative.cend() ?
dynamic_cast<AMFValue<AmfType>*>(it->second) : dynamic_cast<AMFValue<AmfType>*>(it->second) :
nullptr; nullptr;
}; }
// Get from the array but dont cast it // Get from the array but dont cast it
AMFBaseValue* Get(const std::string& key) const { [[nodiscard]] AMFBaseValue* Get(const std::string& key) const {
AMFAssociative::const_iterator it = this->associative.find(key); const AMFAssociative::const_iterator it = m_Associative.find(key);
return it != this->associative.end() ? it->second : nullptr; return it != m_Associative.cend() ? it->second : nullptr;
}; }
/** /**
* @brief Get an AMFValue object at a position in the dense portion. * @brief Get an AMFValue object at a position in the dense portion.
@ -341,27 +353,28 @@ public:
* @return The casted object, or nullptr. * @return The casted object, or nullptr.
*/ */
template <typename AmfType> template <typename AmfType>
AMFValue<AmfType>* Get(uint32_t index) const { [[nodiscard]] AMFValue<AmfType>* Get(const size_t index) const {
return index < this->dense.size() ? return index < m_Dense.size() ?
dynamic_cast<AMFValue<AmfType>*>(this->dense.at(index)) : dynamic_cast<AMFValue<AmfType>*>(m_Dense.at(index)) :
nullptr; nullptr;
}; }
// Get from the dense but dont cast it // Get from the dense but dont cast it
AMFBaseValue* Get(const uint32_t index) const { [[nodiscard]] AMFBaseValue* Get(const size_t index) const {
return index < this->dense.size() ? this->dense.at(index) : nullptr; return index < m_Dense.size() ? m_Dense.at(index) : nullptr;
}; }
private: private:
/** /**
* The associative portion. These values are key'd with strings to an AMFValue. * The associative portion. These values are key'd with strings to an AMFValue.
*/ */
AMFAssociative associative; AMFAssociative m_Associative;
/** /**
* The dense portion. These AMFValue's are stored one after * The dense portion. These AMFValue's are stored one after
* another with the most recent addition being at the back. * another with the most recent addition being at the back.
*/ */
AMFDense dense; AMFDense m_Dense;
}; };
#endif //!__AMF3__H__ #endif //!__AMF3__H__

View File

@ -53,7 +53,7 @@ void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value) {
* A private function to write an value to a RakNet::BitStream * A private function to write an value to a RakNet::BitStream
* RakNet writes in the correct byte order - do not reverse this. * RakNet writes in the correct byte order - do not reverse this.
*/ */
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) { void WriteUInt29(RakNet::BitStream& bs, uint32_t v) {
unsigned char b4 = static_cast<unsigned char>(v); unsigned char b4 = static_cast<unsigned char>(v);
if (v < 0x00200000) { if (v < 0x00200000) {
b4 = b4 & 0x7F; b4 = b4 & 0x7F;
@ -65,10 +65,10 @@ void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
unsigned char b2; unsigned char b2;
v = v >> 7; v = v >> 7;
b2 = static_cast<unsigned char>(v) | 0x80; b2 = static_cast<unsigned char>(v) | 0x80;
bs->Write(b2); bs.Write(b2);
} }
bs->Write(b3); bs.Write(b3);
} }
} else { } else {
unsigned char b1; unsigned char b1;
@ -82,19 +82,19 @@ void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
v = v >> 7; v = v >> 7;
b1 = static_cast<unsigned char>(v) | 0x80; b1 = static_cast<unsigned char>(v) | 0x80;
bs->Write(b1); bs.Write(b1);
bs->Write(b2); bs.Write(b2);
bs->Write(b3); bs.Write(b3);
} }
bs->Write(b4); bs.Write(b4);
} }
/** /**
* Writes a flag number to a RakNet::BitStream * Writes a flag number to a RakNet::BitStream
* RakNet writes in the correct byte order - do not reverse this. * RakNet writes in the correct byte order - do not reverse this.
*/ */
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) { void WriteFlagNumber(RakNet::BitStream& bs, uint32_t v) {
v = (v << 1) | 0x01; v = (v << 1) | 0x01;
WriteUInt29(bs, v); WriteUInt29(bs, v);
} }
@ -104,9 +104,9 @@ void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
* *
* RakNet writes in the correct byte order - do not reverse this. * RakNet writes in the correct byte order - do not reverse this.
*/ */
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) { void WriteAMFString(RakNet::BitStream& bs, const std::string& str) {
WriteFlagNumber(bs, static_cast<uint32_t>(str.size())); WriteFlagNumber(bs, static_cast<uint32_t>(str.size()));
bs->Write(str.c_str(), static_cast<uint32_t>(str.size())); bs.Write(str.c_str(), static_cast<uint32_t>(str.size()));
} }
/** /**
@ -114,8 +114,8 @@ void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
* *
* RakNet writes in the correct byte order - do not reverse this. * RakNet writes in the correct byte order - do not reverse this.
*/ */
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) { void WriteAMFU16(RakNet::BitStream& bs, uint16_t value) {
bs->Write(value); bs.Write(value);
} }
/** /**
@ -123,8 +123,8 @@ void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
* *
* RakNet writes in the correct byte order - do not reverse this. * RakNet writes in the correct byte order - do not reverse this.
*/ */
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) { void WriteAMFU32(RakNet::BitStream& bs, uint32_t value) {
bs->Write(value); bs.Write(value);
} }
/** /**
@ -132,40 +132,40 @@ void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
* *
* RakNet writes in the correct byte order - do not reverse this. * RakNet writes in the correct byte order - do not reverse this.
*/ */
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) { void WriteAMFU64(RakNet::BitStream& bs, uint64_t value) {
bs->Write(value); bs.Write(value);
} }
// Writes an AMFIntegerValue to BitStream // Writes an AMFIntegerValue to BitStream
template<> template<>
void RakNet::BitStream::Write<AMFIntValue&>(AMFIntValue& value) { void RakNet::BitStream::Write<AMFIntValue&>(AMFIntValue& value) {
WriteUInt29(this, value.GetValue()); WriteUInt29(*this, value.GetValue());
} }
// Writes an AMFDoubleValue to BitStream // Writes an AMFDoubleValue to BitStream
template<> template<>
void RakNet::BitStream::Write<AMFDoubleValue&>(AMFDoubleValue& value) { void RakNet::BitStream::Write<AMFDoubleValue&>(AMFDoubleValue& value) {
double d = value.GetValue(); double d = value.GetValue();
WriteAMFU64(this, *reinterpret_cast<uint64_t*>(&d)); WriteAMFU64(*this, *reinterpret_cast<uint64_t*>(&d));
} }
// Writes an AMFStringValue to BitStream // Writes an AMFStringValue to BitStream
template<> template<>
void RakNet::BitStream::Write<AMFStringValue&>(AMFStringValue& value) { void RakNet::BitStream::Write<AMFStringValue&>(AMFStringValue& value) {
WriteAMFString(this, value.GetValue()); WriteAMFString(*this, value.GetValue());
} }
// Writes an AMFArrayValue to BitStream // Writes an AMFArrayValue to BitStream
template<> template<>
void RakNet::BitStream::Write<AMFArrayValue&>(AMFArrayValue& value) { void RakNet::BitStream::Write<AMFArrayValue&>(AMFArrayValue& value) {
uint32_t denseSize = value.GetDense().size(); uint32_t denseSize = value.GetDense().size();
WriteFlagNumber(this, denseSize); WriteFlagNumber(*this, denseSize);
auto it = value.GetAssociative().begin(); auto it = value.GetAssociative().begin();
auto end = value.GetAssociative().end(); auto end = value.GetAssociative().end();
while (it != end) { while (it != end) {
WriteAMFString(this, it->first); WriteAMFString(*this, it->first);
this->Write<AMFBaseValue&>(*it->second); this->Write<AMFBaseValue&>(*it->second);
it++; it++;
} }

View File

@ -8,11 +8,9 @@ set(DCOMMON_SOURCES
"Game.cpp" "Game.cpp"
"GeneralUtils.cpp" "GeneralUtils.cpp"
"LDFFormat.cpp" "LDFFormat.cpp"
"MD5.cpp"
"Metrics.cpp" "Metrics.cpp"
"NiPoint3.cpp" "NiPoint3.cpp"
"NiQuaternion.cpp" "NiQuaternion.cpp"
"SHA512.cpp"
"Demangler.cpp" "Demangler.cpp"
"ZCompression.cpp" "ZCompression.cpp"
"BrickByBrickFix.cpp" "BrickByBrickFix.cpp"
@ -20,17 +18,27 @@ set(DCOMMON_SOURCES
"FdbToSqlite.cpp" "FdbToSqlite.cpp"
) )
# Workaround for compiler bug where the optimized code could result in a memcpy of 0 bytes, even though that isnt possible.
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97185
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set_source_files_properties("FdbToSqlite.cpp" PROPERTIES COMPILE_FLAGS "-Wno-stringop-overflow")
endif()
add_subdirectory(dClient) add_subdirectory(dClient)
foreach(file ${DCOMMON_DCLIENT_SOURCES}) foreach(file ${DCOMMON_DCLIENT_SOURCES})
set(DCOMMON_SOURCES ${DCOMMON_SOURCES} "dClient/${file}") set(DCOMMON_SOURCES ${DCOMMON_SOURCES} "dClient/${file}")
endforeach() endforeach()
include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
add_library(dCommon STATIC ${DCOMMON_SOURCES}) add_library(dCommon STATIC ${DCOMMON_SOURCES})
target_include_directories(dCommon
target_link_libraries(dCommon bcrypt dDatabase tinyxml2) PUBLIC "." "dClient" "dEnums"
PRIVATE
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase"
"${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/include"
)
if (UNIX) if (UNIX)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
@ -61,4 +69,6 @@ else ()
) )
endif () endif ()
target_link_libraries(dCommon ZLIB::ZLIB) target_link_libraries(dCommon
PRIVATE ZLIB::ZLIB bcrypt tinyxml2
INTERFACE dDatabase)

View File

@ -278,14 +278,14 @@ std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char
return vector; return vector;
} }
std::u16string GeneralUtils::ReadWString(RakNet::BitStream* inStream) { std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
uint32_t length; uint32_t length;
inStream->Read<uint32_t>(length); inStream.Read<uint32_t>(length);
std::u16string string; std::u16string string;
for (auto i = 0; i < length; i++) { for (auto i = 0; i < length; i++) {
uint16_t c; uint16_t c;
inStream->Read(c); inStream.Read(c);
string.push_back(c); string.push_back(c);
} }
@ -320,6 +320,24 @@ std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::stri
return sortedFiles; return sortedFiles;
} }
bool GeneralUtils::TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst) { #ifdef DARKFLAME_PLATFORM_MACOS
return TryParse<float>(x.c_str(), dst.x) && TryParse<float>(y.c_str(), dst.y) && TryParse<float>(z.c_str(), dst.z);
// MacOS floating-point parse function specializations
namespace GeneralUtils::details {
template <>
[[nodiscard]] float _parse<float>(const std::string_view str, size_t& parseNum) {
return std::stof(std::string{ str }, &parseNum);
}
template <>
[[nodiscard]] double _parse<double>(const std::string_view str, size_t& parseNum) {
return std::stod(std::string{ str }, &parseNum);
}
template <>
[[nodiscard]] long double _parse<long double>(const std::string_view str, size_t& parseNum) {
return std::stold(std::string{ str }, &parseNum);
}
} }
#endif

View File

@ -1,17 +1,20 @@
#pragma once #pragma once
// C++ // C++
#include <stdint.h> #include <charconv>
#include <cstdint>
#include <random> #include <random>
#include <time.h> #include <ctime>
#include <string> #include <string>
#include <type_traits> #include <string_view>
#include <optional>
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
#include <stdexcept> #include <stdexcept>
#include "BitStream.h" #include "BitStream.h"
#include "NiPoint3.h" #include "NiPoint3.h"
#include "dPlatforms.h"
#include "Game.h" #include "Game.h"
#include "Logger.h" #include "Logger.h"
@ -113,7 +116,7 @@ namespace GeneralUtils {
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to); bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
std::u16string ReadWString(RakNet::BitStream* inStream); std::u16string ReadWString(RakNet::BitStream& inStream);
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter); std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
@ -123,90 +126,111 @@ namespace GeneralUtils {
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder); std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
// Concept constraining to enum types
template <typename T> template <typename T>
T Parse(const char* value); concept Enum = std::is_enum_v<T>;
template <>
inline bool Parse(const char* value) {
return std::stoi(value);
}
template <>
inline int32_t Parse(const char* value) {
return std::stoi(value);
}
template <>
inline int64_t Parse(const char* value) {
return std::stoll(value);
}
template <>
inline float Parse(const char* value) {
return std::stof(value);
}
template <>
inline double Parse(const char* value) {
return std::stod(value);
}
template <>
inline uint16_t Parse(const char* value) {
return std::stoul(value);
}
template <>
inline uint32_t Parse(const char* value) {
return std::stoul(value);
}
template <>
inline uint64_t Parse(const char* value) {
return std::stoull(value);
}
template <>
inline eInventoryType Parse(const char* value) {
return static_cast<eInventoryType>(std::stoul(value));
}
template <>
inline eReplicaComponentType Parse(const char* value) {
return static_cast<eReplicaComponentType>(std::stoul(value));
}
// Concept constraining to numeric types
template <typename T> template <typename T>
bool TryParse(const char* value, T& dst) { concept Numeric = std::integral<T> || Enum<T> || std::floating_point<T>;
// Concept trickery to enable parsing underlying numeric types
template <Numeric T>
struct numeric_parse { using type = T; };
// If an enum, present an alias to its underlying type for parsing
template <Numeric T> requires Enum<T>
struct numeric_parse<T> { using type = std::underlying_type_t<T>; };
// If a boolean, present an alias to an intermediate integral type for parsing
template <Numeric T> requires std::same_as<T, bool>
struct numeric_parse<T> { using type = uint32_t; };
// Shorthand type alias
template <Numeric T>
using numeric_parse_t = numeric_parse<T>::type;
/**
* For numeric values: Parses a string_view and returns an optional variable depending on the result.
* @param str The string_view to be evaluated
* @returns An std::optional containing the desired value if it is equivalent to the string
*/
template <Numeric T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) {
numeric_parse_t<T> result;
const char* const strEnd = str.data() + str.size();
const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
const bool isParsed = parseEnd == strEnd && ec == std::errc{};
return isParsed ? static_cast<T>(result) : std::optional<T>{};
}
#ifdef DARKFLAME_PLATFORM_MACOS
// MacOS floating-point parse helper function specializations
namespace details {
template <std::floating_point T>
[[nodiscard]] T _parse(const std::string_view str, size_t& parseNum);
}
/**
* For floating-point values: Parses a string_view and returns an optional variable depending on the result.
* Note that this function overload is only included for MacOS, as from_chars will fulfill its purpose otherwise.
* @param str The string_view to be evaluated
* @returns An std::optional containing the desired value if it is equivalent to the string
*/
template <std::floating_point T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept
try { try {
dst = Parse<T>(value); size_t parseNum;
const T result = details::_parse<T>(str, parseNum);
const bool isParsed = str.length() == parseNum;
return true; return isParsed ? result : std::optional<T>{};
} catch (...) { } catch (...) {
return false; return std::nullopt;
} }
#endif
/**
* The TryParse overload for handling NiPoint3 by passing 3 seperate string references
* @param strX The string representing the X coordinate
* @param strY The string representing the Y coordinate
* @param strZ The string representing the Z coordinate
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
*/
template <typename T>
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string& strX, const std::string& strY, const std::string& strZ) {
const auto x = TryParse<float>(strX);
if (!x) return std::nullopt;
const auto y = TryParse<float>(strY);
if (!y) return std::nullopt;
const auto z = TryParse<float>(strZ);
return z ? std::make_optional<NiPoint3>(x.value(), y.value(), z.value()) : std::nullopt;
}
/**
* The TryParse overload for handling NiPoint3 by passingn a reference to a vector of three strings
* @param str The string vector representing the X, Y, and Xcoordinates
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
*/
template <typename T>
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::vector<std::string>& str) {
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
} }
template <typename T> template <typename T>
T Parse(const std::string& value) {
return Parse<T>(value.c_str());
}
template <typename T>
bool TryParse(const std::string& value, T& dst) {
return TryParse<T>(value.c_str(), dst);
}
bool TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst);
template<typename T>
std::u16string to_u16string(T value) { std::u16string to_u16string(T value) {
return GeneralUtils::ASCIIToUTF16(std::to_string(value)); return GeneralUtils::ASCIIToUTF16(std::to_string(value));
} }
// From boost::hash_combine // From boost::hash_combine
template <class T> template <class T>
void hash_combine(std::size_t& s, const T& v) { constexpr void hash_combine(std::size_t& s, const T& v) {
std::hash<T> h; std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
} }
@ -239,11 +263,9 @@ namespace GeneralUtils {
* @param entry Enum entry to cast * @param entry Enum entry to cast
* @returns The enum entry's value in its underlying type * @returns The enum entry's value in its underlying type
*/ */
template <typename eType> template <Enum eType>
inline constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) { constexpr std::underlying_type_t<eType> ToUnderlying(const eType entry) noexcept {
static_assert(std::is_enum_v<eType>, "Not an enum"); return static_cast<std::underlying_type_t<eType>>(entry);
return static_cast<typename std::underlying_type_t<eType>>(entry);
} }
// on Windows we need to undef these or else they conflict with our numeric limits calls // on Windows we need to undef these or else they conflict with our numeric limits calls

View File

@ -61,33 +61,33 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_S32: { case LDF_TYPE_S32: {
int32_t data; const auto data = GeneralUtils::TryParse<int32_t>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<int32_t>(key, data); returnValue = new LDFData<int32_t>(key, data.value());
break; break;
} }
case LDF_TYPE_FLOAT: { case LDF_TYPE_FLOAT: {
float data; const auto data = GeneralUtils::TryParse<float>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<float>(key, data); returnValue = new LDFData<float>(key, data.value());
break; break;
} }
case LDF_TYPE_DOUBLE: { case LDF_TYPE_DOUBLE: {
double data; const auto data = GeneralUtils::TryParse<double>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<double>(key, data); returnValue = new LDFData<double>(key, data.value());
break; break;
} }
@ -100,10 +100,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else if (ldfTypeAndValue.second == "false") { } else if (ldfTypeAndValue.second == "false") {
data = 0; data = 0;
} else { } else {
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfTypeAndValue.second);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
data = dataOptional.value();
} }
returnValue = new LDFData<uint32_t>(key, data); returnValue = new LDFData<uint32_t>(key, data);
@ -118,10 +120,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else if (ldfTypeAndValue.second == "false") { } else if (ldfTypeAndValue.second == "false") {
data = false; data = false;
} else { } else {
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { const auto dataOptional = GeneralUtils::TryParse<bool>(ldfTypeAndValue.second);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
data = dataOptional.value();
} }
returnValue = new LDFData<bool>(key, data); returnValue = new LDFData<bool>(key, data);
@ -129,22 +133,22 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_U64: { case LDF_TYPE_U64: {
uint64_t data; const auto data = GeneralUtils::TryParse<uint64_t>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<uint64_t>(key, data); returnValue = new LDFData<uint64_t>(key, data.value());
break; break;
} }
case LDF_TYPE_OBJID: { case LDF_TYPE_OBJID: {
LWOOBJID data; const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<LWOOBJID>(key, data); returnValue = new LDFData<LWOOBJID>(key, data.value());
break; break;
} }

View File

@ -31,7 +31,7 @@ public:
virtual ~LDFBaseData() {} virtual ~LDFBaseData() {}
virtual void WriteToPacket(RakNet::BitStream* packet) = 0; virtual void WriteToPacket(RakNet::BitStream& packet) = 0;
virtual const std::u16string& GetKey() = 0; virtual const std::u16string& GetKey() = 0;
@ -62,17 +62,17 @@ private:
T value; T value;
//! Writes the key to the packet //! Writes the key to the packet
void WriteKey(RakNet::BitStream* packet) { void WriteKey(RakNet::BitStream& packet) {
packet->Write<uint8_t>(this->key.length() * sizeof(uint16_t)); packet.Write<uint8_t>(this->key.length() * sizeof(uint16_t));
for (uint32_t i = 0; i < this->key.length(); ++i) { for (uint32_t i = 0; i < this->key.length(); ++i) {
packet->Write<uint16_t>(this->key[i]); packet.Write<uint16_t>(this->key[i]);
} }
} }
//! Writes the value to the packet //! Writes the value to the packet
void WriteValue(RakNet::BitStream* packet) { void WriteValue(RakNet::BitStream& packet) {
packet->Write<uint8_t>(this->GetValueType()); packet.Write<uint8_t>(this->GetValueType());
packet->Write(this->value); packet.Write(this->value);
} }
public: public:
@ -108,7 +108,7 @@ public:
/*! /*!
\param packet The packet \param packet The packet
*/ */
void WriteToPacket(RakNet::BitStream* packet) override { void WriteToPacket(RakNet::BitStream& packet) override {
this->WriteKey(packet); this->WriteKey(packet);
this->WriteValue(packet); this->WriteValue(packet);
} }
@ -162,7 +162,7 @@ public:
return new LDFData<T>(key, value); return new LDFData<T>(key, value);
} }
inline static T Default = {}; inline static const T Default = {};
}; };
// LDF Types // LDF Types
@ -178,31 +178,31 @@ template<> inline eLDFType LDFData<std::string>::GetValueType(void) { return LDF
// The specialized version for std::u16string (UTF-16) // The specialized version for std::u16string (UTF-16)
template<> template<>
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream* packet) { inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) {
packet->Write<uint8_t>(this->GetValueType()); packet.Write<uint8_t>(this->GetValueType());
packet->Write<uint32_t>(this->value.length()); packet.Write<uint32_t>(this->value.length());
for (uint32_t i = 0; i < this->value.length(); ++i) { for (uint32_t i = 0; i < this->value.length(); ++i) {
packet->Write<uint16_t>(this->value[i]); packet.Write<uint16_t>(this->value[i]);
} }
} }
// The specialized version for bool // The specialized version for bool
template<> template<>
inline void LDFData<bool>::WriteValue(RakNet::BitStream* packet) { inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) {
packet->Write<uint8_t>(this->GetValueType()); packet.Write<uint8_t>(this->GetValueType());
packet->Write<uint8_t>(this->value); packet.Write<uint8_t>(this->value);
} }
// The specialized version for std::string (UTF-8) // The specialized version for std::string (UTF-8)
template<> template<>
inline void LDFData<std::string>::WriteValue(RakNet::BitStream* packet) { inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) {
packet->Write<uint8_t>(this->GetValueType()); packet.Write<uint8_t>(this->GetValueType());
packet->Write<uint32_t>(this->value.length()); packet.Write<uint32_t>(this->value.length());
for (uint32_t i = 0; i < this->value.length(); ++i) { for (uint32_t i = 0; i < this->value.length(); ++i) {
packet->Write<uint8_t>(this->value[i]); packet.Write<uint8_t>(this->value[i]);
} }
} }

View File

@ -1,210 +1,24 @@
#include "NiPoint3.h" #include "NiPoint3.h"
#include "NiQuaternion.h"
// C++ // C++
#include <cmath> #include <cmath>
// Static Variables // MARK: Member Functions
const NiPoint3 NiPoint3::ZERO(0.0f, 0.0f, 0.0f);
const NiPoint3 NiPoint3::UNIT_X(1.0f, 0.0f, 0.0f);
const NiPoint3 NiPoint3::UNIT_Y(0.0f, 1.0f, 0.0f);
const NiPoint3 NiPoint3::UNIT_Z(0.0f, 0.0f, 1.0f);
const NiPoint3 NiPoint3::UNIT_ALL(1.0f, 1.0f, 1.0f);
//! Initializer
NiPoint3::NiPoint3(void) {
this->x = 0;
this->y = 0;
this->z = 0;
}
//! Initializer
NiPoint3::NiPoint3(float x, float y, float z) {
this->x = x;
this->y = y;
this->z = z;
}
//! Copy Constructor
NiPoint3::NiPoint3(const NiPoint3& point) {
this->x = point.x;
this->y = point.y;
this->z = point.z;
}
//! Destructor
NiPoint3::~NiPoint3(void) {}
// MARK: Getters / Setters
//! Gets the X coordinate
float NiPoint3::GetX(void) const {
return this->x;
}
//! Sets the X coordinate
void NiPoint3::SetX(float x) {
this->x = x;
}
//! Gets the Y coordinate
float NiPoint3::GetY(void) const {
return this->y;
}
//! Sets the Y coordinate
void NiPoint3::SetY(float y) {
this->y = y;
}
//! Gets the Z coordinate
float NiPoint3::GetZ(void) const {
return this->z;
}
//! Sets the Z coordinate
void NiPoint3::SetZ(float z) {
this->z = z;
}
// MARK: Functions
//! Gets the length of the vector //! Gets the length of the vector
float NiPoint3::Length(void) const { float NiPoint3::Length() const {
return sqrt(x * x + y * y + z * z); return std::sqrt(x * x + y * y + z * z);
}
//! Gets the squared length of a vector
float NiPoint3::SquaredLength(void) const {
return (x * x + y * y + z * z);
}
//! Returns the dot product of the vector dotted with another vector
float NiPoint3::DotProduct(const Vector3& vec) const {
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
}
//! Returns the cross product of the vector crossed with another vector
Vector3 NiPoint3::CrossProduct(const Vector3& vec) const {
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
((this->z * vec.x) - (this->x * vec.z)),
((this->x * vec.y) - (this->y * vec.x)));
} }
//! Unitize the vector //! Unitize the vector
NiPoint3 NiPoint3::Unitize(void) const { NiPoint3 NiPoint3::Unitize() const {
float length = this->Length(); float length = this->Length();
return length != 0 ? *this / length : NiPoint3::ZERO; return length != 0 ? *this / length : NiPoint3Constant::ZERO;
} }
// MARK: Operators
//! Operator to check for equality
bool NiPoint3::operator==(const NiPoint3& point) const {
return point.x == this->x && point.y == this->y && point.z == this->z;
}
//! Operator to check for inequality
bool NiPoint3::operator!=(const NiPoint3& point) const {
return !(*this == point);
}
//! Operator for subscripting
float& NiPoint3::operator[](int i) {
float* base = &x;
return base[i];
}
//! Operator for subscripting
const float& NiPoint3::operator[](int i) const {
const float* base = &x;
return base[i];
}
//! Operator for addition of vectors
NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
}
//! Operator for addition of vectors
NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
this->x += point.x;
this->y += point.y;
this->z += point.z;
return *this;
}
NiPoint3& NiPoint3::operator*=(const float scalar) {
this->x *= scalar;
this->y *= scalar;
this->z *= scalar;
return *this;
}
//! Operator for subtraction of vectors
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
}
//! Operator for addition of a scalar on all vector components
NiPoint3 NiPoint3::operator+(float fScalar) const {
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
}
//! Operator for subtraction of a scalar on all vector components
NiPoint3 NiPoint3::operator-(float fScalar) const {
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
}
//! Operator for scalar multiplication of a vector
NiPoint3 NiPoint3::operator*(float fScalar) const {
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
}
//! Operator for scalar division of a vector
NiPoint3 NiPoint3::operator/(float fScalar) const {
float retX = this->x != 0 ? this->x / fScalar : 0;
float retY = this->y != 0 ? this->y / fScalar : 0;
float retZ = this->z != 0 ? this->z / fScalar : 0;
return NiPoint3(retX, retY, retZ);
}
// MARK: Helper Functions // MARK: Helper Functions
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) {
if (this->x < minPoint.x) return false;
if (this->x > maxPoint.x) return false;
if (this->y < minPoint.y) return false;
if (this->y > maxPoint.y) return false;
return (this->z < maxPoint.z && this->z > minPoint.z);
}
//! Checks to see if the point (or vector) is within a sphere
bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float radius) {
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
return (diffVec.SquaredLength() <= (radius * radius));
}
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) {
if (a == b) return a;
const auto pa = p - a;
const auto ab = b - a;
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
if (t <= 0.0f) return a;
if (t >= 1.0f) return b;
return a + ab * t;
}
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) { float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) {
const auto dot = a.DotProduct(b); const auto dot = a.DotProduct(b);
const auto lenA = a.SquaredLength(); const auto lenA = a.SquaredLength();
@ -220,15 +34,7 @@ float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) {
return std::sqrt(dx * dx + dy * dy + dz * dz); return std::sqrt(dx * dx + dy * dy + dz * dz);
} }
float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) { NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, const float maxDistanceDelta) {
const auto dx = a.x - b.x;
const auto dy = a.y - b.y;
const auto dz = a.z - b.z;
return dx * dx + dy * dy + dz * dz;
}
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta) {
float dx = target.x - current.x; float dx = target.x - current.x;
float dy = target.y - current.y; float dy = target.y - current.y;
float dz = target.z - current.z; float dz = target.z - current.z;
@ -249,29 +55,3 @@ NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target,
float length = std::sqrt(lengthSquared); float length = std::sqrt(lengthSquared);
return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta); return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta);
} }
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) {
Vector3 vector;
float num12 = rotation.x + rotation.x;
float num2 = rotation.y + rotation.y;
float num = rotation.z + rotation.z;
float num11 = rotation.w * num12;
float num10 = rotation.w * num2;
float num9 = rotation.w * num;
float num8 = rotation.x * num12;
float num7 = rotation.x * num2;
float num6 = rotation.x * num;
float num5 = rotation.y * num2;
float num4 = rotation.y * num;
float num3 = rotation.z * num;
NiPoint3 value = *this;
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
vector.x = num15;
vector.y = num14;
vector.z = num13;
return vector;
}

View File

@ -1,4 +1,5 @@
#pragma once #ifndef __NIPOINT3_H__
#define __NIPOINT3_H__
/*! /*!
\file NiPoint3.hpp \file NiPoint3.hpp
@ -12,13 +13,13 @@ typedef NiPoint3 Vector3; //!< The Vector3 class is technically the NiPoin
//! A custom class the defines a point in space //! A custom class the defines a point in space
class NiPoint3 { class NiPoint3 {
public: public:
float x; //!< The x position float x{ 0 }; //!< The x position
float y; //!< The y position float y{ 0 }; //!< The y position
float z; //!< The z position float z{ 0 }; //!< The z position
//! Initializer //! Initializer
NiPoint3(void); constexpr NiPoint3() = default;
//! Initializer //! Initializer
/*! /*!
@ -26,23 +27,21 @@ public:
\param y The y coordinate \param y The y coordinate
\param z The z coordinate \param z The z coordinate
*/ */
NiPoint3(float x, float y, float z); constexpr NiPoint3(const float x, const float y, const float z) noexcept
: x{ x }
, y{ y }
, z{ z } {
}
//! Copy Constructor //! Copy Constructor
/*! /*!
\param point The point to copy \param point The point to copy
*/ */
NiPoint3(const NiPoint3& point); constexpr NiPoint3(const NiPoint3& point) noexcept
: x{ point.x }
//! Destructor , y{ point.y }
~NiPoint3(void); , z{ point.z } {
}
// MARK: Constants
static const NiPoint3 ZERO; //!< Point(0, 0, 0)
static const NiPoint3 UNIT_X; //!< Point(1, 0, 0)
static const NiPoint3 UNIT_Y; //!< Point(0, 1, 0)
static const NiPoint3 UNIT_Z; //!< Point(0, 0, 1)
static const NiPoint3 UNIT_ALL; //!< Point(1, 1, 1)
// MARK: Getters / Setters // MARK: Getters / Setters
@ -50,38 +49,37 @@ public:
/*! /*!
\return The x coordinate \return The x coordinate
*/ */
float GetX(void) const; [[nodiscard]] constexpr float GetX() const noexcept;
//! Sets the X coordinate //! Sets the X coordinate
/*! /*!
\param x The x coordinate \param x The x coordinate
*/ */
void SetX(float x); constexpr void SetX(const float x) noexcept;
//! Gets the Y coordinate //! Gets the Y coordinate
/*! /*!
\return The y coordinate \return The y coordinate
*/ */
float GetY(void) const; [[nodiscard]] constexpr float GetY() const noexcept;
//! Sets the Y coordinate //! Sets the Y coordinate
/*! /*!
\param y The y coordinate \param y The y coordinate
*/ */
void SetY(float y); constexpr void SetY(const float y) noexcept;
//! Gets the Z coordinate //! Gets the Z coordinate
/*! /*!
\return The z coordinate \return The z coordinate
*/ */
float GetZ(void) const; [[nodiscard]] constexpr float GetZ() const noexcept;
//! Sets the Z coordinate //! Sets the Z coordinate
/*! /*!
\param z The z coordinate \param z The z coordinate
*/ */
void SetZ(float z); constexpr void SetZ(const float z) noexcept;
// MARK: Member Functions // MARK: Member Functions
@ -89,72 +87,70 @@ public:
/*! /*!
\return The scalar length of the vector \return The scalar length of the vector
*/ */
float Length(void) const; [[nodiscard]] float Length() const;
//! Gets the squared length of a vector //! Gets the squared length of a vector
/*! /*!
\return The squared length of a vector \return The squared length of a vector
*/ */
float SquaredLength(void) const; [[nodiscard]] constexpr float SquaredLength() const noexcept;
//! Returns the dot product of the vector dotted with another vector //! Returns the dot product of the vector dotted with another vector
/*! /*!
\param vec The second vector \param vec The second vector
\return The dot product of the two vectors \return The dot product of the two vectors
*/ */
float DotProduct(const Vector3& vec) const; [[nodiscard]] constexpr float DotProduct(const Vector3& vec) const noexcept;
//! Returns the cross product of the vector crossed with another vector //! Returns the cross product of the vector crossed with another vector
/*! /*!
\param vec The second vector \param vec The second vector
\return The cross product of the two vectors \return The cross product of the two vectors
*/ */
Vector3 CrossProduct(const Vector3& vec) const; [[nodiscard]] constexpr Vector3 CrossProduct(const Vector3& vec) const noexcept;
//! Unitize the vector //! Unitize the vector
/*! /*!
\returns The current vector \returns The current vector
*/ */
NiPoint3 Unitize(void) const; [[nodiscard]] NiPoint3 Unitize() const;
// MARK: Operators // MARK: Operators
//! Operator to check for equality //! Operator to check for equality
bool operator==(const NiPoint3& point) const; constexpr bool operator==(const NiPoint3& point) const noexcept;
//! Operator to check for inequality //! Operator to check for inequality
bool operator!=(const NiPoint3& point) const; constexpr bool operator!=(const NiPoint3& point) const noexcept;
//! Operator for subscripting //! Operator for subscripting
float& operator[](int i); constexpr float& operator[](const int i) noexcept;
//! Operator for subscripting //! Operator for subscripting
const float& operator[](int i) const; constexpr const float& operator[](const int i) const noexcept;
//! Operator for addition of vectors //! Operator for addition of vectors
NiPoint3 operator+(const NiPoint3& point) const; constexpr NiPoint3 operator+(const NiPoint3& point) const noexcept;
//! Operator for addition of vectors //! Operator for addition of vectors
NiPoint3& operator+=(const NiPoint3& point); constexpr NiPoint3& operator+=(const NiPoint3& point) noexcept;
NiPoint3& operator*=(const float scalar); constexpr NiPoint3& operator*=(const float scalar) noexcept;
//! Operator for subtraction of vectors //! Operator for subtraction of vectors
NiPoint3 operator-(const NiPoint3& point) const; constexpr NiPoint3 operator-(const NiPoint3& point) const noexcept;
//! Operator for addition of a scalar on all vector components //! Operator for addition of a scalar on all vector components
NiPoint3 operator+(float fScalar) const; constexpr NiPoint3 operator+(const float fScalar) const noexcept;
//! Operator for subtraction of a scalar on all vector components //! Operator for subtraction of a scalar on all vector components
NiPoint3 operator-(float fScalar) const; constexpr NiPoint3 operator-(const float fScalar) const noexcept;
//! Operator for scalar multiplication of a vector //! Operator for scalar multiplication of a vector
NiPoint3 operator*(float fScalar) const; constexpr NiPoint3 operator*(const float fScalar) const noexcept;
//! Operator for scalar division of a vector //! Operator for scalar division of a vector
NiPoint3 operator/(float fScalar) const; constexpr NiPoint3 operator/(const float fScalar) const noexcept;
// MARK: Helper Functions // MARK: Helper Functions
@ -164,14 +160,14 @@ public:
\param maxPoint The maximum point of the bounding box \param maxPoint The maximum point of the bounding box
\return Whether or not this point lies within the box \return Whether or not this point lies within the box
*/ */
bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint); [[nodiscard]] constexpr bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) noexcept;
//! Checks to see if the point (or vector) is within a sphere //! Checks to see if the point (or vector) is within a sphere
/*! /*!
\param sphereCenter The sphere center \param sphereCenter The sphere center
\param radius The radius \param radius The radius
*/ */
bool IsWithinSpehere(const NiPoint3& sphereCenter, float radius); [[nodiscard]] constexpr bool IsWithinSphere(const NiPoint3& sphereCenter, const float radius) noexcept;
/*! /*!
\param a Start of line \param a Start of line
@ -179,15 +175,30 @@ public:
\param p Refrence point \param p Refrence point
\return The point of line AB which is closest to P \return The point of line AB which is closest to P
*/ */
static NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p); [[nodiscard]] static constexpr NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) noexcept;
static float Angle(const NiPoint3& a, const NiPoint3& b); [[nodiscard]] static float Angle(const NiPoint3& a, const NiPoint3& b);
static float Distance(const NiPoint3& a, const NiPoint3& b); [[nodiscard]] static float Distance(const NiPoint3& a, const NiPoint3& b);
static float DistanceSquared(const NiPoint3& a, const NiPoint3& b); [[nodiscard]] static constexpr float DistanceSquared(const NiPoint3& a, const NiPoint3& b) noexcept;
static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta); [[nodiscard]] static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, const float maxDistanceDelta);
NiPoint3 RotateByQuaternion(const NiQuaternion& rotation); //This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
[[nodiscard]] constexpr NiPoint3 RotateByQuaternion(const NiQuaternion& rotation) noexcept;
}; };
// Static Variables
namespace NiPoint3Constant {
constexpr NiPoint3 ZERO(0.0f, 0.0f, 0.0f);
constexpr NiPoint3 UNIT_X(1.0f, 0.0f, 0.0f);
constexpr NiPoint3 UNIT_Y(0.0f, 1.0f, 0.0f);
constexpr NiPoint3 UNIT_Z(0.0f, 0.0f, 1.0f);
constexpr NiPoint3 UNIT_ALL(1.0f, 1.0f, 1.0f);
}
// .inl file needed for code organization and to circumvent circular dependency issues
#include "NiPoint3.inl"
#endif // !__NIPOINT3_H__

196
dCommon/NiPoint3.inl Normal file
View File

@ -0,0 +1,196 @@
#pragma once
#ifndef __NIPOINT3_H__
#error "This should only be included inline in NiPoint3.h: Do not include directly!"
#endif
#include "NiQuaternion.h"
// MARK: Getters / Setters
//! Gets the X coordinate
constexpr float NiPoint3::GetX() const noexcept {
return this->x;
}
//! Sets the X coordinate
constexpr void NiPoint3::SetX(const float x) noexcept {
this->x = x;
}
//! Gets the Y coordinate
constexpr float NiPoint3::GetY() const noexcept {
return this->y;
}
//! Sets the Y coordinate
constexpr void NiPoint3::SetY(const float y) noexcept {
this->y = y;
}
//! Gets the Z coordinate
constexpr float NiPoint3::GetZ() const noexcept {
return this->z;
}
//! Sets the Z coordinate
constexpr void NiPoint3::SetZ(const float z) noexcept {
this->z = z;
}
// MARK: Member Functions
//! Gets the squared length of a vector
constexpr float NiPoint3::SquaredLength() const noexcept {
return (x * x + y * y + z * z);
}
//! Returns the dot product of the vector dotted with another vector
constexpr float NiPoint3::DotProduct(const Vector3& vec) const noexcept {
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
}
//! Returns the cross product of the vector crossed with another vector
constexpr Vector3 NiPoint3::CrossProduct(const Vector3& vec) const noexcept {
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
((this->z * vec.x) - (this->x * vec.z)),
((this->x * vec.y) - (this->y * vec.x)));
}
// MARK: Operators
//! Operator to check for equality
constexpr bool NiPoint3::operator==(const NiPoint3& point) const noexcept {
return point.x == this->x && point.y == this->y && point.z == this->z;
}
//! Operator to check for inequality
constexpr bool NiPoint3::operator!=(const NiPoint3& point) const noexcept {
return !(*this == point);
}
//! Operator for subscripting
constexpr float& NiPoint3::operator[](const int i) noexcept {
float* base = &x;
return base[i];
}
//! Operator for subscripting
constexpr const float& NiPoint3::operator[](const int i) const noexcept {
const float* base = &x;
return base[i];
}
//! Operator for addition of vectors
constexpr NiPoint3 NiPoint3::operator+(const NiPoint3& point) const noexcept {
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
}
//! Operator for addition of vectors
constexpr NiPoint3& NiPoint3::operator+=(const NiPoint3& point) noexcept {
this->x += point.x;
this->y += point.y;
this->z += point.z;
return *this;
}
constexpr NiPoint3& NiPoint3::operator*=(const float scalar) noexcept {
this->x *= scalar;
this->y *= scalar;
this->z *= scalar;
return *this;
}
//! Operator for subtraction of vectors
constexpr NiPoint3 NiPoint3::operator-(const NiPoint3& point) const noexcept {
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
}
//! Operator for addition of a scalar on all vector components
constexpr NiPoint3 NiPoint3::operator+(const float fScalar) const noexcept {
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
}
//! Operator for subtraction of a scalar on all vector components
constexpr NiPoint3 NiPoint3::operator-(const float fScalar) const noexcept {
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
}
//! Operator for scalar multiplication of a vector
constexpr NiPoint3 NiPoint3::operator*(const float fScalar) const noexcept {
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
}
//! Operator for scalar division of a vector
constexpr NiPoint3 NiPoint3::operator/(const float fScalar) const noexcept {
float retX = this->x != 0 ? this->x / fScalar : 0;
float retY = this->y != 0 ? this->y / fScalar : 0;
float retZ = this->z != 0 ? this->z / fScalar : 0;
return NiPoint3(retX, retY, retZ);
}
// MARK: Helper Functions
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
constexpr bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) noexcept {
if (this->x < minPoint.x) return false;
if (this->x > maxPoint.x) return false;
if (this->y < minPoint.y) return false;
if (this->y > maxPoint.y) return false;
return (this->z < maxPoint.z && this->z > minPoint.z);
}
//! Checks to see if the point (or vector) is within a sphere
constexpr bool NiPoint3::IsWithinSphere(const NiPoint3& sphereCenter, const float radius) noexcept {
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
return (diffVec.SquaredLength() <= (radius * radius));
}
constexpr NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) noexcept {
if (a == b) return a;
const auto pa = p - a;
const auto ab = b - a;
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
if (t <= 0.0f) return a;
if (t >= 1.0f) return b;
return a + ab * t;
}
constexpr float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) noexcept {
const auto dx = a.x - b.x;
const auto dy = a.y - b.y;
const auto dz = a.z - b.z;
return dx * dx + dy * dy + dz * dz;
}
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
constexpr NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) noexcept {
Vector3 vector;
float num12 = rotation.x + rotation.x;
float num2 = rotation.y + rotation.y;
float num = rotation.z + rotation.z;
float num11 = rotation.w * num12;
float num10 = rotation.w * num2;
float num9 = rotation.w * num;
float num8 = rotation.x * num12;
float num7 = rotation.x * num2;
float num6 = rotation.x * num;
float num5 = rotation.y * num2;
float num4 = rotation.y * num;
float num3 = rotation.z * num;
NiPoint3 value = *this;
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
vector.x = num15;
vector.y = num14;
vector.z = num13;
return vector;
}

View File

@ -3,89 +3,8 @@
// C++ // C++
#include <cmath> #include <cmath>
// Static Variables
const NiQuaternion NiQuaternion::IDENTITY(1, 0, 0, 0);
//! The initializer
NiQuaternion::NiQuaternion(void) {
this->w = 1;
this->x = 0;
this->y = 0;
this->z = 0;
}
//! The initializer
NiQuaternion::NiQuaternion(float w, float x, float y, float z) {
this->w = w;
this->x = x;
this->y = y;
this->z = z;
}
//! Destructor
NiQuaternion::~NiQuaternion(void) {}
// MARK: Setters / Getters
//! Gets the W coordinate
float NiQuaternion::GetW(void) const {
return this->w;
}
//! Sets the W coordinate
void NiQuaternion::SetW(float w) {
this->w = w;
}
//! Gets the X coordinate
float NiQuaternion::GetX(void) const {
return this->x;
}
//! Sets the X coordinate
void NiQuaternion::SetX(float x) {
this->x = x;
}
//! Gets the Y coordinate
float NiQuaternion::GetY(void) const {
return this->y;
}
//! Sets the Y coordinate
void NiQuaternion::SetY(float y) {
this->y = y;
}
//! Gets the Z coordinate
float NiQuaternion::GetZ(void) const {
return this->z;
}
//! Sets the Z coordinate
void NiQuaternion::SetZ(float z) {
this->z = z;
}
// MARK: Member Functions // MARK: Member Functions
//! Returns the forward vector from the quaternion
Vector3 NiQuaternion::GetForwardVector(void) const {
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
}
//! Returns the up vector from the quaternion
Vector3 NiQuaternion::GetUpVector(void) const {
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
}
//! Returns the right vector from the quaternion
Vector3 NiQuaternion::GetRightVector(void) const {
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
}
Vector3 NiQuaternion::GetEulerAngles() const { Vector3 NiQuaternion::GetEulerAngles() const {
Vector3 angles; Vector3 angles;
@ -111,22 +30,9 @@ Vector3 NiQuaternion::GetEulerAngles() const {
return angles; return angles;
} }
// MARK: Operators
//! Operator to check for equality
bool NiQuaternion::operator==(const NiQuaternion& rot) const {
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
}
//! Operator to check for inequality
bool NiQuaternion::operator!=(const NiQuaternion& rot) const {
return !(*this == rot);
}
// MARK: Helper Functions // MARK: Helper Functions
//! Look from a specific point in space to another point in space //! Look from a specific point in space to another point in space (Y-locked)
NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) { NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
//To make sure we don't orient around the X/Z axis: //To make sure we don't orient around the X/Z axis:
NiPoint3 source = sourcePoint; NiPoint3 source = sourcePoint;
@ -136,7 +42,7 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
NiPoint3 forwardVector = NiPoint3(dest - source).Unitize(); NiPoint3 forwardVector = NiPoint3(dest - source).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z; NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize(); NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
float dot = posZ.DotProduct(forwardVector); float dot = posZ.DotProduct(forwardVector);
@ -148,10 +54,11 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle); return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
} }
//! Look from a specific point in space to another point in space
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) { NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize(); NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z; NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize(); NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
float dot = posZ.DotProduct(forwardVector); float dot = posZ.DotProduct(forwardVector);

View File

@ -1,4 +1,5 @@
#pragma once #ifndef __NIQUATERNION_H__
#define __NIQUATERNION_H__
// Custom Classes // Custom Classes
#include "NiPoint3.h" #include "NiPoint3.h"
@ -14,14 +15,14 @@ typedef NiQuaternion Quaternion; //!< A typedef for a shorthand version o
//! A class that defines a rotation in space //! A class that defines a rotation in space
class NiQuaternion { class NiQuaternion {
public: public:
float w; //!< The w coordinate float w{ 1 }; //!< The w coordinate
float x; //!< The x coordinate float x{ 0 }; //!< The x coordinate
float y; //!< The y coordinate float y{ 0 }; //!< The y coordinate
float z; //!< The z coordinate float z{ 0 }; //!< The z coordinate
//! The initializer //! The initializer
NiQuaternion(void); constexpr NiQuaternion() = default;
//! The initializer //! The initializer
/*! /*!
@ -30,13 +31,12 @@ public:
\param y The y coordinate \param y The y coordinate
\param z The z coordinate \param z The z coordinate
*/ */
NiQuaternion(float w, float x, float y, float z); constexpr NiQuaternion(const float w, const float x, const float y, const float z) noexcept
: w{ w }
//! Destructor , x{ x }
~NiQuaternion(void); , y{ y }
, z{ z } {
// MARK: Constants }
static const NiQuaternion IDENTITY; //!< Quaternion(1, 0, 0, 0)
// MARK: Setters / Getters // MARK: Setters / Getters
@ -44,50 +44,49 @@ public:
/*! /*!
\return The w coordinate \return The w coordinate
*/ */
float GetW(void) const; [[nodiscard]] constexpr float GetW() const noexcept;
//! Sets the W coordinate //! Sets the W coordinate
/*! /*!
\param w The w coordinate \param w The w coordinate
*/ */
void SetW(float w); constexpr void SetW(const float w) noexcept;
//! Gets the X coordinate //! Gets the X coordinate
/*! /*!
\return The x coordinate \return The x coordinate
*/ */
float GetX(void) const; [[nodiscard]] constexpr float GetX() const noexcept;
//! Sets the X coordinate //! Sets the X coordinate
/*! /*!
\param x The x coordinate \param x The x coordinate
*/ */
void SetX(float x); constexpr void SetX(const float x) noexcept;
//! Gets the Y coordinate //! Gets the Y coordinate
/*! /*!
\return The y coordinate \return The y coordinate
*/ */
float GetY(void) const; [[nodiscard]] constexpr float GetY() const noexcept;
//! Sets the Y coordinate //! Sets the Y coordinate
/*! /*!
\param y The y coordinate \param y The y coordinate
*/ */
void SetY(float y); constexpr void SetY(const float y) noexcept;
//! Gets the Z coordinate //! Gets the Z coordinate
/*! /*!
\return The z coordinate \return The z coordinate
*/ */
float GetZ(void) const; [[nodiscard]] constexpr float GetZ() const noexcept;
//! Sets the Z coordinate //! Sets the Z coordinate
/*! /*!
\param z The z coordinate \param z The z coordinate
*/ */
void SetZ(float z); constexpr void SetZ(const float z) noexcept;
// MARK: Member Functions // MARK: Member Functions
@ -95,31 +94,29 @@ public:
/*! /*!
\return The forward vector of the quaternion \return The forward vector of the quaternion
*/ */
Vector3 GetForwardVector(void) const; [[nodiscard]] constexpr Vector3 GetForwardVector() const noexcept;
//! Returns the up vector from the quaternion //! Returns the up vector from the quaternion
/*! /*!
\return The up vector fo the quaternion \return The up vector fo the quaternion
*/ */
Vector3 GetUpVector(void) const; [[nodiscard]] constexpr Vector3 GetUpVector() const noexcept;
//! Returns the right vector from the quaternion //! Returns the right vector from the quaternion
/*! /*!
\return The right vector of the quaternion \return The right vector of the quaternion
*/ */
Vector3 GetRightVector(void) const; [[nodiscard]] constexpr Vector3 GetRightVector() const noexcept;
Vector3 GetEulerAngles() const;
[[nodiscard]] Vector3 GetEulerAngles() const;
// MARK: Operators // MARK: Operators
//! Operator to check for equality //! Operator to check for equality
bool operator==(const NiQuaternion& rot) const; constexpr bool operator==(const NiQuaternion& rot) const noexcept;
//! Operator to check for inequality //! Operator to check for inequality
bool operator!=(const NiQuaternion& rot) const; constexpr bool operator!=(const NiQuaternion& rot) const noexcept;
// MARK: Helper Functions // MARK: Helper Functions
@ -129,7 +126,7 @@ public:
\param destPoint The destination location \param destPoint The destination location
\return The Quaternion with the rotation towards the destination \return The Quaternion with the rotation towards the destination
*/ */
static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint); [[nodiscard]] static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
//! Look from a specific point in space to another point in space //! Look from a specific point in space to another point in space
/*! /*!
@ -137,7 +134,7 @@ public:
\param destPoint The destination location \param destPoint The destination location
\return The Quaternion with the rotation towards the destination \return The Quaternion with the rotation towards the destination
*/ */
static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint); [[nodiscard]] static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
//! Creates a Quaternion from a specific axis and angle relative to that axis //! Creates a Quaternion from a specific axis and angle relative to that axis
/*! /*!
@ -145,7 +142,17 @@ public:
\param angle The angle relative to this axis \param angle The angle relative to this axis
\return A quaternion created from the axis and angle \return A quaternion created from the axis and angle
*/ */
static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle); [[nodiscard]] static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle);
static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles); [[nodiscard]] static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles);
}; };
// Static Variables
namespace NiQuaternionConstant {
constexpr NiQuaternion IDENTITY(1, 0, 0, 0);
}
// Include constexpr and inline function definitions in a seperate file for readability
#include "NiQuaternion.inl"
#endif // !__NIQUATERNION_H__

75
dCommon/NiQuaternion.inl Normal file
View File

@ -0,0 +1,75 @@
#pragma once
#ifndef __NIQUATERNION_H__
#error "This should only be included inline in NiQuaternion.h: Do not include directly!"
#endif
// MARK: Setters / Getters
//! Gets the W coordinate
constexpr float NiQuaternion::GetW() const noexcept {
return this->w;
}
//! Sets the W coordinate
constexpr void NiQuaternion::SetW(const float w) noexcept {
this->w = w;
}
//! Gets the X coordinate
constexpr float NiQuaternion::GetX() const noexcept {
return this->x;
}
//! Sets the X coordinate
constexpr void NiQuaternion::SetX(const float x) noexcept {
this->x = x;
}
//! Gets the Y coordinate
constexpr float NiQuaternion::GetY() const noexcept {
return this->y;
}
//! Sets the Y coordinate
constexpr void NiQuaternion::SetY(const float y) noexcept {
this->y = y;
}
//! Gets the Z coordinate
constexpr float NiQuaternion::GetZ() const noexcept {
return this->z;
}
//! Sets the Z coordinate
constexpr void NiQuaternion::SetZ(const float z) noexcept {
this->z = z;
}
// MARK: Member Functions
//! Returns the forward vector from the quaternion
constexpr Vector3 NiQuaternion::GetForwardVector() const noexcept {
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
}
//! Returns the up vector from the quaternion
constexpr Vector3 NiQuaternion::GetUpVector() const noexcept {
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
}
//! Returns the right vector from the quaternion
constexpr Vector3 NiQuaternion::GetRightVector() const noexcept {
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
}
// MARK: Operators
//! Operator to check for equality
constexpr bool NiQuaternion::operator==(const NiQuaternion& rot) const noexcept {
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
}
//! Operator to check for inequality
constexpr bool NiQuaternion::operator!=(const NiQuaternion& rot) const noexcept {
return !(*this == rot);
}

View File

@ -6,43 +6,29 @@
struct RemoteInputInfo { struct RemoteInputInfo {
RemoteInputInfo() {
m_RemoteInputX = 0;
m_RemoteInputY = 0;
m_IsPowersliding = false;
m_IsModified = false;
}
void operator=(const RemoteInputInfo& other) {
m_RemoteInputX = other.m_RemoteInputX;
m_RemoteInputY = other.m_RemoteInputY;
m_IsPowersliding = other.m_IsPowersliding;
m_IsModified = other.m_IsModified;
}
bool operator==(const RemoteInputInfo& other) { bool operator==(const RemoteInputInfo& other) {
return m_RemoteInputX == other.m_RemoteInputX && m_RemoteInputY == other.m_RemoteInputY && m_IsPowersliding == other.m_IsPowersliding && m_IsModified == other.m_IsModified; return m_RemoteInputX == other.m_RemoteInputX && m_RemoteInputY == other.m_RemoteInputY && m_IsPowersliding == other.m_IsPowersliding && m_IsModified == other.m_IsModified;
} }
float m_RemoteInputX; float m_RemoteInputX = 0;
float m_RemoteInputY; float m_RemoteInputY = 0;
bool m_IsPowersliding; bool m_IsPowersliding = false;
bool m_IsModified; bool m_IsModified = false;
}; };
struct LocalSpaceInfo { struct LocalSpaceInfo {
LWOOBJID objectId = LWOOBJID_EMPTY; LWOOBJID objectId = LWOOBJID_EMPTY;
NiPoint3 position = NiPoint3::ZERO; NiPoint3 position = NiPoint3Constant::ZERO;
NiPoint3 linearVelocity = NiPoint3::ZERO; NiPoint3 linearVelocity = NiPoint3Constant::ZERO;
}; };
struct PositionUpdate { struct PositionUpdate {
NiPoint3 position = NiPoint3::ZERO; NiPoint3 position = NiPoint3Constant::ZERO;
NiQuaternion rotation = NiQuaternion::IDENTITY; NiQuaternion rotation = NiQuaternionConstant::IDENTITY;
bool onGround = false; bool onGround = false;
bool onRail = false; bool onRail = false;
NiPoint3 velocity = NiPoint3::ZERO; NiPoint3 velocity = NiPoint3Constant::ZERO;
NiPoint3 angularVelocity = NiPoint3::ZERO; NiPoint3 angularVelocity = NiPoint3Constant::ZERO;
LocalSpaceInfo localSpaceInfo; LocalSpaceInfo localSpaceInfo;
RemoteInputInfo remoteInputInfo; RemoteInputInfo remoteInputInfo;
}; };

View File

@ -1,154 +0,0 @@
// Source: http://www.zedwood.com/article/cpp-sha512-function
#include "SHA512.h"
#include <cstring>
#include <fstream>
const unsigned long long SHA512::sha512_k[80] = //ULL = uint64
{ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
void SHA512::transform(const unsigned char* message, unsigned int block_nb) {
uint64 w[80];
uint64 wv[8];
uint64 t1, t2;
const unsigned char* sub_block;
int i, j;
for (i = 0; i < (int)block_nb; i++) {
sub_block = message + (i << 7);
for (j = 0; j < 16; j++) {
SHA2_PACK64(&sub_block[j << 3], &w[j]);
}
for (j = 16; j < 80; j++) {
w[j] = SHA512_F4(w[j - 2]) + w[j - 7] + SHA512_F3(w[j - 15]) + w[j - 16];
}
for (j = 0; j < 8; j++) {
wv[j] = m_h[j];
}
for (j = 0; j < 80; j++) {
t1 = wv[7] + SHA512_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])
+ sha512_k[j] + w[j];
t2 = SHA512_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
m_h[j] += wv[j];
}
}
}
void SHA512::init() {
m_h[0] = 0x6a09e667f3bcc908ULL;
m_h[1] = 0xbb67ae8584caa73bULL;
m_h[2] = 0x3c6ef372fe94f82bULL;
m_h[3] = 0xa54ff53a5f1d36f1ULL;
m_h[4] = 0x510e527fade682d1ULL;
m_h[5] = 0x9b05688c2b3e6c1fULL;
m_h[6] = 0x1f83d9abfb41bd6bULL;
m_h[7] = 0x5be0cd19137e2179ULL;
m_len = 0;
m_tot_len = 0;
}
void SHA512::update(const unsigned char* message, unsigned int len) {
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char* shifted_message;
tmp_len = SHA384_512_BLOCK_SIZE - m_len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&m_block[m_len], message, rem_len);
if (m_len + len < SHA384_512_BLOCK_SIZE) {
m_len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA384_512_BLOCK_SIZE;
shifted_message = message + rem_len;
transform(m_block, 1);
transform(shifted_message, block_nb);
rem_len = new_len % SHA384_512_BLOCK_SIZE;
memcpy(m_block, &shifted_message[block_nb << 7], rem_len);
m_len = rem_len;
m_tot_len += (block_nb + 1) << 7;
}
void SHA512::final(unsigned char* digest) {
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = 1 + ((SHA384_512_BLOCK_SIZE - 17)
< (m_len % SHA384_512_BLOCK_SIZE));
len_b = (m_tot_len + m_len) << 3;
pm_len = block_nb << 7;
memset(m_block + m_len, 0, pm_len - m_len);
m_block[m_len] = 0x80;
SHA2_UNPACK32(len_b, m_block + pm_len - 4);
transform(m_block, block_nb);
for (i = 0; i < 8; i++) {
SHA2_UNPACK64(m_h[i], &digest[i << 3]);
}
}
std::string sha512(std::string input) {
unsigned char digest[SHA512::DIGEST_SIZE];
memset(digest, 0, SHA512::DIGEST_SIZE);
class SHA512 ctx;
ctx.init();
ctx.update((unsigned char*)input.c_str(), input.length());
ctx.final(digest);
char buf[2 * SHA512::DIGEST_SIZE + 1];
buf[2 * SHA512::DIGEST_SIZE] = 0;
for (int i = 0; i < SHA512::DIGEST_SIZE; i++)
sprintf(buf + i * 2, "%02x", digest[i]);
return std::string(buf);
}

View File

@ -1,68 +0,0 @@
#pragma once
// C++
#include <string>
class SHA512 {
protected:
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
const static uint64 sha512_k[];
static const unsigned int SHA384_512_BLOCK_SIZE = (1024 / 8);
public:
void init();
void update(const unsigned char* message, unsigned int len);
void final(unsigned char* digest);
static const unsigned int DIGEST_SIZE = (512 / 8);
protected:
void transform(const unsigned char* message, unsigned int block_nb);
unsigned int m_tot_len;
unsigned int m_len;
unsigned char m_block[2 * SHA384_512_BLOCK_SIZE];
uint64 m_h[8];
};
std::string sha512(std::string input);
#define SHA2_SHFR(x, n) (x >> n)
#define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
#define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA512_F1(x) (SHA2_ROTR(x, 28) ^ SHA2_ROTR(x, 34) ^ SHA2_ROTR(x, 39))
#define SHA512_F2(x) (SHA2_ROTR(x, 14) ^ SHA2_ROTR(x, 18) ^ SHA2_ROTR(x, 41))
#define SHA512_F3(x) (SHA2_ROTR(x, 1) ^ SHA2_ROTR(x, 8) ^ SHA2_SHFR(x, 7))
#define SHA512_F4(x) (SHA2_ROTR(x, 19) ^ SHA2_ROTR(x, 61) ^ SHA2_SHFR(x, 6))
#define SHA2_UNPACK32(x, str) \
{ \
*((str) + 3) = (uint8) ((x) ); \
*((str) + 2) = (uint8) ((x) >> 8); \
*((str) + 1) = (uint8) ((x) >> 16); \
*((str) + 0) = (uint8) ((x) >> 24); \
}
#define SHA2_UNPACK64(x, str) \
{ \
*((str) + 7) = (uint8) ((x) ); \
*((str) + 6) = (uint8) ((x) >> 8); \
*((str) + 5) = (uint8) ((x) >> 16); \
*((str) + 4) = (uint8) ((x) >> 24); \
*((str) + 3) = (uint8) ((x) >> 32); \
*((str) + 2) = (uint8) ((x) >> 40); \
*((str) + 1) = (uint8) ((x) >> 48); \
*((str) + 0) = (uint8) ((x) >> 56); \
}
#define SHA2_PACK64(str, x) \
{ \
*(x) = ((uint64) *((str) + 7) ) \
| ((uint64) *((str) + 6) << 8) \
| ((uint64) *((str) + 5) << 16) \
| ((uint64) *((str) + 4) << 24) \
| ((uint64) *((str) + 3) << 32) \
| ((uint64) *((str) + 2) << 40) \
| ((uint64) *((str) + 1) << 48) \
| ((uint64) *((str) + 0) << 56); \
}

View File

@ -1,6 +1,6 @@
set(DCOMMON_DCLIENT_SOURCES set(DCOMMON_DCLIENT_SOURCES
"AssetManager.cpp"
"PackIndex.cpp" "PackIndex.cpp"
"Pack.cpp" "Pack.cpp"
"AssetManager.cpp"
PARENT_SCOPE PARENT_SCOPE
) )

View File

@ -0,0 +1,12 @@
#ifndef __CLIENTVERSION_H__
#define __CLIENTVERSION_H__
#include <cstdint>
namespace ClientVersion {
constexpr uint16_t major = 1;
constexpr uint16_t current = 10;
constexpr uint16_t minor = 64;
}
#endif // !__CLIENTVERSION_H__

View File

@ -9,15 +9,15 @@ namespace StringifiedEnum {
const std::string_view ToString(const T e) { const std::string_view ToString(const T e) {
static_assert(std::is_enum_v<T>, "Not an enum"); // Check type static_assert(std::is_enum_v<T>, "Not an enum"); // Check type
constexpr auto sv = &magic_enum::enum_entries<T>(); constexpr auto& sv = magic_enum::enum_entries<T>();
const auto it = std::lower_bound( const auto it = std::lower_bound(
sv->begin(), sv->end(), e, sv.begin(), sv.end(), e,
[&](const std::pair<T, std::string_view>& lhs, const T rhs) { return lhs.first < rhs; } [&](const std::pair<T, std::string_view>& lhs, const T rhs) { return lhs.first < rhs; }
); );
std::string_view output; std::string_view output;
if (it != sv->end() && it->first == e) { if (it != sv.end() && it->first == e) {
output = it->second; output = it->second;
} else { } else {
output = "UNKNOWN"; output = "UNKNOWN";

View File

@ -34,91 +34,89 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false); #define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits()); #define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); #define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false); #define SEND_PACKET Game::server->Send(bitStream, sysAddr, false);
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); #define SEND_PACKET_BROADCAST Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
//=========== TYPEDEFS ========== //=========== TYPEDEFS ==========
typedef int32_t LOT; //!< A LOT using LOT = int32_t; //!< A LOT
typedef int64_t LWOOBJID; //!< An object ID (should be unsigned actually but ok) using LWOOBJID = int64_t; //!< An object ID (should be unsigned actually but ok)
typedef int32_t TSkillID; //!< A skill ID using TSkillID = int32_t; //!< A skill ID
typedef uint32_t LWOCLONEID; //!< Used for Clone IDs using LWOCLONEID = uint32_t; //!< Used for Clone IDs
typedef uint16_t LWOMAPID; //!< Used for Map IDs using LWOMAPID = uint16_t; //!< Used for Map IDs
typedef uint16_t LWOINSTANCEID; //!< Used for Instance IDs using LWOINSTANCEID = uint16_t; //!< Used for Instance IDs
typedef uint32_t PROPERTYCLONELIST; //!< Used for Property Clone IDs using PROPERTYCLONELIST = uint32_t; //!< Used for Property Clone IDs
typedef uint32_t StripId; using StripId = uint32_t;
const LWOOBJID LWOOBJID_EMPTY = 0; //!< An empty object ID constexpr LWOOBJID LWOOBJID_EMPTY = 0; //!< An empty object ID
const LOT LOT_NULL = -1; //!< A null LOT constexpr LOT LOT_NULL = -1; //!< A null LOT
const int32_t LOOTTYPE_NONE = 0; //!< No loot type available constexpr int32_t LOOTTYPE_NONE = 0; //!< No loot type available
const float SECONDARY_PRIORITY = 1.0f; //!< Secondary Priority constexpr float SECONDARY_PRIORITY = 1.0f; //!< Secondary Priority
const uint32_t INVENTORY_MAX = 9999999; //!< The Maximum Inventory Size constexpr uint32_t INVENTORY_MAX = 9999999; //!< The Maximum Inventory Size
const uint32_t LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID constexpr LWOCLONEID LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID
const uint16_t LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID constexpr LWOINSTANCEID LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID
const uint16_t LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID constexpr LWOMAPID LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID
const uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID constexpr uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID
const float PI = 3.14159f; constexpr float PI = 3.14159f;
//============ STRUCTS ============== //============ STRUCTS ==============
struct LWOSCENEID { struct LWOSCENEID {
public: public:
LWOSCENEID() { m_sceneID = -1; m_layerID = 0; } constexpr LWOSCENEID() noexcept { m_sceneID = -1; m_layerID = 0; }
LWOSCENEID(int sceneID) { m_sceneID = sceneID; m_layerID = 0; } constexpr LWOSCENEID(int32_t sceneID) noexcept { m_sceneID = sceneID; m_layerID = 0; }
LWOSCENEID(int sceneID, unsigned int layerID) { m_sceneID = sceneID; m_layerID = layerID; } constexpr LWOSCENEID(int32_t sceneID, uint32_t layerID) noexcept { m_sceneID = sceneID; m_layerID = layerID; }
LWOSCENEID& operator=(const LWOSCENEID& rhs) { m_sceneID = rhs.m_sceneID; m_layerID = rhs.m_layerID; return *this; } constexpr LWOSCENEID& operator=(const LWOSCENEID& rhs) noexcept { m_sceneID = rhs.m_sceneID; m_layerID = rhs.m_layerID; return *this; }
LWOSCENEID& operator=(const int rhs) { m_sceneID = rhs; m_layerID = 0; return *this; } constexpr LWOSCENEID& operator=(const int32_t rhs) noexcept { m_sceneID = rhs; m_layerID = 0; return *this; }
bool operator<(const LWOSCENEID& rhs) const { return (m_sceneID < rhs.m_sceneID || (m_sceneID == rhs.m_sceneID && m_layerID < rhs.m_layerID)); } constexpr bool operator<(const LWOSCENEID& rhs) const noexcept { return (m_sceneID < rhs.m_sceneID || (m_sceneID == rhs.m_sceneID && m_layerID < rhs.m_layerID)); }
bool operator<(const int rhs) const { return m_sceneID < rhs; } constexpr bool operator<(const int32_t rhs) const noexcept { return m_sceneID < rhs; }
bool operator==(const LWOSCENEID& rhs) const { return (m_sceneID == rhs.m_sceneID && m_layerID == rhs.m_layerID); } constexpr bool operator==(const LWOSCENEID& rhs) const noexcept { return (m_sceneID == rhs.m_sceneID && m_layerID == rhs.m_layerID); }
bool operator==(const int rhs) const { return m_sceneID == rhs; } constexpr bool operator==(const int32_t rhs) const noexcept { return m_sceneID == rhs; }
const int GetSceneID() const { return m_sceneID; } constexpr int32_t GetSceneID() const noexcept { return m_sceneID; }
const unsigned int GetLayerID() const { return m_layerID; } constexpr uint32_t GetLayerID() const noexcept { return m_layerID; }
void SetSceneID(const int sceneID) { m_sceneID = sceneID; } constexpr void SetSceneID(const int32_t sceneID) noexcept { m_sceneID = sceneID; }
void SetLayerID(const unsigned int layerID) { m_layerID = layerID; } constexpr void SetLayerID(const uint32_t layerID) noexcept { m_layerID = layerID; }
private: private:
int m_sceneID; int32_t m_sceneID;
unsigned int m_layerID; uint32_t m_layerID;
}; };
struct LWOZONEID { struct LWOZONEID {
public: public:
const LWOMAPID& GetMapID() const { return m_MapID; } constexpr const LWOMAPID& GetMapID() const noexcept { return m_MapID; }
const LWOINSTANCEID& GetInstanceID() const { return m_InstanceID; } constexpr const LWOINSTANCEID& GetInstanceID() const noexcept { return m_InstanceID; }
const LWOCLONEID& GetCloneID() const { return m_CloneID; } constexpr const LWOCLONEID& GetCloneID() const noexcept { return m_CloneID; }
//In order: def constr, constr, assign op //In order: def constr, constr, assign op
LWOZONEID() { m_MapID = LWOMAPID_INVALID; m_InstanceID = LWOINSTANCEID_INVALID; m_CloneID = LWOCLONEID_INVALID; } constexpr LWOZONEID() noexcept = default;
LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; } constexpr LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) noexcept { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; }
LWOZONEID(const LWOZONEID& replacement) { *this = replacement; } constexpr LWOZONEID(const LWOZONEID& replacement) noexcept { *this = replacement; }
private: private:
LWOMAPID m_MapID; //1000 for VE, 1100 for AG, etc... LWOMAPID m_MapID = LWOMAPID_INVALID; //1000 for VE, 1100 for AG, etc...
LWOINSTANCEID m_InstanceID; //Instances host the same world, but on a different dWorld process. LWOINSTANCEID m_InstanceID = LWOINSTANCEID_INVALID; //Instances host the same world, but on a different dWorld process.
LWOCLONEID m_CloneID; //To differentiate between "your property" and "my property". Always 0 for non-prop worlds. LWOCLONEID m_CloneID = LWOCLONEID_INVALID; //To differentiate between "your property" and "my property". Always 0 for non-prop worlds.
}; };
const LWOSCENEID LWOSCENEID_INVALID = -1; constexpr LWOSCENEID LWOSCENEID_INVALID = -1;
struct LWONameValue { struct LWONameValue {
uint32_t length = 0; //!< The length of the name uint32_t length = 0; //!< The length of the name
std::u16string name; //!< The name std::u16string name; //!< The name
LWONameValue(void) {} LWONameValue() = default;
LWONameValue(const std::u16string& name) { LWONameValue(const std::u16string& name) {
this->name = name; this->name = name;
this->length = static_cast<uint32_t>(name.length()); this->length = static_cast<uint32_t>(name.length());
} }
~LWONameValue(void) {}
}; };
struct FriendData { struct FriendData {

View File

@ -106,7 +106,7 @@ enum class eReplicaComponentType : uint32_t {
INTERACTION_MANAGER, INTERACTION_MANAGER,
DONATION_VENDOR, DONATION_VENDOR,
COMBAT_MEDIATOR, COMBAT_MEDIATOR,
COMMENDATION_VENDOR, ACHIEVEMENT_VENDOR,
GATE_RUSH_CONTROL, GATE_RUSH_CONTROL,
RAIL_ACTIVATOR, RAIL_ACTIVATOR,
ROLLER, ROLLER,

View File

@ -0,0 +1,15 @@
#ifndef __EVENDORTRANSACTIONRESULT__
#define __EVENDORTRANSACTIONRESULT__
#include <cstdint>
enum class eVendorTransactionResult : uint32_t {
SELL_SUCCESS = 0,
SELL_FAIL,
PURCHASE_SUCCESS,
PURCHASE_FAIL,
DONATION_FAIL,
DONATION_FULL
};
#endif // !__EVENDORTRANSACTIONRESULT__

View File

@ -0,0 +1,59 @@
#ifndef __EWAYPOINTCOMMANDTYPES__H__
#define __EWAYPOINTCOMMANDTYPES__H__
#include <cstdint>
enum class eWaypointCommandType : uint32_t {
INVALID,
BOUNCE,
STOP,
GROUP_EMOTE,
SET_VARIABLE,
CAST_SKILL,
EQUIP_INVENTORY,
UNEQUIP_INVENTORY,
DELAY,
EMOTE,
TELEPORT,
PATH_SPEED,
REMOVE_NPC,
CHANGE_WAYPOINT,
DELETE_SELF,
KILL_SELF,
SPAWN_OBJECT,
PLAY_SOUND,
};
class WaypointCommandType {
public:
static eWaypointCommandType StringToWaypointCommandType(std::string commandString) {
const std::map<std::string, eWaypointCommandType> WaypointCommandTypeMap = {
{"bounce", eWaypointCommandType::BOUNCE},
{"stop", eWaypointCommandType::STOP},
{"groupemote", eWaypointCommandType::GROUP_EMOTE},
{"setvar", eWaypointCommandType::SET_VARIABLE},
{"castskill", eWaypointCommandType::CAST_SKILL},
{"eqInvent", eWaypointCommandType::EQUIP_INVENTORY},
{"unInvent", eWaypointCommandType::UNEQUIP_INVENTORY},
{"delay", eWaypointCommandType::DELAY},
{"femote", eWaypointCommandType::EMOTE},
{"emote", eWaypointCommandType::EMOTE},
{"teleport", eWaypointCommandType::TELEPORT},
{"pathspeed", eWaypointCommandType::PATH_SPEED},
{"removeNPC", eWaypointCommandType::REMOVE_NPC},
{"changeWP", eWaypointCommandType::CHANGE_WAYPOINT},
{"DeleteSelf", eWaypointCommandType::DELETE_SELF},
{"killself", eWaypointCommandType::KILL_SELF},
{"removeself", eWaypointCommandType::DELETE_SELF},
{"spawnOBJ", eWaypointCommandType::SPAWN_OBJECT},
{"playSound", eWaypointCommandType::PLAY_SOUND},
};
auto intermed = WaypointCommandTypeMap.find(commandString);
return (intermed != WaypointCommandTypeMap.end()) ? intermed->second : eWaypointCommandType::INVALID;
};
};
#endif //!__EWAYPOINTCOMMANDTYPES__H__

View File

@ -39,6 +39,7 @@
#include "CDFeatureGatingTable.h" #include "CDFeatureGatingTable.h"
#include "CDRailActivatorComponent.h" #include "CDRailActivatorComponent.h"
#include "CDRewardCodesTable.h" #include "CDRewardCodesTable.h"
#include "CDPetComponentTable.h"
#include <exception> #include <exception>
@ -61,6 +62,55 @@ public:
} }
}; };
// Using a macro to reduce repetitive code and issues from copy and paste.
// As a note, ## in a macro is used to concatenate two tokens together.
#define SPECIALIZE_TABLE_STORAGE(table) \
template<> typename table::StorageType& CDClientManager::GetEntriesMutable<table>() { return table##Entries; };
#define DEFINE_TABLE_STORAGE(table) namespace { table::StorageType table##Entries; }; SPECIALIZE_TABLE_STORAGE(table)
DEFINE_TABLE_STORAGE(CDActivityRewardsTable);
DEFINE_TABLE_STORAGE(CDActivitiesTable);
DEFINE_TABLE_STORAGE(CDAnimationsTable);
DEFINE_TABLE_STORAGE(CDBehaviorParameterTable);
DEFINE_TABLE_STORAGE(CDBehaviorTemplateTable);
DEFINE_TABLE_STORAGE(CDBrickIDTableTable);
DEFINE_TABLE_STORAGE(CDComponentsRegistryTable);
DEFINE_TABLE_STORAGE(CDCurrencyTableTable);
DEFINE_TABLE_STORAGE(CDDestructibleComponentTable);
DEFINE_TABLE_STORAGE(CDEmoteTableTable);
DEFINE_TABLE_STORAGE(CDFeatureGatingTable);
DEFINE_TABLE_STORAGE(CDInventoryComponentTable);
DEFINE_TABLE_STORAGE(CDItemComponentTable);
DEFINE_TABLE_STORAGE(CDItemSetSkillsTable);
DEFINE_TABLE_STORAGE(CDItemSetsTable);
DEFINE_TABLE_STORAGE(CDLevelProgressionLookupTable);
DEFINE_TABLE_STORAGE(CDLootMatrixTable);
DEFINE_TABLE_STORAGE(CDLootTableTable);
DEFINE_TABLE_STORAGE(CDMissionEmailTable);
DEFINE_TABLE_STORAGE(CDMissionNPCComponentTable);
DEFINE_TABLE_STORAGE(CDMissionTasksTable);
DEFINE_TABLE_STORAGE(CDMissionsTable);
DEFINE_TABLE_STORAGE(CDMovementAIComponentTable);
DEFINE_TABLE_STORAGE(CDObjectSkillsTable);
DEFINE_TABLE_STORAGE(CDObjectsTable);
DEFINE_TABLE_STORAGE(CDPhysicsComponentTable);
DEFINE_TABLE_STORAGE(CDPackageComponentTable);
DEFINE_TABLE_STORAGE(CDPetComponentTable);
DEFINE_TABLE_STORAGE(CDProximityMonitorComponentTable);
DEFINE_TABLE_STORAGE(CDPropertyEntranceComponentTable);
DEFINE_TABLE_STORAGE(CDPropertyTemplateTable);
DEFINE_TABLE_STORAGE(CDRailActivatorComponentTable);
DEFINE_TABLE_STORAGE(CDRarityTableTable);
DEFINE_TABLE_STORAGE(CDRebuildComponentTable);
DEFINE_TABLE_STORAGE(CDRewardCodesTable);
DEFINE_TABLE_STORAGE(CDRewardsTable);
DEFINE_TABLE_STORAGE(CDScriptComponentTable);
DEFINE_TABLE_STORAGE(CDSkillBehaviorTable);
DEFINE_TABLE_STORAGE(CDVendorComponentTable);
DEFINE_TABLE_STORAGE(CDZoneTableTable);
void CDClientManager::LoadValuesFromDatabase() { void CDClientManager::LoadValuesFromDatabase() {
if (!CDClientDatabase::isConnected) throw CDClientConnectionException(); if (!CDClientDatabase::isConnected) throw CDClientConnectionException();

View File

@ -1,18 +1,12 @@
#pragma once #ifndef __CDCLIENTMANAGER__H__
#define __CDCLIENTMANAGER__H__
#include "CDTable.h"
#include "Singleton.h"
#define UNUSED_TABLE(v) #define UNUSED_TABLE(v)
/** /**
* Initialize the CDClient tables so they are all loaded into memory. * Initialize the CDClient tables so they are all loaded into memory.
*/ */
class CDClientManager : public Singleton<CDClientManager> { namespace CDClientManager {
public:
CDClientManager() = default;
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
void LoadValuesFromDefaults(); void LoadValuesFromDefaults();
@ -23,7 +17,28 @@ public:
* @return A pointer to the requested table. * @return A pointer to the requested table.
*/ */
template<typename T> template<typename T>
T* GetTable() { T* GetTable();
return &T::Instance();
} /**
* Fetch a table from CDClient
* Note: Calling this function without a template specialization in CDClientManager.cpp will cause a linker error.
*
* @tparam Table type to fetch
* @return A pointer to the requested table.
*/
template<typename T>
typename T::StorageType& GetEntriesMutable();
}; };
// These are included after the CDClientManager namespace declaration as CDTable as of Jan 29 2024 relies on CDClientManager in Templated code.
#include "CDTable.h"
#include "Singleton.h"
template<typename T>
T* CDClientManager::GetTable() {
return &T::Instance();
};
#endif //!__CDCLIENTMANAGER__H__

View File

@ -1,5 +1,6 @@
#include "CDActivitiesTable.h" #include "CDActivitiesTable.h"
void CDActivitiesTable::LoadValuesFromDatabase() { void CDActivitiesTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
uint32_t size = 0; uint32_t size = 0;
@ -13,7 +14,8 @@ void CDActivitiesTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Activities"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Activities");
@ -39,7 +41,7 @@ void CDActivitiesTable::LoadValuesFromDatabase() {
entry.noTeamLootOnDeath = tableData.getIntField("noTeamLootOnDeath", -1); entry.noTeamLootOnDeath = tableData.getIntField("noTeamLootOnDeath", -1);
entry.optionalPercentage = tableData.getFloatField("optionalPercentage", -1.0f); entry.optionalPercentage = tableData.getFloatField("optionalPercentage", -1.0f);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -48,7 +50,7 @@ void CDActivitiesTable::LoadValuesFromDatabase() {
std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActivities)> predicate) { std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActivities)> predicate) {
std::vector<CDActivities> data = cpplinq::from(this->entries) std::vector<CDActivities> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();

View File

@ -25,15 +25,10 @@ struct CDActivities {
float optionalPercentage; float optionalPercentage;
}; };
class CDActivitiesTable : public CDTable<CDActivitiesTable> { class CDActivitiesTable : public CDTable<CDActivitiesTable, std::vector<CDActivities>> {
private:
std::vector<CDActivities> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate); std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
const std::vector<CDActivities>& GetEntries() const { return this->entries; }
}; };

View File

@ -1,5 +1,6 @@
#include "CDActivityRewardsTable.h" #include "CDActivityRewardsTable.h"
void CDActivityRewardsTable::LoadValuesFromDatabase() { void CDActivityRewardsTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
@ -14,7 +15,8 @@ void CDActivityRewardsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ActivityRewards"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ActivityRewards");
@ -28,7 +30,7 @@ void CDActivityRewardsTable::LoadValuesFromDatabase() {
entry.ChallengeRating = tableData.getIntField("ChallengeRating", -1); entry.ChallengeRating = tableData.getIntField("ChallengeRating", -1);
entry.description = tableData.getStringField("description", ""); entry.description = tableData.getStringField("description", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -37,7 +39,7 @@ void CDActivityRewardsTable::LoadValuesFromDatabase() {
std::vector<CDActivityRewards> CDActivityRewardsTable::Query(std::function<bool(CDActivityRewards)> predicate) { std::vector<CDActivityRewards> CDActivityRewardsTable::Query(std::function<bool(CDActivityRewards)> predicate) {
std::vector<CDActivityRewards> data = cpplinq::from(this->entries) std::vector<CDActivityRewards> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();

View File

@ -13,15 +13,9 @@ struct CDActivityRewards {
std::string description; //!< The description std::string description; //!< The description
}; };
class CDActivityRewardsTable : public CDTable<CDActivityRewardsTable> { class CDActivityRewardsTable : public CDTable<CDActivityRewardsTable, std::vector<CDActivityRewards>> {
private:
std::vector<CDActivityRewards> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate); std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
std::vector<CDActivityRewards> GetEntries() const;
}; };

View File

@ -5,6 +5,7 @@
void CDAnimationsTable::LoadValuesFromDatabase() { void CDAnimationsTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations");
auto& animations = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
std::string animation_type = tableData.getStringField("animation_type", ""); std::string animation_type = tableData.getStringField("animation_type", "");
DluAssert(!animation_type.empty()); DluAssert(!animation_type.empty());
@ -24,7 +25,7 @@ void CDAnimationsTable::LoadValuesFromDatabase() {
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);) UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);) UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry); animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -35,6 +36,7 @@ bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
auto tableData = queryToCache.execQuery(); auto tableData = queryToCache.execQuery();
// If we received a bad lookup, cache it anyways so we do not run the query again. // If we received a bad lookup, cache it anyways so we do not run the query again.
if (tableData.eof()) return false; if (tableData.eof()) return false;
auto& animations = GetEntriesMutable();
do { do {
std::string animation_type = tableData.getStringField("animation_type", ""); std::string animation_type = tableData.getStringField("animation_type", "");
@ -55,7 +57,7 @@ bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);) UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);) UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry); animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
tableData.nextRow(); tableData.nextRow();
} while (!tableData.eof()); } while (!tableData.eof());
@ -68,15 +70,17 @@ void CDAnimationsTable::CacheAnimations(const CDAnimationKey animationKey) {
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ? and animation_type = ?"); auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ? and animation_type = ?");
query.bind(1, static_cast<int32_t>(animationKey.second)); query.bind(1, static_cast<int32_t>(animationKey.second));
query.bind(2, animationKey.first.c_str()); query.bind(2, animationKey.first.c_str());
auto& animations = GetEntriesMutable();
// If we received a bad lookup, cache it anyways so we do not run the query again. // If we received a bad lookup, cache it anyways so we do not run the query again.
if (!CacheData(query)) { if (!CacheData(query)) {
this->animations[animationKey]; animations[animationKey];
} }
} }
void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) { void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) {
auto animationEntryCached = this->animations.find(CDAnimationKey("", animationGroupID)); auto& animations = GetEntriesMutable();
if (animationEntryCached != this->animations.end()) { auto animationEntryCached = animations.find(CDAnimationKey("", animationGroupID));
if (animationEntryCached != animations.end()) {
return; return;
} }
@ -85,28 +89,29 @@ void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) {
// Cache the query so we don't run the query again. // Cache the query so we don't run the query again.
CacheData(query); CacheData(query);
this->animations[CDAnimationKey("", animationGroupID)]; animations[CDAnimationKey("", animationGroupID)];
} }
CDAnimationLookupResult CDAnimationsTable::GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID) { std::optional<CDAnimation> CDAnimationsTable::GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID) {
auto& animations = GetEntriesMutable();
CDAnimationKey animationKey(animationType, animationGroupID); CDAnimationKey animationKey(animationType, animationGroupID);
auto animationEntryCached = this->animations.find(animationKey); auto animationEntryCached = animations.find(animationKey);
if (animationEntryCached == this->animations.end()) { if (animationEntryCached == animations.end()) {
this->CacheAnimations(animationKey); this->CacheAnimations(animationKey);
} }
auto animationEntry = this->animations.find(animationKey); auto animationEntry = animations.find(animationKey);
// If we have only one animation, return it regardless of the chance to play. // If we have only one animation, return it regardless of the chance to play.
if (animationEntry->second.size() == 1) { if (animationEntry->second.size() == 1) {
return CDAnimationLookupResult(animationEntry->second.front()); return animationEntry->second.front();
} }
auto randomAnimation = GeneralUtils::GenerateRandomNumber<float>(0, 1); auto randomAnimation = GeneralUtils::GenerateRandomNumber<float>(0, 1);
for (auto& animationEntry : animationEntry->second) { for (auto& animationEntry : animationEntry->second) {
randomAnimation -= animationEntry.chance_to_play; randomAnimation -= animationEntry.chance_to_play;
// This is how the client gets the random animation. // This is how the client gets the random animation.
if (animationEntry.animation_name != previousAnimationName && randomAnimation <= 0.0f) return CDAnimationLookupResult(animationEntry); if (animationEntry.animation_name != previousAnimationName && randomAnimation <= 0.0f) return animationEntry;
} }
return CDAnimationLookupResult(); return std::nullopt;
} }

View File

@ -2,6 +2,11 @@
#include "CDTable.h" #include "CDTable.h"
#include <list> #include <list>
#include <optional>
typedef int32_t AnimationGroupID;
typedef std::string AnimationID;
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
struct CDAnimation { struct CDAnimation {
// uint32_t animationGroupID; // uint32_t animationGroupID;
@ -20,12 +25,7 @@ struct CDAnimation {
UNUSED_COLUMN(float blendTime;) //!< The blend time UNUSED_COLUMN(float blendTime;) //!< The blend time
}; };
typedef LookupResult<CDAnimation> CDAnimationLookupResult; class CDAnimationsTable : public CDTable<CDAnimationsTable, std::map<CDAnimationKey, std::list<CDAnimation>>> {
class CDAnimationsTable : public CDTable<CDAnimationsTable> {
typedef int32_t AnimationGroupID;
typedef std::string AnimationID;
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
/** /**
@ -38,7 +38,7 @@ public:
* @param animationGroupID The animationGroupID to lookup * @param animationGroupID The animationGroupID to lookup
* @return CDAnimationLookupResult * @return CDAnimationLookupResult
*/ */
[[nodiscard]] CDAnimationLookupResult GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID); [[nodiscard]] std::optional<CDAnimation> GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID);
/** /**
* Cache a full AnimationGroup by its ID. * Cache a full AnimationGroup by its ID.
@ -58,10 +58,4 @@ private:
* @return false * @return false
*/ */
bool CacheData(CppSQLite3Statement& queryToCache); bool CacheData(CppSQLite3Statement& queryToCache);
/**
* Each animation is key'd by its animationName and its animationGroupID. Each
* animation has a possible list of animations. This is because there can be animations have a percent chance to play so one is selected at random.
*/
std::map<CDAnimationKey, std::list<CDAnimation>> animations;
}; };

View File

@ -1,6 +1,10 @@
#include "CDBehaviorParameterTable.h" #include "CDBehaviorParameterTable.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
namespace {
std::unordered_map<std::string, uint32_t> m_ParametersList;
};
uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) { uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
uint64_t key = behaviorID; uint64_t key = behaviorID;
key <<= 31U; key <<= 31U;
@ -11,6 +15,7 @@ uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
void CDBehaviorParameterTable::LoadValuesFromDatabase() { void CDBehaviorParameterTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
uint32_t behaviorID = tableData.getIntField("behaviorID", -1); uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", "")); auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
@ -24,7 +29,7 @@ void CDBehaviorParameterTable::LoadValuesFromDatabase() {
uint64_t hash = GetKey(behaviorID, parameterId); uint64_t hash = GetKey(behaviorID, parameterId);
float value = tableData.getFloatField("value", -1.0f); float value = tableData.getFloatField("value", -1.0f);
m_Entries.insert(std::make_pair(hash, value)); entries.insert(std::make_pair(hash, value));
tableData.nextRow(); tableData.nextRow();
} }
@ -32,22 +37,24 @@ void CDBehaviorParameterTable::LoadValuesFromDatabase() {
} }
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) { float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
auto parameterID = this->m_ParametersList.find(name); auto parameterID = m_ParametersList.find(name);
if (parameterID == this->m_ParametersList.end()) return defaultValue; if (parameterID == m_ParametersList.end()) return defaultValue;
auto hash = GetKey(behaviorID, parameterID->second); auto hash = GetKey(behaviorID, parameterID->second);
// Search for specific parameter // Search for specific parameter
auto it = m_Entries.find(hash); auto& entries = GetEntriesMutable();
return it != m_Entries.end() ? it->second : defaultValue; auto it = entries.find(hash);
return it != entries.end() ? it->second : defaultValue;
} }
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) { std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
auto& entries = GetEntriesMutable();
uint64_t hashBase = behaviorID; uint64_t hashBase = behaviorID;
std::map<std::string, float> returnInfo; std::map<std::string, float> returnInfo;
for (auto& [parameterString, parameterId] : m_ParametersList) { for (auto& [parameterString, parameterId] : m_ParametersList) {
uint64_t hash = GetKey(hashBase, parameterId); uint64_t hash = GetKey(hashBase, parameterId);
auto infoCandidate = m_Entries.find(hash); auto infoCandidate = entries.find(hash);
if (infoCandidate != m_Entries.end()) { if (infoCandidate != entries.end()) {
returnInfo.insert(std::make_pair(parameterString, infoCandidate->second)); returnInfo.insert(std::make_pair(parameterString, infoCandidate->second));
} }
} }

View File

@ -5,12 +5,10 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> { typedef uint64_t BehaviorParameterHash;
private: typedef float BehaviorParameterValue;
typedef uint64_t BehaviorParameterHash;
typedef float BehaviorParameterValue; class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable, std::unordered_map<BehaviorParameterHash, BehaviorParameterValue>> {
std::unordered_map<BehaviorParameterHash, BehaviorParameterValue> m_Entries;
std::unordered_map<std::string, uint32_t> m_ParametersList;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();

View File

@ -1,5 +1,9 @@
#include "CDBehaviorTemplateTable.h" #include "CDBehaviorTemplateTable.h"
namespace {
std::unordered_set<std::string> m_EffectHandles;
};
void CDBehaviorTemplateTable::LoadValuesFromDatabase() { void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
@ -13,11 +17,9 @@ void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size
this->entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorTemplate"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorTemplate");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDBehaviorTemplate entry; CDBehaviorTemplate entry;
entry.behaviorID = tableData.getIntField("behaviorID", -1); entry.behaviorID = tableData.getIntField("behaviorID", -1);
@ -31,30 +33,17 @@ void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
entry.effectHandle = m_EffectHandles.insert(candidateToAdd).first; entry.effectHandle = m_EffectHandles.insert(candidateToAdd).first;
} }
this->entries.push_back(entry); entries.insert(std::make_pair(entry.behaviorID, entry));
this->entriesMappedByBehaviorID.insert(std::make_pair(entry.behaviorID, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
} }
std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::Query(std::function<bool(CDBehaviorTemplate)> predicate) {
std::vector<CDBehaviorTemplate> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate)
>> cpplinq::to_vector();
return data;
}
const std::vector<CDBehaviorTemplate>& CDBehaviorTemplateTable::GetEntries() const {
return this->entries;
}
const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behaviorID) { const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behaviorID) {
auto entry = this->entriesMappedByBehaviorID.find(behaviorID); auto& entries = GetEntriesMutable();
if (entry == this->entriesMappedByBehaviorID.end()) { auto entry = entries.find(behaviorID);
if (entry == entries.end()) {
CDBehaviorTemplate entryToReturn; CDBehaviorTemplate entryToReturn;
entryToReturn.behaviorID = 0; entryToReturn.behaviorID = 0;
entryToReturn.effectHandle = m_EffectHandles.end(); entryToReturn.effectHandle = m_EffectHandles.end();

View File

@ -12,19 +12,9 @@ struct CDBehaviorTemplate {
std::unordered_set<std::string>::iterator effectHandle; //!< The effect handle std::unordered_set<std::string>::iterator effectHandle; //!< The effect handle
}; };
class CDBehaviorTemplateTable : public CDTable<CDBehaviorTemplateTable, std::unordered_map<uint32_t, CDBehaviorTemplate>> {
class CDBehaviorTemplateTable : public CDTable<CDBehaviorTemplateTable> {
private:
std::vector<CDBehaviorTemplate> entries;
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
std::unordered_set<std::string> m_EffectHandles;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause
std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate);
const std::vector<CDBehaviorTemplate>& GetEntries(void) const;
const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID); const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID);
}; };

View File

@ -14,7 +14,8 @@ void CDBrickIDTableTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BrickIDTable"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BrickIDTable");
@ -23,7 +24,7 @@ void CDBrickIDTableTable::LoadValuesFromDatabase() {
entry.NDObjectID = tableData.getIntField("NDObjectID", -1); entry.NDObjectID = tableData.getIntField("NDObjectID", -1);
entry.LEGOBrickID = tableData.getIntField("LEGOBrickID", -1); entry.LEGOBrickID = tableData.getIntField("LEGOBrickID", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -31,15 +32,9 @@ void CDBrickIDTableTable::LoadValuesFromDatabase() {
} }
std::vector<CDBrickIDTable> CDBrickIDTableTable::Query(std::function<bool(CDBrickIDTable)> predicate) { std::vector<CDBrickIDTable> CDBrickIDTableTable::Query(std::function<bool(CDBrickIDTable)> predicate) {
std::vector<CDBrickIDTable> data = cpplinq::from(GetEntries())
std::vector<CDBrickIDTable> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDBrickIDTable>& CDBrickIDTableTable::GetEntries() const {
return this->entries;
}

View File

@ -16,14 +16,9 @@ struct CDBrickIDTable {
//! BrickIDTable table //! BrickIDTable table
class CDBrickIDTableTable : public CDTable<CDBrickIDTableTable> { class CDBrickIDTableTable : public CDTable<CDBrickIDTableTable, std::vector<CDBrickIDTable>> {
private:
std::vector<CDBrickIDTable> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate); std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
const std::vector<CDBrickIDTable>& GetEntries() const;
}; };

View File

@ -4,14 +4,15 @@
void CDComponentsRegistryTable::LoadValuesFromDatabase() { void CDComponentsRegistryTable::LoadValuesFromDatabase() {
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDComponentsRegistry entry; CDComponentsRegistry entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0)); entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
entry.component_id = tableData.getIntField("component_id", -1); entry.component_id = tableData.getIntField("component_id", -1);
this->mappedEntries.insert_or_assign(static_cast<uint64_t>(entry.component_type) << 32 | static_cast<uint64_t>(entry.id), entry.component_id); entries.insert_or_assign(static_cast<uint64_t>(entry.component_type) << 32 | static_cast<uint64_t>(entry.id), entry.component_id);
this->mappedEntries.insert_or_assign(entry.id, 0); entries.insert_or_assign(entry.id, 0);
tableData.nextRow(); tableData.nextRow();
} }
@ -20,10 +21,11 @@ void CDComponentsRegistryTable::LoadValuesFromDatabase() {
} }
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) { int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
auto exists = mappedEntries.find(id); auto& entries = GetEntriesMutable();
if (exists != mappedEntries.end()) { auto exists = entries.find(id);
auto iter = mappedEntries.find(static_cast<uint64_t>(componentType) << 32 | static_cast<uint64_t>(id)); if (exists != entries.end()) {
return iter == mappedEntries.end() ? defaultValue : iter->second; auto iter = entries.find(static_cast<uint64_t>(componentType) << 32 | static_cast<uint64_t>(id));
return iter == entries.end() ? defaultValue : iter->second;
} }
// Now get the data. Get all components of this entity so we dont do a query for each component // Now get the data. Get all components of this entity so we dont do a query for each component
@ -38,14 +40,14 @@ int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponent
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0)); entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
entry.component_id = tableData.getIntField("component_id", -1); entry.component_id = tableData.getIntField("component_id", -1);
this->mappedEntries.insert_or_assign(static_cast<uint64_t>(entry.component_type) << 32 | static_cast<uint64_t>(entry.id), entry.component_id); entries.insert_or_assign(static_cast<uint64_t>(entry.component_type) << 32 | static_cast<uint64_t>(entry.id), entry.component_id);
tableData.nextRow(); tableData.nextRow();
} }
mappedEntries.insert_or_assign(id, 0); entries.insert_or_assign(id, 0);
auto iter = this->mappedEntries.find(static_cast<uint64_t>(componentType) << 32 | static_cast<uint64_t>(id)); auto iter = entries.find(static_cast<uint64_t>(componentType) << 32 | static_cast<uint64_t>(id));
return iter == this->mappedEntries.end() ? defaultValue : iter->second; return iter == entries.end() ? defaultValue : iter->second;
} }

View File

@ -13,10 +13,7 @@ struct CDComponentsRegistry {
}; };
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> { class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable, std::unordered_map<uint64_t, uint32_t>> {
private:
std::unordered_map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0); int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);

View File

@ -15,7 +15,8 @@ void CDCurrencyTableTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM CurrencyTable"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM CurrencyTable");
@ -27,7 +28,7 @@ void CDCurrencyTableTable::LoadValuesFromDatabase() {
entry.maxvalue = tableData.getIntField("maxvalue", -1); entry.maxvalue = tableData.getIntField("maxvalue", -1);
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -35,15 +36,9 @@ void CDCurrencyTableTable::LoadValuesFromDatabase() {
} }
std::vector<CDCurrencyTable> CDCurrencyTableTable::Query(std::function<bool(CDCurrencyTable)> predicate) { std::vector<CDCurrencyTable> CDCurrencyTableTable::Query(std::function<bool(CDCurrencyTable)> predicate) {
std::vector<CDCurrencyTable> data = cpplinq::from(GetEntries())
std::vector<CDCurrencyTable> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDCurrencyTable>& CDCurrencyTableTable::GetEntries() const {
return this->entries;
}

View File

@ -18,14 +18,9 @@ struct CDCurrencyTable {
}; };
//! CurrencyTable table //! CurrencyTable table
class CDCurrencyTableTable : public CDTable<CDCurrencyTableTable> { class CDCurrencyTableTable : public CDTable<CDCurrencyTableTable, std::vector<CDCurrencyTable>> {
private:
std::vector<CDCurrencyTable> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate); std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
const std::vector<CDCurrencyTable>& GetEntries() const;
}; };

View File

@ -13,7 +13,8 @@ void CDDestructibleComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM DestructibleComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM DestructibleComponent");
@ -34,7 +35,7 @@ void CDDestructibleComponentTable::LoadValuesFromDatabase() {
entry.isSmashable = tableData.getIntField("isSmashable", -1) == 1 ? true : false; entry.isSmashable = tableData.getIntField("isSmashable", -1) == 1 ? true : false;
entry.difficultyLevel = tableData.getIntField("difficultyLevel", -1); entry.difficultyLevel = tableData.getIntField("difficultyLevel", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -42,15 +43,9 @@ void CDDestructibleComponentTable::LoadValuesFromDatabase() {
} }
std::vector<CDDestructibleComponent> CDDestructibleComponentTable::Query(std::function<bool(CDDestructibleComponent)> predicate) { std::vector<CDDestructibleComponent> CDDestructibleComponentTable::Query(std::function<bool(CDDestructibleComponent)> predicate) {
std::vector<CDDestructibleComponent> data = cpplinq::from(GetEntries())
std::vector<CDDestructibleComponent> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDDestructibleComponent>& CDDestructibleComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -20,14 +20,9 @@ struct CDDestructibleComponent {
int32_t difficultyLevel; //!< ??? int32_t difficultyLevel; //!< ???
}; };
class CDDestructibleComponentTable : public CDTable<CDDestructibleComponentTable> { class CDDestructibleComponentTable : public CDTable<CDDestructibleComponentTable, std::vector<CDDestructibleComponent>> {
private:
std::vector<CDDestructibleComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate); std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
const std::vector<CDDestructibleComponent>& GetEntries(void) const;
}; };

View File

@ -2,6 +2,7 @@
void CDEmoteTableTable::LoadValuesFromDatabase() { void CDEmoteTableTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDEmoteTable entry; CDEmoteTable entry;
entry.ID = tableData.getIntField("id", -1); entry.ID = tableData.getIntField("id", -1);
@ -21,6 +22,7 @@ void CDEmoteTableTable::LoadValuesFromDatabase() {
} }
CDEmoteTable* CDEmoteTableTable::GetEmote(int32_t id) { CDEmoteTable* CDEmoteTableTable::GetEmote(int32_t id) {
auto& entries = GetEntriesMutable();
auto itr = entries.find(id); auto itr = entries.find(id);
return itr != entries.end() ? &itr->second : nullptr; return itr != entries.end() ? &itr->second : nullptr;
} }

View File

@ -26,10 +26,7 @@ struct CDEmoteTable {
std::string gateVersion; std::string gateVersion;
}; };
class CDEmoteTableTable : public CDTable<CDEmoteTableTable> { class CDEmoteTableTable : public CDTable<CDEmoteTableTable, std::map<int, CDEmoteTable>> {
private:
std::map<int, CDEmoteTable> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Returns an emote by ID // Returns an emote by ID

View File

@ -14,7 +14,8 @@ void CDFeatureGatingTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM FeatureGating"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM FeatureGating");
@ -26,7 +27,7 @@ void CDFeatureGatingTable::LoadValuesFromDatabase() {
entry.minor = tableData.getIntField("minor", -1); entry.minor = tableData.getIntField("minor", -1);
entry.description = tableData.getStringField("description", ""); entry.description = tableData.getStringField("description", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -35,7 +36,8 @@ void CDFeatureGatingTable::LoadValuesFromDatabase() {
std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFeatureGating)> predicate) { std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFeatureGating)> predicate) {
std::vector<CDFeatureGating> data = cpplinq::from(this->entries) auto& entries = GetEntriesMutable();
std::vector<CDFeatureGating> data = cpplinq::from(entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
@ -43,6 +45,7 @@ std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFe
} }
bool CDFeatureGatingTable::FeatureUnlocked(const CDFeatureGating& feature) const { bool CDFeatureGatingTable::FeatureUnlocked(const CDFeatureGating& feature) const {
auto& entries = GetEntriesMutable();
for (const auto& entry : entries) { for (const auto& entry : entries) {
if (entry.featureName == feature.featureName && feature >= entry) { if (entry.featureName == feature.featureName && feature >= entry) {
return true; return true;
@ -51,8 +54,3 @@ bool CDFeatureGatingTable::FeatureUnlocked(const CDFeatureGating& feature) const
return false; return false;
} }
const std::vector<CDFeatureGating>& CDFeatureGatingTable::GetEntries() const {
return this->entries;
}

View File

@ -17,10 +17,7 @@ struct CDFeatureGating {
} }
}; };
class CDFeatureGatingTable : public CDTable<CDFeatureGatingTable> { class CDFeatureGatingTable : public CDTable<CDFeatureGatingTable, std::vector<CDFeatureGating>> {
private:
std::vector<CDFeatureGating> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
@ -28,6 +25,4 @@ public:
std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate); std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate);
bool FeatureUnlocked(const CDFeatureGating& feature) const; bool FeatureUnlocked(const CDFeatureGating& feature) const;
const std::vector<CDFeatureGating>& GetEntries(void) const;
}; };

View File

@ -14,7 +14,8 @@ void CDInventoryComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM InventoryComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM InventoryComponent");
@ -25,7 +26,7 @@ void CDInventoryComponentTable::LoadValuesFromDatabase() {
entry.count = tableData.getIntField("count", -1); entry.count = tableData.getIntField("count", -1);
entry.equip = tableData.getIntField("equip", -1) == 1 ? true : false; entry.equip = tableData.getIntField("equip", -1) == 1 ? true : false;
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -33,15 +34,9 @@ void CDInventoryComponentTable::LoadValuesFromDatabase() {
} }
std::vector<CDInventoryComponent> CDInventoryComponentTable::Query(std::function<bool(CDInventoryComponent)> predicate) { std::vector<CDInventoryComponent> CDInventoryComponentTable::Query(std::function<bool(CDInventoryComponent)> predicate) {
std::vector<CDInventoryComponent> data = cpplinq::from(GetEntries())
std::vector<CDInventoryComponent> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDInventoryComponent>& CDInventoryComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -10,14 +10,9 @@ struct CDInventoryComponent {
bool equip; //!< Whether or not to equip the item bool equip; //!< Whether or not to equip the item
}; };
class CDInventoryComponentTable : public CDTable<CDInventoryComponentTable> { class CDInventoryComponentTable : public CDTable<CDInventoryComponentTable, std::vector<CDInventoryComponent>> {
private:
std::vector<CDInventoryComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate); std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
const std::vector<CDInventoryComponent>& GetEntries() const;
}; };

View File

@ -17,6 +17,7 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemComponent");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDItemComponent entry; CDItemComponent entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
@ -62,7 +63,7 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
entry.forgeType = tableData.getIntField("forgeType", -1); entry.forgeType = tableData.getIntField("forgeType", -1);
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f); entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
this->entries.insert(std::make_pair(entry.id, entry)); entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
@ -70,8 +71,9 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
} }
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skillID) { const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skillID) {
const auto& it = this->entries.find(skillID); auto& entries = GetEntriesMutable();
if (it != this->entries.end()) { const auto& it = entries.find(skillID);
if (it != entries.end()) {
return it->second; return it->second;
} }
@ -129,12 +131,12 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skill
entry.forgeType = tableData.getIntField("forgeType", -1); entry.forgeType = tableData.getIntField("forgeType", -1);
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f); entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
this->entries.insert(std::make_pair(entry.id, entry)); entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
const auto& it2 = this->entries.find(skillID); const auto& it2 = entries.find(skillID);
if (it2 != this->entries.end()) { if (it2 != entries.end()) {
return it2->second; return it2->second;
} }

View File

@ -49,10 +49,7 @@ struct CDItemComponent {
float SellMultiplier; //!< Something to do with early vendors perhaps (but replaced) float SellMultiplier; //!< Something to do with early vendors perhaps (but replaced)
}; };
class CDItemComponentTable : public CDTable<CDItemComponentTable> { class CDItemComponentTable : public CDTable<CDItemComponentTable, std::map<uint32_t, CDItemComponent>> {
private:
std::map<uint32_t, CDItemComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent); static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);

View File

@ -14,7 +14,8 @@ void CDItemSetSkillsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemSetSkills"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemSetSkills");
@ -24,7 +25,7 @@ void CDItemSetSkillsTable::LoadValuesFromDatabase() {
entry.SkillID = tableData.getIntField("SkillID", -1); entry.SkillID = tableData.getIntField("SkillID", -1);
entry.SkillCastType = tableData.getIntField("SkillCastType", -1); entry.SkillCastType = tableData.getIntField("SkillCastType", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -32,22 +33,17 @@ void CDItemSetSkillsTable::LoadValuesFromDatabase() {
} }
std::vector<CDItemSetSkills> CDItemSetSkillsTable::Query(std::function<bool(CDItemSetSkills)> predicate) { std::vector<CDItemSetSkills> CDItemSetSkillsTable::Query(std::function<bool(CDItemSetSkills)> predicate) {
std::vector<CDItemSetSkills> data = cpplinq::from(GetEntries())
std::vector<CDItemSetSkills> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDItemSetSkills>& CDItemSetSkillsTable::GetEntries() const {
return this->entries;
}
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetBySkillID(uint32_t SkillSetID) { std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetBySkillID(uint32_t SkillSetID) {
std::vector<CDItemSetSkills> toReturn; std::vector<CDItemSetSkills> toReturn;
for (CDItemSetSkills entry : this->entries) { for (const auto& entry : GetEntries()) {
if (entry.SkillSetID == SkillSetID) toReturn.push_back(entry); if (entry.SkillSetID == SkillSetID) toReturn.push_back(entry);
if (entry.SkillSetID > SkillSetID) return toReturn; //stop seeking in the db if it's not needed. if (entry.SkillSetID > SkillSetID) return toReturn; //stop seeking in the db if it's not needed.
} }

View File

@ -9,16 +9,11 @@ struct CDItemSetSkills {
uint32_t SkillCastType; //!< The skill cast type uint32_t SkillCastType; //!< The skill cast type
}; };
class CDItemSetSkillsTable : public CDTable<CDItemSetSkillsTable> { class CDItemSetSkillsTable : public CDTable<CDItemSetSkillsTable, std::vector<CDItemSetSkills>> {
private:
std::vector<CDItemSetSkills> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate); std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
const std::vector<CDItemSetSkills>& GetEntries() const;
std::vector<CDItemSetSkills> GetBySkillID(uint32_t SkillSetID); std::vector<CDItemSetSkills> GetBySkillID(uint32_t SkillSetID);
}; };

View File

@ -14,7 +14,8 @@ void CDItemSetsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemSets"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemSets");
@ -36,7 +37,7 @@ void CDItemSetsTable::LoadValuesFromDatabase() {
entry.kitID = tableData.getIntField("kitID", -1); entry.kitID = tableData.getIntField("kitID", -1);
entry.priority = tableData.getFloatField("priority", -1.0f); entry.priority = tableData.getFloatField("priority", -1.0f);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -45,14 +46,9 @@ void CDItemSetsTable::LoadValuesFromDatabase() {
std::vector<CDItemSets> CDItemSetsTable::Query(std::function<bool(CDItemSets)> predicate) { std::vector<CDItemSets> CDItemSetsTable::Query(std::function<bool(CDItemSets)> predicate) {
std::vector<CDItemSets> data = cpplinq::from(this->entries) std::vector<CDItemSets> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDItemSets>& CDItemSetsTable::GetEntries() const {
return this->entries;
}

View File

@ -21,15 +21,10 @@ struct CDItemSets {
float priority; //!< The priority float priority; //!< The priority
}; };
class CDItemSetsTable : public CDTable<CDItemSetsTable> { class CDItemSetsTable : public CDTable<CDItemSetsTable, std::vector<CDItemSets>> {
private:
std::vector<CDItemSets> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate); std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
const std::vector<CDItemSets>& GetEntries(void) const;
}; };

View File

@ -14,7 +14,8 @@ void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LevelProgressionLookup"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LevelProgressionLookup");
@ -24,7 +25,7 @@ void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
entry.requiredUScore = tableData.getIntField("requiredUScore", -1); entry.requiredUScore = tableData.getIntField("requiredUScore", -1);
entry.BehaviorEffect = tableData.getStringField("BehaviorEffect", ""); entry.BehaviorEffect = tableData.getStringField("BehaviorEffect", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -33,14 +34,9 @@ void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) { std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) {
std::vector<CDLevelProgressionLookup> data = cpplinq::from(this->entries) std::vector<CDLevelProgressionLookup> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDLevelProgressionLookup>& CDLevelProgressionLookupTable::GetEntries() const {
return this->entries;
}

View File

@ -9,15 +9,10 @@ struct CDLevelProgressionLookup {
std::string BehaviorEffect; //!< The behavior effect attached to this std::string BehaviorEffect; //!< The behavior effect attached to this
}; };
class CDLevelProgressionLookupTable : public CDTable<CDLevelProgressionLookupTable> { class CDLevelProgressionLookupTable : public CDTable<CDLevelProgressionLookupTable, std::vector<CDLevelProgressionLookup>> {
private:
std::vector<CDLevelProgressionLookup> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate); std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
const std::vector<CDLevelProgressionLookup>& GetEntries() const;
}; };

View File

@ -25,7 +25,8 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
} }
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
@ -33,14 +34,15 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
CDLootMatrix entry; CDLootMatrix entry;
uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1); uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
this->entries[lootMatrixIndex].push_back(ReadRow(tableData)); entries[lootMatrixIndex].push_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
} }
const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) { const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
auto itr = this->entries.find(matrixId); auto& entries = GetEntriesMutable();
if (itr != this->entries.end()) { auto itr = entries.find(matrixId);
if (itr != entries.end()) {
return itr->second; return itr->second;
} }
@ -49,10 +51,10 @@ const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
auto tableData = query.execQuery(); auto tableData = query.execQuery();
while (!tableData.eof()) { while (!tableData.eof()) {
this->entries[matrixId].push_back(ReadRow(tableData)); entries[matrixId].push_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
return this->entries[matrixId]; return entries[matrixId];
} }

View File

@ -16,7 +16,7 @@ struct CDLootMatrix {
typedef uint32_t LootMatrixIndex; typedef uint32_t LootMatrixIndex;
typedef std::vector<CDLootMatrix> LootMatrixEntries; typedef std::vector<CDLootMatrix> LootMatrixEntries;
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> { class CDLootMatrixTable : public CDTable<CDLootMatrixTable, std::unordered_map<LootMatrixIndex, LootMatrixEntries>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
@ -24,6 +24,5 @@ public:
const LootMatrixEntries& GetMatrix(uint32_t matrixId); const LootMatrixEntries& GetMatrix(uint32_t matrixId);
private: private:
CDLootMatrix ReadRow(CppSQLite3Query& tableData) const; CDLootMatrix ReadRow(CppSQLite3Query& tableData) const;
std::unordered_map<LootMatrixIndex, LootMatrixEntries> entries;
}; };

View File

@ -6,8 +6,8 @@
// Sort the tables by their rarity so the highest rarity items are first. // Sort the tables by their rarity so the highest rarity items are first.
void SortTable(LootTableEntries& table) { void SortTable(LootTableEntries& table) {
auto* componentsRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>(); auto* componentsRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>(); auto* itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
// We modify the table in place so the outer loop keeps track of what is sorted // We modify the table in place so the outer loop keeps track of what is sorted
// and the inner loop finds the highest rarity item and swaps it with the current position // and the inner loop finds the highest rarity item and swaps it with the current position
// of the outer loop. // of the outer loop.
@ -49,7 +49,8 @@ void CDLootTableTable::LoadValuesFromDatabase() {
} }
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
@ -57,17 +58,18 @@ void CDLootTableTable::LoadValuesFromDatabase() {
CDLootTable entry; CDLootTable entry;
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1); uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
this->entries[lootTableIndex].push_back(ReadRow(tableData)); entries[lootTableIndex].emplace_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
for (auto& [id, table] : this->entries) { for (auto& [id, table] : entries) {
SortTable(table); SortTable(table);
} }
} }
const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) { const LootTableEntries& CDLootTableTable::GetTable(const uint32_t tableId) {
auto itr = this->entries.find(tableId); auto& entries = GetEntriesMutable();
if (itr != this->entries.end()) { auto itr = entries.find(tableId);
if (itr != entries.end()) {
return itr->second; return itr->second;
} }
@ -77,10 +79,10 @@ const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
while (!tableData.eof()) { while (!tableData.eof()) {
CDLootTable entry; CDLootTable entry;
this->entries[tableId].push_back(ReadRow(tableData)); entries[tableId].emplace_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
SortTable(this->entries[tableId]); SortTable(entries[tableId]);
return this->entries[tableId]; return entries[tableId];
} }

View File

@ -3,6 +3,8 @@
// Custom Classes // Custom Classes
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
struct CDLootTable { struct CDLootTable {
uint32_t itemid; //!< The LOT of the item uint32_t itemid; //!< The LOT of the item
uint32_t LootTableIndex; //!< The Loot Table Index uint32_t LootTableIndex; //!< The Loot Table Index
@ -13,14 +15,12 @@ struct CDLootTable {
typedef uint32_t LootTableIndex; typedef uint32_t LootTableIndex;
typedef std::vector<CDLootTable> LootTableEntries; typedef std::vector<CDLootTable> LootTableEntries;
class CDLootTableTable : public CDTable<CDLootTableTable> { class CDLootTableTable : public CDTable<CDLootTableTable, std::unordered_map<LootTableIndex, LootTableEntries>> {
private: private:
CDLootTable ReadRow(CppSQLite3Query& tableData) const; CDLootTable ReadRow(CppSQLite3Query& tableData) const;
std::unordered_map<LootTableIndex, LootTableEntries> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
const LootTableEntries& GetTable(uint32_t tableId); const LootTableEntries& GetTable(const uint32_t tableId);
}; };

View File

@ -1,7 +1,7 @@
#include "CDMissionEmailTable.h" #include "CDMissionEmailTable.h"
void CDMissionEmailTable::LoadValuesFromDatabase() {
void CDMissionEmailTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
uint32_t size = 0; uint32_t size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM MissionEmail"); auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM MissionEmail");
@ -14,12 +14,13 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionEmail"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionEmail");
while (!tableData.eof()) { while (!tableData.eof()) {
CDMissionEmail entry; auto& entry = entries.emplace_back();
entry.ID = tableData.getIntField("ID", -1); entry.ID = tableData.getIntField("ID", -1);
entry.messageType = tableData.getIntField("messageType", -1); entry.messageType = tableData.getIntField("messageType", -1);
entry.notificationGroup = tableData.getIntField("notificationGroup", -1); entry.notificationGroup = tableData.getIntField("notificationGroup", -1);
@ -29,24 +30,15 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
entry.locStatus = tableData.getIntField("locStatus", -1); entry.locStatus = tableData.getIntField("locStatus", -1);
entry.gate_version = tableData.getStringField("gate_version", ""); entry.gate_version = tableData.getStringField("gate_version", "");
this->entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize();
} }
//! Queries the table with a custom "where" clause //! Queries the table with a custom "where" clause
std::vector<CDMissionEmail> CDMissionEmailTable::Query(std::function<bool(CDMissionEmail)> predicate) { std::vector<CDMissionEmail> CDMissionEmailTable::Query(std::function<bool(CDMissionEmail)> predicate) {
std::vector<CDMissionEmail> data = cpplinq::from(GetEntries())
std::vector<CDMissionEmail> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
//! Gets all the entries in the table
const std::vector<CDMissionEmail>& CDMissionEmailTable::GetEntries() const {
return this->entries;
}

View File

@ -3,6 +3,8 @@
// Custom Classes // Custom Classes
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
struct CDMissionEmail { struct CDMissionEmail {
uint32_t ID; uint32_t ID;
uint32_t messageType; uint32_t messageType;
@ -15,14 +17,9 @@ struct CDMissionEmail {
}; };
class CDMissionEmailTable : public CDTable<CDMissionEmailTable> { class CDMissionEmailTable : public CDTable<CDMissionEmailTable, std::vector<CDMissionEmail>> {
private:
std::vector<CDMissionEmail> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate); std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
const std::vector<CDMissionEmail>& GetEntries() const;
}; };

View File

@ -14,37 +14,29 @@ void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionNPCComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionNPCComponent");
while (!tableData.eof()) { while (!tableData.eof()) {
CDMissionNPCComponent entry; auto& entry = entries.emplace_back();
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry.missionID = tableData.getIntField("missionID", -1); entry.missionID = tableData.getIntField("missionID", -1);
entry.offersMission = tableData.getIntField("offersMission", -1) == 1 ? true : false; entry.offersMission = tableData.getIntField("offersMission", -1) == 1 ? true : false;
entry.acceptsMission = tableData.getIntField("acceptsMission", -1) == 1 ? true : false; entry.acceptsMission = tableData.getIntField("acceptsMission", -1) == 1 ? true : false;
entry.gate_version = tableData.getStringField("gate_version", ""); entry.gate_version = tableData.getStringField("gate_version", "");
this->entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize();
} }
//! Queries the table with a custom "where" clause //! Queries the table with a custom "where" clause
std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::Query(std::function<bool(CDMissionNPCComponent)> predicate) { std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::Query(std::function<bool(CDMissionNPCComponent)> predicate) {
std::vector<CDMissionNPCComponent> data = cpplinq::from(this->entries) std::vector<CDMissionNPCComponent> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
//! Gets all the entries in the table
const std::vector<CDMissionNPCComponent>& CDMissionNPCComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -3,6 +3,8 @@
// Custom Classes // Custom Classes
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
struct CDMissionNPCComponent { struct CDMissionNPCComponent {
uint32_t id; //!< The ID uint32_t id; //!< The ID
uint32_t missionID; //!< The Mission ID uint32_t missionID; //!< The Mission ID
@ -11,17 +13,9 @@ struct CDMissionNPCComponent {
std::string gate_version; //!< The gate version std::string gate_version; //!< The gate version
}; };
class CDMissionNPCComponentTable : public CDTable<CDMissionNPCComponentTable> { class CDMissionNPCComponentTable : public CDTable<CDMissionNPCComponentTable, std::vector<CDMissionNPCComponent>> {
private:
std::vector<CDMissionNPCComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate); std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
// Gets all the entries in the table
const std::vector<CDMissionNPCComponent>& GetEntries() const;
}; };

View File

@ -14,12 +14,13 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionTasks"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionTasks");
while (!tableData.eof()) { while (!tableData.eof()) {
CDMissionTasks entry; auto& entry = entries.emplace_back();
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1)); UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
entry.taskType = tableData.getIntField("taskType", -1); entry.taskType = tableData.getIntField("taskType", -1);
@ -34,26 +35,24 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
UNUSED(entry.localize = tableData.getIntField("localize", -1) == 1 ? true : false); UNUSED(entry.localize = tableData.getIntField("localize", -1) == 1 ? true : false);
UNUSED(entry.gate_version = tableData.getStringField("gate_version", "")); UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
this->entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize();
} }
std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMissionTasks)> predicate) { std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMissionTasks)> predicate) {
std::vector<CDMissionTasks> data = cpplinq::from(this->entries) std::vector<CDMissionTasks> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID) { std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(const uint32_t missionID) {
std::vector<CDMissionTasks*> tasks; std::vector<CDMissionTasks*> tasks;
for (auto& entry : this->entries) { // TODO: this should not be linear(?) and also shouldnt need to be a pointer
for (auto& entry : GetEntriesMutable()) {
if (entry.id == missionID) { if (entry.id == missionID) {
tasks.push_back(&entry); tasks.push_back(&entry);
} }
@ -62,7 +61,6 @@ std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missio
return tasks; return tasks;
} }
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries() const { const typename CDMissionTasksTable::StorageType& CDMissionTasksTable::GetEntries() const {
return this->entries; return CDTable::GetEntries();
} }

View File

@ -3,6 +3,8 @@
// Custom Classes // Custom Classes
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
struct CDMissionTasks { struct CDMissionTasks {
uint32_t id; //!< The Mission ID that the task belongs to uint32_t id; //!< The Mission ID that the task belongs to
UNUSED(uint32_t locStatus); //!< ??? UNUSED(uint32_t locStatus); //!< ???
@ -19,17 +21,15 @@ struct CDMissionTasks {
UNUSED(std::string gate_version); //!< ??? UNUSED(std::string gate_version); //!< ???
}; };
class CDMissionTasksTable : public CDTable<CDMissionTasksTable> { class CDMissionTasksTable : public CDTable<CDMissionTasksTable, std::vector<CDMissionTasks>> {
private:
std::vector<CDMissionTasks> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate); std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID); std::vector<CDMissionTasks*> GetByMissionID(const uint32_t missionID);
const std::vector<CDMissionTasks>& GetEntries() const; // TODO: Remove this and replace it with a proper lookup function.
const CDTable::StorageType& GetEntries() const;
}; };

View File

@ -16,12 +16,13 @@ void CDMissionsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Missions"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Missions");
while (!tableData.eof()) { while (!tableData.eof()) {
CDMissions entry; auto& entry = entries.emplace_back();
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry.defined_type = tableData.getStringField("defined_type", ""); entry.defined_type = tableData.getStringField("defined_type", "");
entry.defined_subtype = tableData.getStringField("defined_subtype", ""); entry.defined_subtype = tableData.getStringField("defined_subtype", "");
@ -75,10 +76,8 @@ void CDMissionsTable::LoadValuesFromDatabase() {
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1)); UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
entry.reward_bankinventory = tableData.getIntField("reward_bankinventory", -1); entry.reward_bankinventory = tableData.getIntField("reward_bankinventory", -1);
this->entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
Default.id = -1; Default.id = -1;
@ -86,19 +85,15 @@ void CDMissionsTable::LoadValuesFromDatabase() {
std::vector<CDMissions> CDMissionsTable::Query(std::function<bool(CDMissions)> predicate) { std::vector<CDMissions> CDMissionsTable::Query(std::function<bool(CDMissions)> predicate) {
std::vector<CDMissions> data = cpplinq::from(this->entries) std::vector<CDMissions> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDMissions>& CDMissionsTable::GetEntries(void) const {
return this->entries;
}
const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const { const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const {
for (const auto& entry : entries) { for (const auto& entry : GetEntries()) {
if (entry.id == missionID) { if (entry.id == missionID) {
return const_cast<CDMissions*>(&entry); return const_cast<CDMissions*>(&entry);
} }
@ -108,7 +103,7 @@ const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const {
} }
const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const { const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const {
for (const auto& entry : entries) { for (const auto& entry : GetEntries()) {
if (entry.id == missionID) { if (entry.id == missionID) {
found = true; found = true;
@ -121,3 +116,12 @@ const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& foun
return Default; return Default;
} }
const std::set<int32_t> CDMissionsTable::GetMissionsForReward(LOT lot) {
std::set<int32_t> toReturn {};
for (const auto& entry : GetEntries()) {
if (lot == entry.reward_item1 || lot == entry.reward_item2 || lot == entry.reward_item3 || lot == entry.reward_item4) {
toReturn.insert(entry.id);
}
}
return toReturn;
}

View File

@ -60,22 +60,18 @@ struct CDMissions {
int32_t reward_bankinventory; //!< The amount of bank space this mission rewards int32_t reward_bankinventory; //!< The amount of bank space this mission rewards
}; };
class CDMissionsTable : public CDTable<CDMissionsTable> { class CDMissionsTable : public CDTable<CDMissionsTable, std::vector<CDMissions>> {
private:
std::vector<CDMissions> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate); std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
// Gets all the entries in the table
const std::vector<CDMissions>& GetEntries() const;
const CDMissions* GetPtrByMissionID(uint32_t missionID) const; const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const; const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const;
const std::set<int32_t> GetMissionsForReward(LOT lot);
static CDMissions Default; static CDMissions Default;
}; };

View File

@ -14,12 +14,13 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MovementAIComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MovementAIComponent");
while (!tableData.eof()) { while (!tableData.eof()) {
CDMovementAIComponent entry; auto& entry = entries.emplace_back();
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry.MovementType = tableData.getStringField("MovementType", ""); entry.MovementType = tableData.getStringField("MovementType", "");
entry.WanderChance = tableData.getFloatField("WanderChance", -1.0f); entry.WanderChance = tableData.getFloatField("WanderChance", -1.0f);
@ -29,23 +30,15 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
entry.WanderRadius = tableData.getFloatField("WanderRadius", -1.0f); entry.WanderRadius = tableData.getFloatField("WanderRadius", -1.0f);
entry.attachedPath = tableData.getStringField("attachedPath", ""); entry.attachedPath = tableData.getStringField("attachedPath", "");
this->entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize();
} }
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) { std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
std::vector<CDMovementAIComponent> data = cpplinq::from(this->entries) std::vector<CDMovementAIComponent> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDMovementAIComponent>& CDMovementAIComponentTable::GetEntries(void) const {
return this->entries;
}

View File

@ -3,6 +3,8 @@
// Custom Classes // Custom Classes
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
struct CDMovementAIComponent { struct CDMovementAIComponent {
uint32_t id; uint32_t id;
std::string MovementType; std::string MovementType;
@ -14,15 +16,9 @@ struct CDMovementAIComponent {
std::string attachedPath; std::string attachedPath;
}; };
class CDMovementAIComponentTable : public CDTable<CDMovementAIComponentTable> { class CDMovementAIComponentTable : public CDTable<CDMovementAIComponentTable, std::vector<CDMovementAIComponent>> {
private:
std::vector<CDMovementAIComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate); std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
// Gets all the entries in the table
const std::vector<CDMovementAIComponent>& GetEntries() const;
}; };

View File

@ -14,33 +14,27 @@ void CDObjectSkillsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ObjectSkills"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ObjectSkills");
while (!tableData.eof()) { while (!tableData.eof()) {
CDObjectSkills entry; auto &entry = entries.emplace_back();
entry.objectTemplate = tableData.getIntField("objectTemplate", -1); entry.objectTemplate = tableData.getIntField("objectTemplate", -1);
entry.skillID = tableData.getIntField("skillID", -1); entry.skillID = tableData.getIntField("skillID", -1);
entry.castOnType = tableData.getIntField("castOnType", -1); entry.castOnType = tableData.getIntField("castOnType", -1);
entry.AICombatWeight = tableData.getIntField("AICombatWeight", -1); entry.AICombatWeight = tableData.getIntField("AICombatWeight", -1);
this->entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize();
} }
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) { std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
std::vector<CDObjectSkills> data = cpplinq::from(this->entries) std::vector<CDObjectSkills> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDObjectSkills>& CDObjectSkillsTable::GetEntries() const {
return this->entries;
}

View File

@ -3,6 +3,8 @@
// Custom Classes // Custom Classes
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
struct CDObjectSkills { struct CDObjectSkills {
uint32_t objectTemplate; //!< The LOT of the item uint32_t objectTemplate; //!< The LOT of the item
uint32_t skillID; //!< The Skill ID of the object uint32_t skillID; //!< The Skill ID of the object
@ -10,17 +12,10 @@ struct CDObjectSkills {
uint32_t AICombatWeight; //!< ??? uint32_t AICombatWeight; //!< ???
}; };
class CDObjectSkillsTable : public CDTable<CDObjectSkillsTable> { class CDObjectSkillsTable : public CDTable<CDObjectSkillsTable, std::vector<CDObjectSkills>> {
private:
std::vector<CDObjectSkills> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate); std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
// Gets all the entries in the table
const std::vector<CDObjectSkills>& GetEntries() const;
}; };

View File

@ -1,5 +1,9 @@
#include "CDObjectsTable.h" #include "CDObjectsTable.h"
namespace {
CDObjects ObjDefault;
};
void CDObjectsTable::LoadValuesFromDatabase() { void CDObjectsTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
uint32_t size = 0; uint32_t size = 0;
@ -14,9 +18,12 @@ void CDObjectsTable::LoadValuesFromDatabase() {
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Objects"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Objects");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDObjects entry; const uint32_t lot = tableData.getIntField("id", 0);
entry.id = tableData.getIntField("id", -1);
auto& entry = entries[lot];
entry.id = lot;
entry.name = tableData.getStringField("name", ""); entry.name = tableData.getStringField("name", "");
UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);) UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);)
entry.type = tableData.getStringField("type", ""); entry.type = tableData.getStringField("type", "");
@ -31,34 +38,34 @@ void CDObjectsTable::LoadValuesFromDatabase() {
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");) UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);) UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
this->entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); ObjDefault.id = 0;
m_default.id = 0;
} }
const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) { const CDObjects& CDObjectsTable::GetByID(const uint32_t lot) {
const auto& it = this->entries.find(LOT); auto& entries = GetEntriesMutable();
if (it != this->entries.end()) { const auto& it = entries.find(lot);
if (it != entries.end()) {
return it->second; return it->second;
} }
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Objects WHERE id = ?;"); auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Objects WHERE id = ?;");
query.bind(1, static_cast<int32_t>(LOT)); query.bind(1, static_cast<int32_t>(lot));
auto tableData = query.execQuery(); auto tableData = query.execQuery();
if (tableData.eof()) { if (tableData.eof()) {
this->entries.insert(std::make_pair(LOT, m_default)); entries.emplace(lot, ObjDefault);
return m_default; return ObjDefault;
} }
// Now get the data // Now get the data
while (!tableData.eof()) { while (!tableData.eof()) {
CDObjects entry; const uint32_t lot = tableData.getIntField("id", 0);
entry.id = tableData.getIntField("id", -1);
auto& entry = entries[lot];
entry.id = lot;
entry.name = tableData.getStringField("name", ""); entry.name = tableData.getStringField("name", "");
UNUSED(entry.placeable = tableData.getIntField("placeable", -1)); UNUSED(entry.placeable = tableData.getIntField("placeable", -1));
entry.type = tableData.getStringField("type", ""); entry.type = tableData.getStringField("type", "");
@ -73,17 +80,15 @@ const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) {
UNUSED(entry.gate_version = tableData.getStringField("gate_version", "")); UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
UNUSED(entry.HQ_valid = tableData.getIntField("HQ_valid", -1)); UNUSED(entry.HQ_valid = tableData.getIntField("HQ_valid", -1));
this->entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
const auto& it2 = entries.find(LOT); const auto& it2 = entries.find(lot);
if (it2 != entries.end()) { if (it2 != entries.end()) {
return it2->second; return it2->second;
} }
return m_default; return ObjDefault;
} }

View File

@ -3,6 +3,8 @@
// Custom Classes // Custom Classes
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
struct CDObjects { struct CDObjects {
uint32_t id; //!< The LOT of the object uint32_t id; //!< The LOT of the object
std::string name; //!< The internal name of the object std::string name; //!< The internal name of the object
@ -20,14 +22,10 @@ struct CDObjects {
UNUSED(uint32_t HQ_valid); //!< Probably used for the Nexus HQ database on LEGOUniverse.com UNUSED(uint32_t HQ_valid); //!< Probably used for the Nexus HQ database on LEGOUniverse.com
}; };
class CDObjectsTable : public CDTable<CDObjectsTable> { class CDObjectsTable : public CDTable<CDObjectsTable, std::map<uint32_t, CDObjects>> {
private:
std::map<uint32_t, CDObjects> entries;
CDObjects m_default;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Gets an entry by ID // Gets an entry by ID
const CDObjects& GetByID(uint32_t LOT); const CDObjects& GetByID(const uint32_t lot);
}; };

View File

@ -13,18 +13,17 @@ void CDPackageComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size auto& entries = GetEntriesMutable();
this->entries.reserve(size); entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PackageComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PackageComponent");
while (!tableData.eof()) { while (!tableData.eof()) {
CDPackageComponent entry; auto& entry = entries.emplace_back();
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1); entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
entry.packageType = tableData.getIntField("packageType", -1); entry.packageType = tableData.getIntField("packageType", -1);
this->entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -34,15 +33,9 @@ void CDPackageComponentTable::LoadValuesFromDatabase() {
//! Queries the table with a custom "where" clause //! Queries the table with a custom "where" clause
std::vector<CDPackageComponent> CDPackageComponentTable::Query(std::function<bool(CDPackageComponent)> predicate) { std::vector<CDPackageComponent> CDPackageComponentTable::Query(std::function<bool(CDPackageComponent)> predicate) {
std::vector<CDPackageComponent> data = cpplinq::from(this->entries) std::vector<CDPackageComponent> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
//! Gets all the entries in the table
const std::vector<CDPackageComponent>& CDPackageComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -3,20 +3,17 @@
// Custom Classes // Custom Classes
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
struct CDPackageComponent { struct CDPackageComponent {
uint32_t id; uint32_t id;
uint32_t LootMatrixIndex; uint32_t LootMatrixIndex;
uint32_t packageType; uint32_t packageType;
}; };
class CDPackageComponentTable : public CDTable<CDPackageComponentTable> { class CDPackageComponentTable : public CDTable<CDPackageComponentTable, std::vector<CDPackageComponent>> {
private:
std::vector<CDPackageComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate); std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
const std::vector<CDPackageComponent>& GetEntries() const;
}; };

View File

@ -23,10 +23,12 @@ namespace {
void CDPetComponentTable::LoadValuesFromDatabase() { void CDPetComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PetComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PetComponent");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
const uint32_t componentID = tableData.getIntField("id", defaultEntry.id); const uint32_t componentID = tableData.getIntField("id", defaultEntry.id);
auto& entry = m_Entries[componentID]; auto& entry = entries[componentID];
entry.id = componentID; entry.id = componentID;
UNUSED_COLUMN(entry.minTameUpdateTime = tableData.getFloatField("minTameUpdateTime", defaultEntry.minTameUpdateTime)); UNUSED_COLUMN(entry.minTameUpdateTime = tableData.getFloatField("minTameUpdateTime", defaultEntry.minTameUpdateTime));
UNUSED_COLUMN(entry.maxTameUpdateTime = tableData.getFloatField("maxTameUpdateTime", defaultEntry.maxTameUpdateTime)); UNUSED_COLUMN(entry.maxTameUpdateTime = tableData.getFloatField("maxTameUpdateTime", defaultEntry.maxTameUpdateTime));
@ -48,12 +50,13 @@ void CDPetComponentTable::LoadValuesFromDatabase() {
} }
void CDPetComponentTable::LoadValuesFromDefaults() { void CDPetComponentTable::LoadValuesFromDefaults() {
m_Entries.insert(std::make_pair(defaultEntry.id, defaultEntry)); GetEntriesMutable().insert(std::make_pair(defaultEntry.id, defaultEntry));
} }
CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) { CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) {
auto itr = m_Entries.find(componentID); auto& entries = GetEntriesMutable();
if (itr == m_Entries.end()) { auto itr = entries.find(componentID);
if (itr == entries.end()) {
LOG("Unable to load pet component (ID %i) values from database! Using default values instead.", componentID); LOG("Unable to load pet component (ID %i) values from database! Using default values instead.", componentID);
return defaultEntry; return defaultEntry;
} }

View File

@ -21,7 +21,7 @@ struct CDPetComponent {
UNUSED_COLUMN(std::string buffIDs;) UNUSED_COLUMN(std::string buffIDs;)
}; };
class CDPetComponentTable : public CDTable<CDPetComponentTable> { class CDPetComponentTable : public CDTable<CDPetComponentTable, std::map<uint32_t, CDPetComponent>> {
public: public:
/** /**
@ -39,7 +39,4 @@ public:
* @returns A reference to the corresponding table, or the default if one could not be found * @returns A reference to the corresponding table, or the default if one could not be found
*/ */
CDPetComponent& GetByID(const uint32_t componentID); CDPetComponent& GetByID(const uint32_t componentID);
private:
std::map<uint32_t, CDPetComponent> m_Entries;
}; };

View File

@ -2,34 +2,35 @@
void CDPhysicsComponentTable::LoadValuesFromDatabase() { void CDPhysicsComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDPhysicsComponent entry; const uint32_t componentID = tableData.getIntField("id", -1);
entry.id = tableData.getIntField("id", -1);
auto& entry = entries[componentID];
entry.id = componentID;
entry.bStatic = tableData.getIntField("static", -1) != 0; entry.bStatic = tableData.getIntField("static", -1) != 0;
entry.physicsAsset = tableData.getStringField("physics_asset", ""); entry.physicsAsset = tableData.getStringField("physics_asset", "");
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0); UNUSED_COLUMN(entry.jump = tableData.getIntField("jump", -1) != 0;)
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0); UNUSED_COLUMN(entry.doubleJump = tableData.getIntField("doublejump", -1) != 0;)
entry.speed = tableData.getFloatField("speed", -1); entry.speed = static_cast<float>(tableData.getFloatField("speed", -1));
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1)); UNUSED_COLUMN(entry.rotSpeed = tableData.getFloatField("rotSpeed", -1);)
entry.playerHeight = tableData.getFloatField("playerHeight"); entry.playerHeight = static_cast<float>(tableData.getFloatField("playerHeight"));
entry.playerRadius = tableData.getFloatField("playerRadius"); entry.playerRadius = static_cast<float>(tableData.getFloatField("playerRadius"));
entry.pcShapeType = tableData.getIntField("pcShapeType"); entry.pcShapeType = tableData.getIntField("pcShapeType");
entry.collisionGroup = tableData.getIntField("collisionGroup"); entry.collisionGroup = tableData.getIntField("collisionGroup");
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed")); UNUSED_COLUMN(entry.airSpeed = tableData.getFloatField("airSpeed");)
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset")); UNUSED_COLUMN(entry.boundaryAsset = tableData.getStringField("boundaryAsset");)
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed")); UNUSED_COLUMN(entry.jumpAirSpeed = tableData.getFloatField("jumpAirSpeed");)
UNUSED(entry->friction = tableData.getFloatField("friction")); UNUSED_COLUMN(entry.friction = tableData.getFloatField("friction");)
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset")); UNUSED_COLUMN(entry.gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset");)
m_entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize();
} }
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(uint32_t componentID) { CDPhysicsComponent* CDPhysicsComponentTable::GetByID(const uint32_t componentID) {
auto itr = m_entries.find(componentID); auto& entries = GetEntriesMutable();
return itr != m_entries.end() ? &itr->second : nullptr; auto itr = entries.find(componentID);
return itr != entries.end() ? &itr->second : nullptr;
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "CDTable.h" #include "CDTable.h"
#include <cstdint>
#include <string> #include <string>
struct CDPhysicsComponent { struct CDPhysicsComponent {
@ -7,7 +8,7 @@ struct CDPhysicsComponent {
bool bStatic; bool bStatic;
std::string physicsAsset; std::string physicsAsset;
UNUSED(bool jump); UNUSED(bool jump);
UNUSED(bool doublejump); UNUSED(bool doubleJump);
float speed; float speed;
UNUSED(float rotSpeed); UNUSED(float rotSpeed);
float playerHeight; float playerHeight;
@ -21,13 +22,10 @@ struct CDPhysicsComponent {
UNUSED(std::string gravityVolumeAsset); UNUSED(std::string gravityVolumeAsset);
}; };
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> { class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable, std::map<uint32_t, CDPhysicsComponent>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
static const std::string GetTableName() { return "PhysicsComponent"; }; static const std::string GetTableName() { return "PhysicsComponent"; };
CDPhysicsComponent* GetByID(uint32_t componentID); CDPhysicsComponent* GetByID(const uint32_t componentID);
private:
std::map<uint32_t, CDPhysicsComponent> m_entries;
}; };

View File

@ -1,5 +1,9 @@
#include "CDPropertyEntranceComponentTable.h" #include "CDPropertyEntranceComponentTable.h"
namespace {
CDPropertyEntranceComponent defaultEntry{};
};
void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() { void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
@ -12,7 +16,8 @@ void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PropertyEntranceComponent;"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PropertyEntranceComponent;");
while (!tableData.eof()) { while (!tableData.eof()) {
@ -24,7 +29,7 @@ void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
tableData.getStringField("groupType", "") tableData.getStringField("groupType", "")
}; };
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -32,11 +37,10 @@ void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
} }
CDPropertyEntranceComponent CDPropertyEntranceComponentTable::GetByID(uint32_t id) { CDPropertyEntranceComponent CDPropertyEntranceComponentTable::GetByID(uint32_t id) {
for (const auto& entry : entries) { for (const auto& entry : GetEntries()) {
if (entry.id == id) if (entry.id == id)
return entry; return entry;
} }
return defaultEntry; return defaultEntry;
} }

View File

@ -9,15 +9,9 @@ struct CDPropertyEntranceComponent {
std::string groupType; std::string groupType;
}; };
class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable> { class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable, std::vector<CDPropertyEntranceComponent>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
CDPropertyEntranceComponent GetByID(uint32_t id); CDPropertyEntranceComponent GetByID(uint32_t id);
// Gets all the entries in the table
[[nodiscard]] const std::vector<CDPropertyEntranceComponent>& GetEntries() const { return entries; }
private:
std::vector<CDPropertyEntranceComponent> entries{};
CDPropertyEntranceComponent defaultEntry{};
}; };

View File

@ -1,5 +1,9 @@
#include "CDPropertyTemplateTable.h" #include "CDPropertyTemplateTable.h"
namespace {
CDPropertyTemplate defaultEntry{};
};
void CDPropertyTemplateTable::LoadValuesFromDatabase() { void CDPropertyTemplateTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
@ -12,7 +16,8 @@ void CDPropertyTemplateTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PropertyTemplate;"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PropertyTemplate;");
while (!tableData.eof()) { while (!tableData.eof()) {
@ -23,7 +28,7 @@ void CDPropertyTemplateTable::LoadValuesFromDatabase() {
tableData.getStringField("spawnName", "") tableData.getStringField("spawnName", "")
}; };
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -31,7 +36,7 @@ void CDPropertyTemplateTable::LoadValuesFromDatabase() {
} }
CDPropertyTemplate CDPropertyTemplateTable::GetByMapID(uint32_t mapID) { CDPropertyTemplate CDPropertyTemplateTable::GetByMapID(uint32_t mapID) {
for (const auto& entry : entries) { for (const auto& entry : GetEntries()) {
if (entry.mapID == mapID) if (entry.mapID == mapID)
return entry; return entry;
} }

View File

@ -8,13 +8,9 @@ struct CDPropertyTemplate {
std::string spawnName; std::string spawnName;
}; };
class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable> { class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable, std::vector<CDPropertyTemplate>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
static const std::string GetTableName() { return "PropertyTemplate"; };
CDPropertyTemplate GetByMapID(uint32_t mapID); CDPropertyTemplate GetByMapID(uint32_t mapID);
private:
std::vector<CDPropertyTemplate> entries{};
CDPropertyTemplate defaultEntry{};
}; };

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