mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-23 05:57:20 +00:00
Merge branch 'main' into cdclient-rework
This commit is contained in:
commit
45ae46f6f1
7
.github/workflows/build-and-test.yml
vendored
7
.github/workflows/build-and-test.yml
vendored
@ -12,18 +12,21 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ windows-2022, ubuntu-20.04 ]
|
os: [ windows-2022, ubuntu-20.04, macos-11 ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Add msbuild to PATH (windows only)
|
- name: Add msbuild to PATH (Windows only)
|
||||||
if: ${{ matrix.os == 'windows-2022' }}
|
if: ${{ matrix.os == 'windows-2022' }}
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
with:
|
with:
|
||||||
vs-version: '[17,18)'
|
vs-version: '[17,18)'
|
||||||
msbuild-architecture: x64
|
msbuild-architecture: x64
|
||||||
|
- name: Install libssl (Mac Only)
|
||||||
|
if: ${{ matrix.os == 'macos-11' }}
|
||||||
|
run: brew install openssl@3
|
||||||
- name: cmake
|
- name: cmake
|
||||||
uses: lukka/run-cmake@v10
|
uses: lukka/run-cmake@v10
|
||||||
with:
|
with:
|
||||||
|
444
CMakeLists.txt
444
CMakeLists.txt
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.14)
|
|||||||
project(Darkflame)
|
project(Darkflame)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
set (CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
# Read variables from file
|
# Read variables from file
|
||||||
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
|
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
|
||||||
|
|
||||||
@ -34,68 +36,43 @@ foreach(variable ${variables})
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# On windows it's better to build this from source, as there's no way FindZLIB is gonna find it
|
|
||||||
if(NOT WIN32)
|
|
||||||
find_package(ZLIB REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Fetch External (Non-Submodule) Libraries
|
|
||||||
if(WIN32)
|
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
|
||||||
zlib
|
|
||||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
|
||||||
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
|
|
||||||
)
|
|
||||||
|
|
||||||
FetchContent_MakeAvailable(zlib)
|
|
||||||
|
|
||||||
set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
|
|
||||||
set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}") # Why?
|
|
||||||
add_library(ZLIB::ZLIB ALIAS zlib) # You're welcome
|
|
||||||
|
|
||||||
endif(WIN32)
|
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
include(FetchContent)
|
|
||||||
if (__include_backtrace__ AND __compile_backtrace__)
|
|
||||||
FetchContent_Declare(
|
|
||||||
backtrace
|
|
||||||
GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace.git
|
|
||||||
)
|
|
||||||
|
|
||||||
FetchContent_MakeAvailable(backtrace)
|
|
||||||
|
|
||||||
if (NOT EXISTS ${backtrace_SOURCE_DIR}/.libs)
|
|
||||||
set(backtrace_make_cmd "${backtrace_SOURCE_DIR}/configure --prefix=\"/usr\" --enable-shared --with-system-libunwind")
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND bash -c "cd ${backtrace_SOURCE_DIR} && ${backtrace_make_cmd} && make && cd ${CMAKE_SOURCE_DIR}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
link_directories(${backtrace_SOURCE_DIR}/.libs/)
|
|
||||||
include_directories(${backtrace_SOURCE_DIR})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Set the version
|
# Set the version
|
||||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROJECT_VERSION=${PROJECT_VERSION}")
|
|
||||||
|
|
||||||
# Echo the version
|
# Echo the version
|
||||||
message(STATUS "Version: ${PROJECT_VERSION}")
|
message(STATUS "Version: ${PROJECT_VERSION}")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
# Compiler flags:
|
||||||
|
# Disabled deprecated warnings as the MySQL includes have deprecated code in them.
|
||||||
if(WIN32)
|
# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent.
|
||||||
|
# Disabled no-register
|
||||||
|
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROJECT_VERSION=${PROJECT_VERSION}")
|
||||||
|
if(UNIX)
|
||||||
|
if(APPLE)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -fPIC")
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC")
|
||||||
|
endif()
|
||||||
|
if (__dynamic)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
|
||||||
|
endif()
|
||||||
|
if (__ggdb)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
|
||||||
|
elseif(MSVC)
|
||||||
|
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
|
||||||
|
add_compile_options("/wd4267")
|
||||||
|
elseif(WIN32)
|
||||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||||
endif(WIN32)
|
endif()
|
||||||
|
|
||||||
# Our output dir
|
# Our output dir
|
||||||
set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR})
|
set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR})
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
# Create a /res directory
|
# Create a /res directory
|
||||||
make_directory(${CMAKE_BINARY_DIR}/res)
|
make_directory(${CMAKE_BINARY_DIR}/res)
|
||||||
@ -107,139 +84,90 @@ make_directory(${CMAKE_BINARY_DIR}/locale)
|
|||||||
make_directory(${CMAKE_BINARY_DIR}/logs)
|
make_directory(${CMAKE_BINARY_DIR}/logs)
|
||||||
|
|
||||||
# Copy ini files on first build
|
# Copy ini files on first build
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/authconfig.ini)
|
set(INI_FILES "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini")
|
||||||
|
foreach(ini ${INI_FILES})
|
||||||
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${ini})
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_SOURCE_DIR}/resources/authconfig.ini ${PROJECT_BINARY_DIR}/authconfig.ini
|
${CMAKE_SOURCE_DIR}/resources/${ini} ${PROJECT_BINARY_DIR}/${ini}
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/chatconfig.ini)
|
endforeach()
|
||||||
|
|
||||||
|
# Copy vanity files on first build
|
||||||
|
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml")
|
||||||
|
foreach(file ${VANITY_FILES})
|
||||||
|
configure_file("${CMAKE_SOURCE_DIR}/vanity/${file}" "${CMAKE_BINARY_DIR}/vanity/${file}" COPYONLY)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Move our migrations for MasterServer to run
|
||||||
|
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/migrations/)
|
||||||
|
file(GLOB SQL_FILES ${CMAKE_SOURCE_DIR}/migrations/dlu/*.sql)
|
||||||
|
foreach(file ${SQL_FILES})
|
||||||
|
get_filename_component(file ${file} NAME)
|
||||||
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/migrations/${file})
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_SOURCE_DIR}/resources/chatconfig.ini ${PROJECT_BINARY_DIR}/chatconfig.ini
|
${CMAKE_SOURCE_DIR}/migrations/dlu/${file} ${PROJECT_BINARY_DIR}/migrations/${file}
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/worldconfig.ini)
|
endforeach()
|
||||||
configure_file(
|
|
||||||
${CMAKE_SOURCE_DIR}/resources/worldconfig.ini ${PROJECT_BINARY_DIR}/worldconfig.ini
|
# Create our list of include directories
|
||||||
COPYONLY
|
set(INCLUDED_DIRECTORIES
|
||||||
)
|
"dCommon"
|
||||||
endif()
|
"dChatFilter"
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/masterconfig.ini)
|
"dGame"
|
||||||
configure_file(
|
"dGame/dBehaviors"
|
||||||
${CMAKE_SOURCE_DIR}/resources/masterconfig.ini ${PROJECT_BINARY_DIR}/masterconfig.ini
|
"dGame/dComponents"
|
||||||
COPYONLY
|
"dGame/dGameMessages"
|
||||||
|
"dGame/dInventory"
|
||||||
|
"dGame/dMission"
|
||||||
|
"dGame/dEntity"
|
||||||
|
"dGame/dUtilities"
|
||||||
|
"dPhysics"
|
||||||
|
"dZoneManager"
|
||||||
|
"dDatabase"
|
||||||
|
"dDatabase/Tables"
|
||||||
|
"dNet"
|
||||||
|
"dScripts"
|
||||||
|
|
||||||
|
"thirdparty/raknet/Source"
|
||||||
|
"thirdparty/tinyxml2"
|
||||||
|
"thirdparty/recastnavigation/Recast/Include"
|
||||||
|
"thirdparty/recastnavigation/Detour/Include"
|
||||||
|
"thirdparty/SQLite"
|
||||||
|
"thirdparty/cpplinq"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
||||||
|
if (APPLE)
|
||||||
|
include_directories("/usr/local/include/")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Copy files to output
|
if (WIN32)
|
||||||
configure_file("${CMAKE_SOURCE_DIR}/vanity/CREDITS.md" "${CMAKE_BINARY_DIR}/vanity/CREDITS.md" COPYONLY)
|
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include")
|
||||||
configure_file("${CMAKE_SOURCE_DIR}/vanity/INFO.md" "${CMAKE_BINARY_DIR}/vanity/INFO.md" COPYONLY)
|
elseif (UNIX)
|
||||||
configure_file("${CMAKE_SOURCE_DIR}/vanity/TESTAMENT.md" "${CMAKE_BINARY_DIR}/vanity/TESTAMENT.md" COPYONLY)
|
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt")
|
||||||
configure_file("${CMAKE_SOURCE_DIR}/vanity/NPC.xml" "${CMAKE_BINARY_DIR}/vanity/NPC.xml" COPYONLY)
|
set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include/bcrypt")
|
||||||
|
endif()
|
||||||
|
|
||||||
# 3rdparty includes
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/raknet/Source/)
|
|
||||||
if(APPLE)
|
|
||||||
include_directories(/usr/local/include/)
|
|
||||||
endif(APPLE)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Recast/Include)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/recastnavigation/Detour/Include)
|
|
||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
|
# Add binary directory as an include directory
|
||||||
# Bcrypt
|
|
||||||
if (NOT WIN32)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include/bcrypt)
|
|
||||||
else ()
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/libbcrypt/include)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Our includes
|
|
||||||
include_directories(${PROJECT_BINARY_DIR})
|
include_directories(${PROJECT_BINARY_DIR})
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dChatFilter/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dGame/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dGame/dBehaviors)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dGame/dComponents)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dGame/dGameMessages)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dGame/dInventory)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dGame/dMission)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dGame/dEntity)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dGame/dUtilities)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dPhysics/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dZoneManager/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dDatabase/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dDatabase/Tables/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/SQLite/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/cpplinq/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dNet/)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/dScripts/)
|
|
||||||
|
|
||||||
# Lib folders:
|
# Actually include the directories from our list
|
||||||
|
foreach (dir ${INCLUDED_DIRECTORIES})
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/${dir})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Add linking directories:
|
||||||
link_directories(${PROJECT_BINARY_DIR})
|
link_directories(${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
# Third-Party libraries
|
# Load all of our third party directories
|
||||||
add_subdirectory(thirdparty)
|
add_subdirectory(thirdparty)
|
||||||
|
|
||||||
# Source Code
|
# Glob together all headers that need to be precompiled
|
||||||
file(
|
|
||||||
GLOB SOURCES
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dWorldServer/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source Code for AuthServer
|
|
||||||
file(
|
|
||||||
GLOB SOURCES_AUTH
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dAuthServer/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source Code for MasterServer
|
|
||||||
file(
|
|
||||||
GLOB SOURCES_MASTER
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dMasterServer/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source Code for ChatServer
|
|
||||||
file(
|
|
||||||
GLOB SOURCES_CHAT
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dChatServer/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source Code for dCommon
|
|
||||||
file(
|
|
||||||
GLOB SOURCES_DCOMMON
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dCommon/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source Code for dChatFilter
|
|
||||||
file(
|
|
||||||
GLOB SOURCES_DCHATFILTER
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dChatFilter/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source Code for dDatabase
|
|
||||||
file(
|
|
||||||
GLOB SOURCES_DDATABASE
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dDatabase/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dDatabase/Tables/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
file(
|
file(
|
||||||
GLOB HEADERS_DDATABASE
|
GLOB HEADERS_DDATABASE
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
@ -269,80 +197,37 @@ file(
|
|||||||
${PROJECT_SOURCE_DIR}/dScripts/CppScripts.h
|
${PROJECT_SOURCE_DIR}/dScripts/CppScripts.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# Source Code for dNet
|
# Add our library subdirectories for creation of the library object
|
||||||
file(
|
add_subdirectory(dCommon)
|
||||||
GLOB SOURCES_DNET
|
add_subdirectory(dDatabase)
|
||||||
LIST_DIRECTORIES false
|
add_subdirectory(dChatFilter)
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
add_subdirectory(dNet)
|
||||||
${PROJECT_SOURCE_DIR}/dNet/*.cpp
|
add_subdirectory(dScripts) # Add for dGame to use
|
||||||
)
|
add_subdirectory(dGame)
|
||||||
|
add_subdirectory(dZoneManager)
|
||||||
|
add_subdirectory(dPhysics)
|
||||||
|
|
||||||
# Source Code for dGame
|
# Create a list of common libraries shared between all binaries
|
||||||
file(
|
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp")
|
||||||
GLOB SOURCES_DGAME
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/dBehaviors/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/dComponents/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/dGameMessages/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/dInventory/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/dMission/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/dEntity/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/dUtilities/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/dScripts/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source Code for dZoneManager
|
# Add platform specific common libraries
|
||||||
file(
|
if (UNIX)
|
||||||
GLOB SOURCES_DZM
|
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "dl" "pthread")
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dZoneManager/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source Code for dPhysics
|
if (NOT APPLE AND __include_backtrace__)
|
||||||
file(
|
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "backtrace")
|
||||||
GLOB SOURCES_DPHYSICS
|
endif()
|
||||||
LIST_DIRECTORIES false
|
endif()
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
${PROJECT_SOURCE_DIR}/dPhysics/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
if(MSVC)
|
add_subdirectory(tests)
|
||||||
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
|
|
||||||
add_compile_options("/wd4267")
|
|
||||||
endif(MSVC)
|
|
||||||
|
|
||||||
# Our static libraries:
|
# Include all of our binary directories
|
||||||
add_library(dCommon ${SOURCES_DCOMMON})
|
add_subdirectory(dWorldServer)
|
||||||
add_library(dChatFilter ${SOURCES_DCHATFILTER})
|
add_subdirectory(dAuthServer)
|
||||||
add_library(dDatabase ${SOURCES_DDATABASE})
|
add_subdirectory(dChatServer)
|
||||||
add_library(dNet ${SOURCES_DNET})
|
add_subdirectory(dMasterServer) # Add MasterServer last so it can rely on the other binaries
|
||||||
add_library(dGame ${SOURCES_DGAME})
|
|
||||||
add_library(dZoneManager ${SOURCES_DZM})
|
|
||||||
add_library(dPhysics ${SOURCES_DPHYSICS})
|
|
||||||
target_link_libraries(dDatabase sqlite3)
|
|
||||||
target_link_libraries(dNet dCommon) #Needed because otherwise linker errors occur.
|
|
||||||
target_link_libraries(dCommon ZLIB::ZLIB)
|
|
||||||
target_link_libraries(dCommon libbcrypt)
|
|
||||||
target_link_libraries(dDatabase mariadbConnCpp)
|
|
||||||
target_link_libraries(dNet dDatabase)
|
|
||||||
target_link_libraries(dGame dDatabase)
|
|
||||||
target_link_libraries(dChatFilter dDatabase)
|
|
||||||
|
|
||||||
|
# Add our precompiled headers
|
||||||
if(WIN32)
|
|
||||||
target_link_libraries(raknet ws2_32)
|
|
||||||
endif(WIN32)
|
|
||||||
|
|
||||||
# Our executables:
|
|
||||||
add_executable(WorldServer ${SOURCES})
|
|
||||||
add_executable(AuthServer ${SOURCES_AUTH})
|
|
||||||
add_executable(MasterServer ${SOURCES_MASTER})
|
|
||||||
add_executable(ChatServer ${SOURCES_CHAT})
|
|
||||||
|
|
||||||
# Add out precompiled headers
|
|
||||||
target_precompile_headers(
|
target_precompile_headers(
|
||||||
dGame PRIVATE
|
dGame PRIVATE
|
||||||
${HEADERS_DGAME}
|
${HEADERS_DGAME}
|
||||||
@ -368,90 +253,3 @@ target_precompile_headers(
|
|||||||
tinyxml2 PRIVATE
|
tinyxml2 PRIVATE
|
||||||
"$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>"
|
"$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Target libraries to link to:
|
|
||||||
target_link_libraries(WorldServer dCommon)
|
|
||||||
target_link_libraries(WorldServer dChatFilter)
|
|
||||||
target_link_libraries(WorldServer dDatabase)
|
|
||||||
target_link_libraries(WorldServer dNet)
|
|
||||||
target_link_libraries(WorldServer dGame)
|
|
||||||
target_link_libraries(WorldServer dZoneManager)
|
|
||||||
target_link_libraries(WorldServer dPhysics)
|
|
||||||
target_link_libraries(WorldServer detour)
|
|
||||||
target_link_libraries(WorldServer recast)
|
|
||||||
target_link_libraries(WorldServer raknet)
|
|
||||||
target_link_libraries(WorldServer mariadbConnCpp)
|
|
||||||
if(UNIX)
|
|
||||||
if(NOT APPLE AND __include_backtrace__)
|
|
||||||
target_link_libraries(WorldServer backtrace)
|
|
||||||
target_link_libraries(MasterServer backtrace)
|
|
||||||
target_link_libraries(AuthServer backtrace)
|
|
||||||
target_link_libraries(ChatServer backtrace)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif(UNIX)
|
|
||||||
target_link_libraries(WorldServer tinyxml2)
|
|
||||||
|
|
||||||
# Target libraries for Auth:
|
|
||||||
target_link_libraries(AuthServer dCommon)
|
|
||||||
target_link_libraries(AuthServer dDatabase)
|
|
||||||
target_link_libraries(AuthServer dNet)
|
|
||||||
target_link_libraries(AuthServer raknet)
|
|
||||||
target_link_libraries(AuthServer mariadbConnCpp)
|
|
||||||
if(UNIX)
|
|
||||||
target_link_libraries(AuthServer pthread)
|
|
||||||
target_link_libraries(AuthServer dl)
|
|
||||||
endif(UNIX)
|
|
||||||
|
|
||||||
# Target libraries for Master:
|
|
||||||
target_link_libraries(MasterServer dCommon)
|
|
||||||
target_link_libraries(MasterServer dDatabase)
|
|
||||||
target_link_libraries(MasterServer dNet)
|
|
||||||
target_link_libraries(MasterServer raknet)
|
|
||||||
target_link_libraries(MasterServer mariadbConnCpp)
|
|
||||||
if(UNIX)
|
|
||||||
target_link_libraries(MasterServer pthread)
|
|
||||||
target_link_libraries(MasterServer dl)
|
|
||||||
endif(UNIX)
|
|
||||||
|
|
||||||
# Target libraries for Chat:
|
|
||||||
target_link_libraries(ChatServer dCommon)
|
|
||||||
target_link_libraries(ChatServer dChatFilter)
|
|
||||||
target_link_libraries(ChatServer dDatabase)
|
|
||||||
target_link_libraries(ChatServer dNet)
|
|
||||||
target_link_libraries(ChatServer raknet)
|
|
||||||
target_link_libraries(ChatServer mariadbConnCpp)
|
|
||||||
if(UNIX)
|
|
||||||
target_link_libraries(ChatServer pthread)
|
|
||||||
target_link_libraries(ChatServer dl)
|
|
||||||
endif(UNIX)
|
|
||||||
|
|
||||||
# Compiler flags:
|
|
||||||
# Disabled deprecated warnings as the MySQL includes have deprecated code in them.
|
|
||||||
# Disabled misleading indentation as DL_LinkedList from RakNet has a weird indent.
|
|
||||||
# Disabled no-register
|
|
||||||
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
|
||||||
if(UNIX)
|
|
||||||
if(APPLE)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -fPIC")
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_CXX17_ABI=0 -static-libgcc -fPIC")
|
|
||||||
endif()
|
|
||||||
if (__dynamic)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
|
|
||||||
endif()
|
|
||||||
if (__ggdb)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
|
|
||||||
endif()
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
|
|
||||||
endif(UNIX)
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
add_dependencies(MasterServer WorldServer)
|
|
||||||
add_dependencies(MasterServer AuthServer)
|
|
||||||
add_dependencies(MasterServer ChatServer)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Finally, add the tests
|
|
||||||
add_subdirectory(tests)
|
|
||||||
|
|
||||||
|
@ -19,6 +19,15 @@
|
|||||||
"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",
|
||||||
|
"displayName": "CI configure step for MacOS",
|
||||||
|
"description": "Same as default, Used in GitHub actions workflow",
|
||||||
|
"inherits": "default",
|
||||||
|
"cacheVariables": {
|
||||||
|
"OPENSSL_ROOT_DIR": "/usr/local/Cellar/openssl@3/3.0.5/"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ci-windows-2022",
|
"name": "ci-windows-2022",
|
||||||
"displayName": "CI configure step for Windows",
|
"displayName": "CI configure step for Windows",
|
||||||
@ -66,6 +75,13 @@
|
|||||||
"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",
|
||||||
|
"configurePreset": "ci-macos-11",
|
||||||
|
"displayName": "MacOS CI Build",
|
||||||
|
"description": "This preset is used by the CI build on MacOS",
|
||||||
|
"jobs": 2
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"testPresets": [
|
"testPresets": [
|
||||||
@ -81,6 +97,18 @@
|
|||||||
"outputOnFailure": true
|
"outputOnFailure": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "ci-macos-11",
|
||||||
|
"configurePreset": "ci-macos-11",
|
||||||
|
"displayName": "CI Tests on MacOS",
|
||||||
|
"description": "Runs all tests on a Mac configuration",
|
||||||
|
"execution": {
|
||||||
|
"jobs": 2
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"outputOnFailure": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ci-windows-2022",
|
"name": "ci-windows-2022",
|
||||||
"configurePreset": "ci-windows-2022",
|
"configurePreset": "ci-windows-2022",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
PROJECT_VERSION_MAJOR=1
|
PROJECT_VERSION_MAJOR=1
|
||||||
PROJECT_VERSION_MINOR=0
|
PROJECT_VERSION_MINOR=0
|
||||||
PROJECT_VERSION_PATCH=2
|
PROJECT_VERSION_PATCH=3
|
||||||
# LICENSE
|
# LICENSE
|
||||||
LICENSE=AGPL-3.0
|
LICENSE=AGPL-3.0
|
||||||
# The network version.
|
# The network version.
|
||||||
|
14
README.md
14
README.md
@ -152,13 +152,6 @@ now follow the build section for your system
|
|||||||
|
|
||||||
## Setting up the environment
|
## Setting up the environment
|
||||||
|
|
||||||
### Database
|
|
||||||
Darkflame Universe utilizes a MySQL/MariaDB database for account and character information.
|
|
||||||
|
|
||||||
Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running.
|
|
||||||
* Create a database for Darkflame Universe to use
|
|
||||||
* Run each SQL file in the order at which they appear [here](migrations/dlu/) on the database
|
|
||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
||||||
**LEGO® Universe 1.10.64**
|
**LEGO® Universe 1.10.64**
|
||||||
@ -202,6 +195,13 @@ certutil -hashfile <file> SHA256
|
|||||||
* Move and rename `cdclient.sqlite` into `build/res/CDServer.sqlite`
|
* Move and rename `cdclient.sqlite` into `build/res/CDServer.sqlite`
|
||||||
* Run each SQL file in the order at which they appear [here](migrations/cdserver/) on the SQLite database
|
* Run each SQL file in the order at which they appear [here](migrations/cdserver/) on the SQLite database
|
||||||
|
|
||||||
|
### Database
|
||||||
|
Darkflame Universe utilizes a MySQL/MariaDB database for account and character information.
|
||||||
|
|
||||||
|
Initial setup can vary drastically based on which operating system or distribution you are running; there are instructions out there for most setups, follow those and come back here when you have a database up and running.
|
||||||
|
* Create a database for Darkflame Universe to use
|
||||||
|
* Use the command `./MasterServer -m` to automatically run them.
|
||||||
|
|
||||||
**Configuration**
|
**Configuration**
|
||||||
|
|
||||||
After the server has been built there should be four `ini` files in the build director: `authconfig.ini`, `chatconfig.ini`, `masterconfig.ini`, and `worldconfig.ini`. Go through them and fill in the database credentials and configure other settings if necessary.
|
After the server has been built there should be four `ini` files in the build director: `authconfig.ini`, `chatconfig.ini`, `masterconfig.ini`, and `worldconfig.ini`. Go through them and fill in the database credentials and configure other settings if necessary.
|
||||||
|
4
dAuthServer/CMakeLists.txt
Normal file
4
dAuthServer/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
set(DAUTHSERVER_SOURCES "AuthServer.cpp")
|
||||||
|
|
||||||
|
add_executable(AuthServer ${DAUTHSERVER_SOURCES})
|
||||||
|
target_link_libraries(AuthServer ${COMMON_LIBRARIES})
|
4
dChatFilter/CMakeLists.txt
Normal file
4
dChatFilter/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
set(DCHATFILTER_SOURCES "dChatFilter.cpp")
|
||||||
|
|
||||||
|
add_library(dChatFilter STATIC ${DCHATFILTER_SOURCES})
|
||||||
|
target_link_libraries(dChatFilter dDatabase)
|
6
dChatServer/CMakeLists.txt
Normal file
6
dChatServer/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
set(DCHATSERVER_SOURCES "ChatPacketHandler.cpp"
|
||||||
|
"ChatServer.cpp"
|
||||||
|
"PlayerContainer.cpp")
|
||||||
|
|
||||||
|
add_executable(ChatServer ${DCHATSERVER_SOURCES})
|
||||||
|
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter)
|
@ -8,6 +8,10 @@
|
|||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
|
#include "AddFriendResponseCode.h"
|
||||||
|
#include "AddFriendResponseType.h"
|
||||||
|
#include "RakString.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
|
||||||
extern PlayerContainer playerContainer;
|
extern PlayerContainer playerContainer;
|
||||||
|
|
||||||
@ -21,44 +25,41 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
auto player = playerContainer.GetPlayerData(playerID);
|
auto player = playerContainer.GetPlayerData(playerID);
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
|
|
||||||
//Get our friends list from the Db:
|
//Get our friends list from the Db. Using a derived table since the friend of a player can be in either column.
|
||||||
auto stmt = Database::CreatePreppedStmt("SELECT * FROM friends WHERE player_id = ? OR friend_id = ?");
|
std::unique_ptr<sql::PreparedStatement> stmt(Database::CreatePreppedStmt(
|
||||||
stmt->setUInt64(1, playerID);
|
"SELECT fr.requested_player, best_friend, ci.name FROM "
|
||||||
stmt->setUInt64(2, playerID);
|
"(SELECT CASE "
|
||||||
|
"WHEN player_id = ? THEN friend_id "
|
||||||
|
"WHEN friend_id = ? THEN player_id "
|
||||||
|
"END AS requested_player, best_friend FROM friends) AS fr "
|
||||||
|
"JOIN charinfo AS ci ON ci.id = fr.requested_player "
|
||||||
|
"WHERE fr.requested_player IS NOT NULL;"));
|
||||||
|
stmt->setUInt(1, static_cast<uint32_t>(playerID));
|
||||||
|
stmt->setUInt(2, static_cast<uint32_t>(playerID));
|
||||||
|
|
||||||
std::vector<FriendData> friends;
|
std::vector<FriendData> friends;
|
||||||
|
|
||||||
auto res = stmt->executeQuery();
|
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery());
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
FriendData fd;
|
FriendData fd;
|
||||||
fd.isFTP = false; // not a thing in DLU
|
fd.isFTP = false; // not a thing in DLU
|
||||||
fd.friendID = res->getInt64(1);
|
fd.friendID = res->getUInt(1);
|
||||||
if (fd.friendID == playerID) fd.friendID = res->getUInt64(2);
|
GeneralUtils::SetBit(fd.friendID, static_cast<size_t>(eObjectBits::OBJECT_BIT_PERSISTENT));
|
||||||
|
GeneralUtils::SetBit(fd.friendID, static_cast<size_t>(eObjectBits::OBJECT_BIT_CHARACTER));
|
||||||
|
|
||||||
fd.isBestFriend = res->getInt(3) == 2; //0 = friends, 1 = requested, 2 = bffs
|
fd.isBestFriend = res->getInt(2) == 3; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||||
|
if (fd.isBestFriend) player->countOfBestFriends+=1;
|
||||||
//We need to find their name as well:
|
fd.friendName = res->getString(3);
|
||||||
{
|
|
||||||
auto stmt = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE id=? limit 1");
|
|
||||||
stmt->setInt(1, fd.friendID);
|
|
||||||
|
|
||||||
auto res = stmt->executeQuery();
|
|
||||||
while (res->next()) {
|
|
||||||
fd.friendName = res->getString(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete res;
|
|
||||||
delete stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Now check if they're online:
|
//Now check if they're online:
|
||||||
auto fr = playerContainer.GetPlayerData(fd.friendID);
|
auto fr = playerContainer.GetPlayerData(fd.friendID);
|
||||||
|
|
||||||
if (fr) {
|
if (fr) {
|
||||||
fd.isOnline = true;
|
fd.isOnline = true;
|
||||||
fd.zoneID = fr->zoneID;
|
fd.zoneID = fr->zoneID;
|
||||||
|
|
||||||
//Since this friend is online, we need to update them on the fact that we've just logged in:
|
//Since this friend is online, we need to update them on the fact that we've just logged in:
|
||||||
SendFriendUpdate(fr, player, 1);
|
SendFriendUpdate(fr, player, 1, fd.isBestFriend);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fd.isOnline = false;
|
fd.isOnline = false;
|
||||||
@ -68,9 +69,6 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
friends.push_back(fd);
|
friends.push_back(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete res;
|
|
||||||
delete stmt;
|
|
||||||
|
|
||||||
//Now, we need to send the friendlist to the server they came from:
|
//Now, we need to send the friendlist to the server they came from:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
@ -93,20 +91,150 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||||
|
auto maxNumberOfBestFriendsAsString = Game::config->GetValue("max_number_of_best_friends");
|
||||||
|
// If this config option doesn't exist, default to 5 which is what live used.
|
||||||
|
auto maxNumberOfBestFriends = maxNumberOfBestFriendsAsString != "" ? std::stoi(maxNumberOfBestFriendsAsString) : 5U;
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
LWOOBJID playerID;
|
LWOOBJID requestorPlayerID;
|
||||||
inStream.Read(playerID);
|
inStream.Read(requestorPlayerID);
|
||||||
inStream.Read(playerID);
|
inStream.Read(requestorPlayerID);
|
||||||
std::string playerName = PacketUtils::ReadString(0x14, packet, true);
|
uint32_t spacing{};
|
||||||
//There's another bool here to determine if it's a best friend request, but we're not handling it right now.
|
inStream.Read(spacing);
|
||||||
|
std::string playerName = "";
|
||||||
|
uint16_t character;
|
||||||
|
bool noMoreLettersInName = false;
|
||||||
|
|
||||||
//PacketUtils::SavePacket("FriendRequest.bin", (char*)inStream.GetData(), inStream.GetNumberOfBytesUsed());
|
for (uint32_t j = 0; j < 33; j++) {
|
||||||
|
inStream.Read(character);
|
||||||
//We need to check to see if the player is actually online or not:
|
if (character == '\0') noMoreLettersInName = true;
|
||||||
auto targetData = playerContainer.GetPlayerData(playerName);
|
if (!noMoreLettersInName) playerName.push_back(static_cast<char>(character));
|
||||||
if (targetData) {
|
|
||||||
SendFriendRequest(targetData, playerContainer.GetPlayerData(playerID));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char isBestFriendRequest{};
|
||||||
|
inStream.Read(isBestFriendRequest);
|
||||||
|
|
||||||
|
auto requestor = playerContainer.GetPlayerData(requestorPlayerID);
|
||||||
|
std::unique_ptr<PlayerData> requestee(playerContainer.GetPlayerData(playerName));
|
||||||
|
|
||||||
|
// Check if player is online first
|
||||||
|
if (isBestFriendRequest && !requestee) {
|
||||||
|
for (auto friendDataCandidate : requestor->friends) {
|
||||||
|
if (friendDataCandidate.friendName == playerName) {
|
||||||
|
requestee.reset(new PlayerData());
|
||||||
|
// Setup the needed info since you can add a best friend offline.
|
||||||
|
requestee->playerID = friendDataCandidate.friendID;
|
||||||
|
requestee->playerName = friendDataCandidate.friendName;
|
||||||
|
requestee->zoneID = LWOZONEID();
|
||||||
|
|
||||||
|
FriendData requesteeFriendData{};
|
||||||
|
requesteeFriendData.friendID = requestor->playerID;
|
||||||
|
requesteeFriendData.friendName = requestor->playerName;
|
||||||
|
requesteeFriendData.isFTP = false;
|
||||||
|
requesteeFriendData.isOnline = false;
|
||||||
|
requesteeFriendData.zoneID = requestor->zoneID;
|
||||||
|
requestee->friends.push_back(requesteeFriendData);
|
||||||
|
requestee->sysAddr = UNASSIGNED_SYSTEM_ADDRESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If at this point we dont have a target, then they arent online and we cant send the request.
|
||||||
|
// Send the response code that corresponds to what the error is.
|
||||||
|
if (!requestee) {
|
||||||
|
std::unique_ptr<sql::PreparedStatement> nameQuery(Database::CreatePreppedStmt("SELECT name from charinfo where name = ?;"));
|
||||||
|
nameQuery->setString(1, playerName);
|
||||||
|
std::unique_ptr<sql::ResultSet> result(nameQuery->executeQuery());
|
||||||
|
|
||||||
|
requestee.reset(new PlayerData());
|
||||||
|
requestee->playerName = playerName;
|
||||||
|
|
||||||
|
SendFriendResponse(requestor, requestee.get(), result->next() ? AddFriendResponseType::NOTONLINE : AddFriendResponseType::INVALIDCHARACTER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBestFriendRequest) {
|
||||||
|
std::unique_ptr<sql::PreparedStatement> friendUpdate(Database::CreatePreppedStmt("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;"));
|
||||||
|
friendUpdate->setUInt(1, static_cast<uint32_t>(requestorPlayerID));
|
||||||
|
friendUpdate->setUInt(2, static_cast<uint32_t>(requestee->playerID));
|
||||||
|
friendUpdate->setUInt(3, static_cast<uint32_t>(requestee->playerID));
|
||||||
|
friendUpdate->setUInt(4, static_cast<uint32_t>(requestorPlayerID));
|
||||||
|
std::unique_ptr<sql::ResultSet> result(friendUpdate->executeQuery());
|
||||||
|
|
||||||
|
LWOOBJID queryPlayerID = LWOOBJID_EMPTY;
|
||||||
|
LWOOBJID queryFriendID = LWOOBJID_EMPTY;
|
||||||
|
uint8_t oldBestFriendStatus{};
|
||||||
|
uint8_t bestFriendStatus{};
|
||||||
|
|
||||||
|
if (result->next()) {
|
||||||
|
// Get the IDs
|
||||||
|
queryPlayerID = result->getInt(1);
|
||||||
|
queryFriendID = result->getInt(2);
|
||||||
|
oldBestFriendStatus = result->getInt(3);
|
||||||
|
bestFriendStatus = oldBestFriendStatus;
|
||||||
|
|
||||||
|
// Set the bits
|
||||||
|
GeneralUtils::SetBit(queryPlayerID, static_cast<size_t>(eObjectBits::OBJECT_BIT_CHARACTER));
|
||||||
|
GeneralUtils::SetBit(queryPlayerID, static_cast<size_t>(eObjectBits::OBJECT_BIT_PERSISTENT));
|
||||||
|
GeneralUtils::SetBit(queryFriendID, static_cast<size_t>(eObjectBits::OBJECT_BIT_CHARACTER));
|
||||||
|
GeneralUtils::SetBit(queryFriendID, static_cast<size_t>(eObjectBits::OBJECT_BIT_PERSISTENT));
|
||||||
|
|
||||||
|
// Since this player can either be the friend of someone else or be friends with someone else
|
||||||
|
// their column in the database determines what bit gets set. When the value hits 3, they
|
||||||
|
// are now best friends with the other player.
|
||||||
|
if (queryPlayerID == requestorPlayerID) {
|
||||||
|
bestFriendStatus |= 1ULL << 0;
|
||||||
|
} else {
|
||||||
|
bestFriendStatus |= 1ULL << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only do updates if there was a change in the bff status.
|
||||||
|
if (oldBestFriendStatus != bestFriendStatus) {
|
||||||
|
if (requestee->countOfBestFriends >= maxNumberOfBestFriends || requestor->countOfBestFriends >= maxNumberOfBestFriends) {
|
||||||
|
if (requestee->countOfBestFriends >= maxNumberOfBestFriends) {
|
||||||
|
SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::THEIRFRIENDLISTFULL, false);
|
||||||
|
}
|
||||||
|
if (requestor->countOfBestFriends >= maxNumberOfBestFriends) {
|
||||||
|
SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::YOURFRIENDSLISTFULL, false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Then update the database with this new info.
|
||||||
|
std::unique_ptr<sql::PreparedStatement> updateQuery(Database::CreatePreppedStmt("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;"));
|
||||||
|
updateQuery->setUInt(1, bestFriendStatus);
|
||||||
|
updateQuery->setUInt(2, static_cast<uint32_t>(requestorPlayerID));
|
||||||
|
updateQuery->setUInt(3, static_cast<uint32_t>(requestee->playerID));
|
||||||
|
updateQuery->setUInt(4, static_cast<uint32_t>(requestee->playerID));
|
||||||
|
updateQuery->setUInt(5, static_cast<uint32_t>(requestorPlayerID));
|
||||||
|
updateQuery->executeUpdate();
|
||||||
|
// Sent the best friend update here if the value is 3
|
||||||
|
if (bestFriendStatus == 3U) {
|
||||||
|
requestee->countOfBestFriends+=1;
|
||||||
|
requestor->countOfBestFriends+=1;
|
||||||
|
if (requestee->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee.get(), requestor, AddFriendResponseType::ACCEPTED, false, true);
|
||||||
|
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::ACCEPTED, false, true);
|
||||||
|
for (auto& friendData : requestor->friends) {
|
||||||
|
if (friendData.friendID == requestee->playerID) {
|
||||||
|
friendData.isBestFriend = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& friendData : requestee->friends) {
|
||||||
|
if (friendData.friendID == requestor->playerID) {
|
||||||
|
friendData.isBestFriend = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), AddFriendResponseType::WAITINGAPPROVAL, true, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Do not send this if we are requesting to be a best friend.
|
||||||
|
SendFriendRequest(requestee.get(), requestor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the player is actually a player and not a ghost one defined above, release it from being deleted.
|
||||||
|
if (requestee->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) requestee.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
||||||
@ -115,29 +243,74 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
|||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
uint8_t responseCode = packet->data[0x14];
|
AddFriendResponseCode clientResponseCode = static_cast<AddFriendResponseCode>(packet->data[0x14]);
|
||||||
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Friend response code: %i\n", responseCode);
|
|
||||||
|
|
||||||
if (responseCode != 0) return; //If we're not accepting the request, end here, do not insert to friends table.
|
|
||||||
|
|
||||||
PacketUtils::SavePacket("HandleFriendResponse.bin", (char*)inStream.GetData(), inStream.GetNumberOfBytesUsed());
|
|
||||||
|
|
||||||
//Now to try and find both of these:
|
//Now to try and find both of these:
|
||||||
auto goonA = playerContainer.GetPlayerData(playerID);
|
auto requestor = playerContainer.GetPlayerData(playerID);
|
||||||
auto goonB = playerContainer.GetPlayerData(friendName);
|
auto requestee = playerContainer.GetPlayerData(friendName);
|
||||||
if (!goonA || !goonB) return;
|
if (!requestor || !requestee) return;
|
||||||
|
|
||||||
SendFriendResponse(goonB, goonA, responseCode);
|
AddFriendResponseType serverResponseCode{};
|
||||||
SendFriendResponse(goonA, goonB, responseCode); //Do we need to send it to both? I think so so both get the updated friendlist but... idk.
|
uint8_t isAlreadyBestFriends = 0U;
|
||||||
|
// We need to convert this response code to one we can actually send back to the client.
|
||||||
|
switch (clientResponseCode) {
|
||||||
|
case AddFriendResponseCode::ACCEPTED:
|
||||||
|
serverResponseCode = AddFriendResponseType::ACCEPTED;
|
||||||
|
break;
|
||||||
|
case AddFriendResponseCode::BUSY:
|
||||||
|
serverResponseCode = AddFriendResponseType::BUSY;
|
||||||
|
break;
|
||||||
|
case AddFriendResponseCode::CANCELLED:
|
||||||
|
serverResponseCode = AddFriendResponseType::CANCELLED;
|
||||||
|
break;
|
||||||
|
case AddFriendResponseCode::REJECTED:
|
||||||
|
serverResponseCode = AddFriendResponseType::DECLINED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto stmt = Database::CreatePreppedStmt("INSERT INTO `friends`(`player_id`, `friend_id`, `best_friend`) VALUES (?,?,?)");
|
// Now that we have handled the base cases, we need to check the other cases.
|
||||||
stmt->setUInt64(1, goonA->playerID);
|
if (serverResponseCode == AddFriendResponseType::ACCEPTED) {
|
||||||
stmt->setUInt64(2, goonB->playerID);
|
for (auto friendData : requestor->friends) {
|
||||||
stmt->setInt(3, 0);
|
if (friendData.friendID == requestee->playerID) {
|
||||||
stmt->execute();
|
serverResponseCode = AddFriendResponseType::ALREADYFRIEND;
|
||||||
delete stmt;
|
if (friendData.isBestFriend) {
|
||||||
|
isAlreadyBestFriends = 1U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This message is NOT sent for best friends and is handled differently for those requests.
|
||||||
|
if (serverResponseCode == AddFriendResponseType::ACCEPTED) {
|
||||||
|
// Add the each player to the others friend list.
|
||||||
|
FriendData requestorData;
|
||||||
|
requestorData.zoneID = requestor->zoneID;
|
||||||
|
requestorData.friendID = requestor->playerID;
|
||||||
|
requestorData.friendName = requestor->playerName;
|
||||||
|
requestorData.isBestFriend = false;
|
||||||
|
requestorData.isFTP = false;
|
||||||
|
requestorData.isOnline = true;
|
||||||
|
requestee->friends.push_back(requestorData);
|
||||||
|
|
||||||
|
FriendData requesteeData;
|
||||||
|
requesteeData.zoneID = requestee->zoneID;
|
||||||
|
requesteeData.friendID = requestee->playerID;
|
||||||
|
requesteeData.friendName = requestee->playerName;
|
||||||
|
requesteeData.isBestFriend = false;
|
||||||
|
requesteeData.isFTP = false;
|
||||||
|
requesteeData.isOnline = true;
|
||||||
|
requestor->friends.push_back(requesteeData);
|
||||||
|
|
||||||
|
std::unique_ptr<sql::PreparedStatement> statement(Database::CreatePreppedStmt("INSERT IGNORE INTO `friends` (`player_id`, `friend_id`, `best_friend`) VALUES (?,?,?);"));
|
||||||
|
statement->setUInt(1, static_cast<uint32_t>(requestor->playerID));
|
||||||
|
statement->setUInt(2, static_cast<uint32_t>(requestee->playerID));
|
||||||
|
statement->setInt(3, 0);
|
||||||
|
statement->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverResponseCode != AddFriendResponseType::DECLINED) SendFriendResponse(requestor, requestee, serverResponseCode, isAlreadyBestFriends);
|
||||||
|
if (serverResponseCode != AddFriendResponseType::ALREADYFRIEND) SendFriendResponse(requestee, requestor, serverResponseCode, isAlreadyBestFriends);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
||||||
@ -145,50 +318,55 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
std::string friendName = PacketUtils::ReadString(16, packet, true);
|
std::string friendName = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
//we'll have to query the db here to find the user, since you can delete them while they're offline.
|
//we'll have to query the db here to find the user, since you can delete them while they're offline.
|
||||||
//First, we need to find their ID:
|
//First, we need to find their ID:
|
||||||
auto stmt = Database::CreatePreppedStmt("select id from charinfo where name=? limit 1;");
|
std::unique_ptr<sql::PreparedStatement> stmt(Database::CreatePreppedStmt("SELECT id FROM charinfo WHERE name=? LIMIT 1;"));
|
||||||
stmt->setString(1, friendName.c_str());
|
stmt->setString(1, friendName.c_str());
|
||||||
|
|
||||||
LWOOBJID friendID = 0;
|
LWOOBJID friendID = 0;
|
||||||
auto res = stmt->executeQuery();
|
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery());
|
||||||
while (res->next()) {
|
while (res->next()) {
|
||||||
friendID = res->getUInt64(1);
|
friendID = res->getUInt(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete res;
|
// Convert friendID to LWOOBJID
|
||||||
delete stmt;
|
GeneralUtils::SetBit(friendID, static_cast<size_t>(eObjectBits::OBJECT_BIT_PERSISTENT));
|
||||||
|
GeneralUtils::SetBit(friendID, static_cast<size_t>(eObjectBits::OBJECT_BIT_CHARACTER));
|
||||||
|
|
||||||
//Set our bits to convert to the BIG BOY objectID.
|
std::unique_ptr<sql::PreparedStatement> deletestmt(Database::CreatePreppedStmt("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;"));
|
||||||
friendID = GeneralUtils::ClearBit(friendID, OBJECT_BIT_CHARACTER);
|
deletestmt->setUInt(1, static_cast<uint32_t>(playerID));
|
||||||
friendID = GeneralUtils::ClearBit(friendID, OBJECT_BIT_PERSISTENT);
|
deletestmt->setUInt(2, static_cast<uint32_t>(friendID));
|
||||||
|
deletestmt->setUInt(3, static_cast<uint32_t>(friendID));
|
||||||
//YEET:
|
deletestmt->setUInt(4, static_cast<uint32_t>(playerID));
|
||||||
auto deletestmt = Database::CreatePreppedStmt("DELETE FROM `friends` WHERE player_id=? AND friend_id=? LIMIT 1");
|
|
||||||
deletestmt->setUInt64(1, playerID);
|
|
||||||
deletestmt->setUInt64(2, friendID);
|
|
||||||
deletestmt->execute();
|
deletestmt->execute();
|
||||||
delete deletestmt;
|
|
||||||
|
|
||||||
//because I'm lazy and they can be reversed:
|
|
||||||
{
|
|
||||||
auto deletestmt = Database::CreatePreppedStmt("DELETE FROM `friends` WHERE player_id=? AND friend_id=? LIMIT 1");
|
|
||||||
deletestmt->setUInt64(1, friendID);
|
|
||||||
deletestmt->setUInt64(2, playerID);
|
|
||||||
deletestmt->execute();
|
|
||||||
delete deletestmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended:
|
//Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended:
|
||||||
auto goonA = playerContainer.GetPlayerData(playerID);
|
auto goonA = playerContainer.GetPlayerData(playerID);
|
||||||
if (goonA) {
|
if (goonA) {
|
||||||
|
// Remove the friend from our list of friends
|
||||||
|
for (auto friendData = goonA->friends.begin(); friendData != goonA->friends.end(); friendData++) {
|
||||||
|
if ((*friendData).friendID == friendID) {
|
||||||
|
if ((*friendData).isBestFriend) --goonA->countOfBestFriends;
|
||||||
|
goonA->friends.erase(friendData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
SendRemoveFriend(goonA, friendName, true);
|
SendRemoveFriend(goonA, friendName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto goonB = playerContainer.GetPlayerData(friendID);
|
auto goonB = playerContainer.GetPlayerData(friendID);
|
||||||
if (!goonB) return;
|
if (!goonB) return;
|
||||||
|
// Do it again for other person
|
||||||
|
for (auto friendData = goonB->friends.begin(); friendData != goonB->friends.end(); friendData++) {
|
||||||
|
if ((*friendData).friendID == playerID) {
|
||||||
|
if ((*friendData).isBestFriend) --goonB->countOfBestFriends;
|
||||||
|
goonB->friends.erase(friendData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string goonAName = GeneralUtils::UTF16ToWTF8(playerContainer.GetName(playerID));
|
std::string goonAName = GeneralUtils::UTF16ToWTF8(playerContainer.GetName(playerID));
|
||||||
SendRemoveFriend(goonB, goonAName, true);
|
SendRemoveFriend(goonB, goonAName, true);
|
||||||
}
|
}
|
||||||
@ -206,7 +384,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
|
|||||||
|
|
||||||
if (playerContainer.GetIsMuted(sender)) return;
|
if (playerContainer.GetIsMuted(sender)) return;
|
||||||
|
|
||||||
const auto senderName = std::string(sender->playerName.C_String());
|
const auto senderName = std::string(sender->playerName.c_str());
|
||||||
|
|
||||||
inStream.SetReadOffset(0x14 * 8);
|
inStream.SetReadOffset(0x14 * 8);
|
||||||
|
|
||||||
@ -217,8 +395,6 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
|
|||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s\n", senderName.c_str(), channel, message.c_str());
|
Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s\n", senderName.c_str(), channel, message.c_str());
|
||||||
|
|
||||||
//PacketUtils::SavePacket("chat.bin", reinterpret_cast<char*>(packet->data), packet->length);
|
|
||||||
|
|
||||||
if (channel != 8) return;
|
if (channel != 8) return;
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = playerContainer.GetTeam(playerID);
|
||||||
@ -231,7 +407,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet)
|
|||||||
|
|
||||||
if (otherMember == nullptr) return;
|
if (otherMember == nullptr) return;
|
||||||
|
|
||||||
const auto otherName = std::string(otherMember->playerName.C_String());
|
const auto otherName = std::string(otherMember->playerName.c_str());
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
@ -267,8 +443,8 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
if (playerContainer.GetIsMuted(goonA)) return;
|
if (playerContainer.GetIsMuted(goonA)) return;
|
||||||
|
|
||||||
std::string goonAName = goonA->playerName.C_String();
|
std::string goonAName = goonA->playerName.c_str();
|
||||||
std::string goonBName = goonB->playerName.C_String();
|
std::string goonBName = goonB->playerName.c_str();
|
||||||
|
|
||||||
//To the sender:
|
//To the sender:
|
||||||
{
|
{
|
||||||
@ -454,8 +630,6 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet)
|
|||||||
|
|
||||||
playerContainer.RemoveMember(team, kickedId, false, true, false);
|
playerContainer.RemoveMember(team, kickedId, false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//PacketUtils::SavePacket("kick.bin", reinterpret_cast<char*>(packet->data), packet->length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamPromote(Packet* packet)
|
void ChatPacketHandler::HandleTeamPromote(Packet* packet)
|
||||||
@ -481,8 +655,6 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet)
|
|||||||
|
|
||||||
playerContainer.PromoteMember(team, promoted->playerID);
|
playerContainer.PromoteMember(team, promoted->playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
//PacketUtils::SavePacket("promote.bin", reinterpret_cast<char*>(packet->data), packet->length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
|
void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
|
||||||
@ -509,8 +681,6 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet)
|
|||||||
|
|
||||||
playerContainer.UpdateTeamsOnWorld(team, false);
|
playerContainer.UpdateTeamsOnWorld(team, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//PacketUtils::SavePacket("option.bin", reinterpret_cast<char*>(packet->data), packet->length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
|
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
|
||||||
@ -550,7 +720,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
|
|||||||
|
|
||||||
playerContainer.TeamStatusUpdate(team);
|
playerContainer.TeamStatusUpdate(team);
|
||||||
|
|
||||||
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.C_String()));
|
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.c_str()));
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs)
|
||||||
{
|
{
|
||||||
@ -560,7 +730,6 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet)
|
|||||||
|
|
||||||
const auto memberName = playerContainer.GetName(memberId);
|
const auto memberName = playerContainer.GetName(memberId);
|
||||||
|
|
||||||
//ChatPacketHandler::SendTeamAddPlayer(otherMember, false, false, false, data->playerID, leaderName, data->zoneID);
|
|
||||||
if (otherMember != nullptr)
|
if (otherMember != nullptr)
|
||||||
{
|
{
|
||||||
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
|
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
|
||||||
@ -581,7 +750,7 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
|
|||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_TEAM_INVITE);
|
PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_TEAM_INVITE);
|
||||||
|
|
||||||
PacketUtils::WritePacketWString(sender->playerName.C_String(), 33, &bitStream);
|
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
@ -745,7 +914,7 @@ void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType) {
|
void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType, uint8_t isBestFriend) {
|
||||||
/*chat notification is displayed if log in / out and friend is updated in friends list
|
/*chat notification is displayed if log in / out and friend is updated in friends list
|
||||||
[u8] - update type
|
[u8] - update type
|
||||||
Update types
|
Update types
|
||||||
@ -767,7 +936,7 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
|
|||||||
PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_UPDATE_FRIEND_NOTIFY);
|
PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_UPDATE_FRIEND_NOTIFY);
|
||||||
bitStream.Write<uint8_t>(notifyType);
|
bitStream.Write<uint8_t>(notifyType);
|
||||||
|
|
||||||
std::string playerName = playerData->playerName.C_String();
|
std::string playerName = playerData->playerName.c_str();
|
||||||
|
|
||||||
PacketUtils::WritePacketWString(playerName, 33, &bitStream);
|
PacketUtils::WritePacketWString(playerName, 33, &bitStream);
|
||||||
|
|
||||||
@ -783,19 +952,20 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
|
|||||||
bitStream.Write(playerData->zoneID.GetCloneID());
|
bitStream.Write(playerData->zoneID.GetCloneID());
|
||||||
}
|
}
|
||||||
|
|
||||||
bitStream.Write<uint8_t>(0); //isBFF
|
bitStream.Write<uint8_t>(isBestFriend); //isBFF
|
||||||
bitStream.Write<uint8_t>(0); //isFTP
|
bitStream.Write<uint8_t>(0); //isFTP
|
||||||
|
|
||||||
SystemAddress sysAddr = friendData->sysAddr;
|
SystemAddress sysAddr = friendData->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* sender, bool isBFFReq) {
|
void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* sender) {
|
||||||
if (!receiver || !sender) return;
|
if (!receiver || !sender) return;
|
||||||
|
|
||||||
//Make sure people aren't requesting people that they're already friends with:
|
//Make sure people aren't requesting people that they're already friends with:
|
||||||
for (auto fr : receiver->friends) {
|
for (auto fr : receiver->friends) {
|
||||||
if (fr.friendID == sender->playerID) {
|
if (fr.friendID == sender->playerID) {
|
||||||
|
SendFriendResponse(sender, receiver, AddFriendResponseType::ALREADYFRIEND, fr.isBestFriend);
|
||||||
return; //we have this player as a friend, yeet this function so it doesn't send another request.
|
return; //we have this player as a friend, yeet this function so it doesn't send another request.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -806,30 +976,34 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send
|
|||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_ADD_FRIEND_REQUEST);
|
PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_ADD_FRIEND_REQUEST);
|
||||||
PacketUtils::WritePacketWString(sender->playerName.C_String(), 33, &bitStream);
|
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
||||||
bitStream.Write<uint8_t>(0);
|
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sender, uint8_t responseCode) {
|
void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sender, AddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) {
|
||||||
if (!receiver || !sender) return;
|
if (!receiver || !sender) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
// Portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_ADD_FRIEND_RESPONSE);
|
PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_ADD_FRIEND_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(responseCode);
|
bitStream.Write(responseCode);
|
||||||
bitStream.Write<uint8_t>(1); //isOnline
|
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
||||||
PacketUtils::WritePacketWString(sender->playerName.C_String(), 33, &bitStream);
|
bitStream.Write<uint8_t>(responseCode != AddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
|
// Then write the player name
|
||||||
|
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
||||||
|
// Then if this is an acceptance code, write the following extra info.
|
||||||
|
if (responseCode == AddFriendResponseType::ACCEPTED) {
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
bitStream.Write(sender->zoneID);
|
bitStream.Write(sender->zoneID);
|
||||||
bitStream.Write<uint8_t>(0); //isBFF
|
bitStream.Write(isBestFriendRequest); //isBFF
|
||||||
bitStream.Write<uint8_t>(0); //isFTP
|
bitStream.Write<uint8_t>(0); //isFTP
|
||||||
|
}
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
|
|
||||||
struct PlayerData;
|
struct PlayerData;
|
||||||
|
enum class AddFriendResponseType : uint8_t;
|
||||||
|
|
||||||
namespace ChatPacketHandler {
|
namespace ChatPacketHandler {
|
||||||
void HandleFriendlistRequest(Packet* packet);
|
void HandleFriendlistRequest(Packet* packet);
|
||||||
@ -31,10 +32,9 @@ namespace ChatPacketHandler {
|
|||||||
void SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID);
|
void SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID);
|
||||||
|
|
||||||
//FriendData is the player we're SENDING this stuff to. Player is the friend that changed state.
|
//FriendData is the player we're SENDING this stuff to. Player is the friend that changed state.
|
||||||
void SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType);
|
void SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType, uint8_t isBestFriend);
|
||||||
|
|
||||||
void SendFriendRequest(PlayerData* receiver, PlayerData* sender, bool isBFFReq = false);
|
void SendFriendRequest(PlayerData* receiver, PlayerData* sender);
|
||||||
void SendFriendResponse(PlayerData* receiver, PlayerData* sender, uint8_t responseCode = 3);
|
void SendFriendResponse(PlayerData* receiver, PlayerData* sender, AddFriendResponseType responseCode, uint8_t isBestFriendsAlready = 0U, uint8_t isBestFriendRequest = 0U);
|
||||||
void SendRemoveFriend(PlayerData* receiver, std::string& personToRemove, bool isSuccessful);
|
void SendRemoveFriend(PlayerData* receiver, std::string& personToRemove, bool isSuccessful);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,17 +20,25 @@ PlayerContainer::~PlayerContainer() {
|
|||||||
void PlayerContainer::InsertPlayer(Packet* packet) {
|
void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM;
|
||||||
PlayerData* data = new PlayerData();
|
PlayerData* data = new PlayerData();
|
||||||
|
inStream.SetReadOffset(inStream.GetReadOffset() + 64);
|
||||||
inStream.Read(data->playerID);
|
inStream.Read(data->playerID);
|
||||||
inStream.Read(data->playerID);
|
|
||||||
inStream.Read(data->playerName);
|
uint32_t len;
|
||||||
|
inStream.Read<uint32_t>(len);
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
char character; inStream.Read<char>(character);
|
||||||
|
data->playerName += character;
|
||||||
|
}
|
||||||
|
|
||||||
inStream.Read(data->zoneID);
|
inStream.Read(data->zoneID);
|
||||||
inStream.Read(data->muteExpire);
|
inStream.Read(data->muteExpire);
|
||||||
data->sysAddr = packet->systemAddress;
|
data->sysAddr = packet->systemAddress;
|
||||||
|
|
||||||
mNames[data->playerID] = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.C_String()));
|
mNames[data->playerID] = GeneralUtils::ASCIIToUTF16(std::string(data->playerName.c_str()));
|
||||||
|
|
||||||
mPlayers.insert(std::make_pair(data->playerID, data));
|
mPlayers.insert(std::make_pair(data->playerID, data));
|
||||||
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i\n", data->playerName.C_String(), data->playerID, data->zoneID.GetMapID());
|
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i\n", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
|
||||||
|
|
||||||
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
||||||
|
|
||||||
@ -49,26 +57,22 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
//Before they get kicked, we need to also send a message to their friends saying that they disconnected.
|
//Before they get kicked, we need to also send a message to their friends saying that they disconnected.
|
||||||
auto player = this->GetPlayerData(playerID);
|
std::unique_ptr<PlayerData> player(this->GetPlayerData(playerID));
|
||||||
|
|
||||||
if (player == nullptr) {
|
if (player == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& fr : player->friends) {
|
for (auto& fr : player->friends) {
|
||||||
//if (!fr.isOnline) continue;
|
|
||||||
|
|
||||||
auto fd = this->GetPlayerData(fr.friendID);
|
auto fd = this->GetPlayerData(fr.friendID);
|
||||||
if (fd) ChatPacketHandler::SendFriendUpdate(fd, player, 0);
|
if (fd) ChatPacketHandler::SendFriendUpdate(fd, player.get(), 0, fr.isBestFriend);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* team = GetTeam(playerID);
|
auto* team = GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr)
|
if (team != nullptr)
|
||||||
{
|
{
|
||||||
//TeamStatusUpdate(team);
|
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.c_str()));
|
||||||
|
|
||||||
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(player->playerName.C_String()));
|
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs)
|
||||||
{
|
{
|
||||||
@ -77,7 +81,6 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
if (otherMember == nullptr) continue;
|
if (otherMember == nullptr) continue;
|
||||||
|
|
||||||
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, {0, 0, 0});
|
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, {0, 0, 0});
|
||||||
//ChatPacketHandler::SendTeamRemovePlayer(otherMember, false, false, true, false, team->leaderID, player->playerID, memberName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,17 +240,11 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID)
|
|||||||
|
|
||||||
if (leader == nullptr || member == nullptr) return;
|
if (leader == nullptr || member == nullptr) return;
|
||||||
|
|
||||||
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.C_String()));
|
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str()));
|
||||||
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.C_String()));
|
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(member->playerName.c_str()));
|
||||||
|
|
||||||
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName);
|
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName);
|
||||||
|
|
||||||
/*
|
|
||||||
ChatPacketHandler::SendTeamAddPlayer(member, false, false, false, leader->playerID, leaderName, leader->zoneID);
|
|
||||||
|
|
||||||
Game::logger->Log("PlayerContainer", "Team invite successfully accepted, leader: %s, member: %s\n", leader->playerName.C_String(), member->playerName.C_String());
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!team->local)
|
if (!team->local)
|
||||||
{
|
{
|
||||||
ChatPacketHandler::SendTeamSetLeader(member, leader->playerID);
|
ChatPacketHandler::SendTeamSetLeader(member, leader->playerID);
|
||||||
@ -348,7 +345,7 @@ void PlayerContainer::DisbandTeam(TeamData* team)
|
|||||||
|
|
||||||
if (otherMember == nullptr) continue;
|
if (otherMember == nullptr) continue;
|
||||||
|
|
||||||
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(otherMember->playerName.C_String()));
|
const auto memberName = GeneralUtils::ASCIIToUTF16(std::string(otherMember->playerName.c_str()));
|
||||||
|
|
||||||
ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY);
|
ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY);
|
||||||
ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember->playerID, memberName);
|
ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember->playerID, memberName);
|
||||||
@ -371,7 +368,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team)
|
|||||||
|
|
||||||
if (leader == nullptr) return;
|
if (leader == nullptr) return;
|
||||||
|
|
||||||
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.C_String()));
|
const auto leaderName = GeneralUtils::ASCIIToUTF16(std::string(leader->playerName.c_str()));
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs)
|
for (const auto memberId : team->memberIDs)
|
||||||
{
|
{
|
||||||
@ -383,10 +380,6 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team)
|
|||||||
{
|
{
|
||||||
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName);
|
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
//ChatPacketHandler::SendTeamStatus(otherMember, LWOOBJID_EMPTY, LWOZONEID(0, 0, 0), 1, 0, u"");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTeamsOnWorld(team, false);
|
UpdateTeamsOnWorld(team, false);
|
||||||
|
@ -9,11 +9,12 @@
|
|||||||
|
|
||||||
struct PlayerData {
|
struct PlayerData {
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
RakNet::RakString playerName;
|
std::string playerName;
|
||||||
SystemAddress sysAddr;
|
SystemAddress sysAddr;
|
||||||
LWOZONEID zoneID;
|
LWOZONEID zoneID;
|
||||||
std::vector<FriendData> friends;
|
std::vector<FriendData> friends;
|
||||||
time_t muteExpire;
|
time_t muteExpire;
|
||||||
|
uint8_t countOfBestFriends = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TeamData {
|
struct TeamData {
|
||||||
@ -45,7 +46,7 @@ public:
|
|||||||
PlayerData* GetPlayerData(const std::string& playerName) {
|
PlayerData* GetPlayerData(const std::string& playerName) {
|
||||||
for (auto player : mPlayers) {
|
for (auto player : mPlayers) {
|
||||||
if (player.second) {
|
if (player.second) {
|
||||||
std::string pn = player.second->playerName.C_String();
|
std::string pn = player.second->playerName.c_str();
|
||||||
if (pn == playerName) return player.second;
|
if (pn == playerName) return player.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
dCommon/AddFriendResponseCode.h
Normal file
15
dCommon/AddFriendResponseCode.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __ADDFRIENDRESPONSECODE__H__
|
||||||
|
#define __ADDFRIENDRESPONSECODE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum class AddFriendResponseCode : uint8_t {
|
||||||
|
ACCEPTED = 0,
|
||||||
|
REJECTED,
|
||||||
|
BUSY,
|
||||||
|
CANCELLED
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__ADDFRIENDRESPONSECODE__H__
|
24
dCommon/AddFriendResponseType.h
Normal file
24
dCommon/AddFriendResponseType.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __ADDFRIENDRESPONSETYPE__H__
|
||||||
|
#define __ADDFRIENDRESPONSETYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum class AddFriendResponseType : uint8_t {
|
||||||
|
ACCEPTED = 0,
|
||||||
|
ALREADYFRIEND,
|
||||||
|
INVALIDCHARACTER,
|
||||||
|
GENERALERROR,
|
||||||
|
YOURFRIENDSLISTFULL,
|
||||||
|
THEIRFRIENDLISTFULL,
|
||||||
|
DECLINED,
|
||||||
|
BUSY,
|
||||||
|
NOTONLINE,
|
||||||
|
WAITINGAPPROVAL,
|
||||||
|
MYTHRAN,
|
||||||
|
CANCELLED,
|
||||||
|
FRIENDISFREETRIAL
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__ADDFRIENDRESPONSETYPE__H__
|
26
dCommon/CMakeLists.txt
Normal file
26
dCommon/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
set(DCOMMON_SOURCES "AMFFormat.cpp"
|
||||||
|
"AMFFormat_BitStream.cpp"
|
||||||
|
"BinaryIO.cpp"
|
||||||
|
"dConfig.cpp"
|
||||||
|
"Diagnostics.cpp"
|
||||||
|
"dLogger.cpp"
|
||||||
|
"GeneralUtils.cpp"
|
||||||
|
"LDFFormat.cpp"
|
||||||
|
"MD5.cpp"
|
||||||
|
"Metrics.cpp"
|
||||||
|
"NiPoint3.cpp"
|
||||||
|
"NiQuaternion.cpp"
|
||||||
|
"SHA512.cpp"
|
||||||
|
"Type.cpp"
|
||||||
|
"ZCompression.cpp")
|
||||||
|
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/dCommon/)
|
||||||
|
|
||||||
|
add_library(dCommon STATIC ${DCOMMON_SOURCES})
|
||||||
|
|
||||||
|
target_link_libraries(dCommon libbcrypt)
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
target_link_libraries(dCommon ZLIB::ZLIB)
|
||||||
|
endif()
|
@ -188,3 +188,53 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream *inStream) {
|
|||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
std::vector<std::string> GeneralUtils::GetFileNamesFromFolder(const std::string& folder)
|
||||||
|
{
|
||||||
|
std::vector<std::string> names;
|
||||||
|
std::string search_path = folder + "/*.*";
|
||||||
|
WIN32_FIND_DATA fd;
|
||||||
|
HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd);
|
||||||
|
if (hFind != INVALID_HANDLE_VALUE) {
|
||||||
|
do {
|
||||||
|
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
|
names.push_back(fd.cFileName);
|
||||||
|
}
|
||||||
|
} while (::FindNextFile(hFind, &fd));
|
||||||
|
::FindClose(hFind);
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
std::vector<std::string> GeneralUtils::GetFileNamesFromFolder(const std::string& folder) {
|
||||||
|
std::vector<std::string> names;
|
||||||
|
struct dirent* entry;
|
||||||
|
DIR* dir = opendir(folder.c_str());
|
||||||
|
if (dir == NULL) {
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
std::string value(entry->d_name, strlen(entry->d_name));
|
||||||
|
if (value == "." || value == "..") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
names.push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
#endif
|
@ -128,6 +128,8 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
std::vector<std::string> SplitString(const std::string& str, char delimiter);
|
std::vector<std::string> SplitString(const std::string& str, char delimiter);
|
||||||
|
|
||||||
|
std::vector<std::string> GetFileNamesFromFolder(const std::string& folder);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Parse(const char* value);
|
T Parse(const char* value);
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "ZCompression.h"
|
#include "ZCompression.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
namespace ZCompression
|
namespace ZCompression
|
||||||
@ -71,3 +73,5 @@ namespace ZCompression
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "dPlatforms.h"
|
||||||
|
|
||||||
|
#ifndef DARKFLAME_PLATFORM_WIN32
|
||||||
|
|
||||||
namespace ZCompression
|
namespace ZCompression
|
||||||
{
|
{
|
||||||
int32_t GetMaxCompressedLength(int32_t nLenSrc);
|
int32_t GetMaxCompressedLength(int32_t nLenSrc);
|
||||||
@ -10,3 +14,5 @@ namespace ZCompression
|
|||||||
|
|
||||||
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr);
|
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -440,33 +440,6 @@ enum eInventoryType : uint32_t {
|
|||||||
INVALID // made up, for internal use!!!
|
INVALID // made up, for internal use!!!
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eItemType : int32_t {
|
|
||||||
ITEM_TYPE_UNKNOWN = -1, //!< An unknown item type
|
|
||||||
ITEM_TYPE_BRICK = 1, //!< A brick
|
|
||||||
ITEM_TYPE_HAT = 2, //!< A hat / head item
|
|
||||||
ITEM_TYPE_HAIR = 3, //!< A hair item
|
|
||||||
ITEM_TYPE_NECK = 4, //!< A neck item
|
|
||||||
ITEM_TYPE_LEFT_HAND = 5, //!< A left handed item
|
|
||||||
ITEM_TYPE_RIGHT_HAND = 6, //!< A right handed item
|
|
||||||
ITEM_TYPE_LEGS = 7, //!< A pants item
|
|
||||||
ITEM_TYPE_LEFT_TRINKET = 8, //!< A left handled trinket item
|
|
||||||
ITEM_TYPE_RIGHT_TRINKET = 9, //!< A right handed trinket item
|
|
||||||
ITEM_TYPE_BEHAVIOR = 10, //!< A behavior
|
|
||||||
ITEM_TYPE_PROPERTY = 11, //!< A property
|
|
||||||
ITEM_TYPE_MODEL = 12, //!< A model
|
|
||||||
ITEM_TYPE_COLLECTIBLE = 13, //!< A collectible item
|
|
||||||
ITEM_TYPE_CONSUMABLE = 14, //!< A consumable item
|
|
||||||
ITEM_TYPE_CHEST = 15, //!< A chest item
|
|
||||||
ITEM_TYPE_EGG = 16, //!< An egg
|
|
||||||
ITEM_TYPE_PET_FOOD = 17, //!< A pet food item
|
|
||||||
ITEM_TYPE_QUEST_OBJECT = 18, //!< A quest item
|
|
||||||
ITEM_TYPE_PET_INVENTORY_ITEM = 19, //!< A pet inventory item
|
|
||||||
ITEM_TYPE_PACKAGE = 20, //!< A package
|
|
||||||
ITEM_TYPE_LOOT_MODEL = 21, //!< A loot model
|
|
||||||
ITEM_TYPE_VEHICLE = 22, //!< A vehicle
|
|
||||||
ITEM_TYPE_CURRENCY = 23 //!< Currency
|
|
||||||
};
|
|
||||||
|
|
||||||
enum eRebuildState : uint32_t {
|
enum eRebuildState : uint32_t {
|
||||||
REBUILD_OPEN,
|
REBUILD_OPEN,
|
||||||
REBUILD_COMPLETED = 2,
|
REBUILD_COMPLETED = 2,
|
||||||
|
29
dCommon/dPlatforms.h
Normal file
29
dCommon/dPlatforms.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define DARKFLAME_PLATFORM_WIN32
|
||||||
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
|
#include <TargetConditionals.h>
|
||||||
|
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||||
|
#define DARKFLAME_PLATFORM_IOS
|
||||||
|
#elif TARGET_OS_MAC
|
||||||
|
#define DARKFLAME_PLATFORM_MACOS
|
||||||
|
#else
|
||||||
|
#error unknown Apple operating system
|
||||||
|
#endif
|
||||||
|
#elif defined(__unix__)
|
||||||
|
#define DARKFLAME_PLATFORM_UNIX
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
#define DARKFLAME_PLATFORM_ANDROID
|
||||||
|
#elif defined(__linux__)
|
||||||
|
#define DARKFLAME_PLATFORM_LINUX
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
|
#define DARKFLAME_PLATFORM_FREEBSD
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
#define DARKFLAME_PLATFORM_CYGWIN
|
||||||
|
#else
|
||||||
|
#error unknown unix operating system
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#error unknown operating system
|
||||||
|
#endif
|
36
dCommon/eItemType.h
Normal file
36
dCommon/eItemType.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __EITEMTYPE__H__
|
||||||
|
#define __EITEMTYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum class eItemType : int32_t {
|
||||||
|
ITEM_TYPE_UNKNOWN = -1, //!< An unknown item type
|
||||||
|
ITEM_TYPE_BRICK = 1, //!< A brick
|
||||||
|
ITEM_TYPE_HAT = 2, //!< A hat / head item
|
||||||
|
ITEM_TYPE_HAIR = 3, //!< A hair item
|
||||||
|
ITEM_TYPE_NECK = 4, //!< A neck item
|
||||||
|
ITEM_TYPE_LEFT_HAND = 5, //!< A left handed item
|
||||||
|
ITEM_TYPE_RIGHT_HAND = 6, //!< A right handed item
|
||||||
|
ITEM_TYPE_LEGS = 7, //!< A pants item
|
||||||
|
ITEM_TYPE_LEFT_TRINKET = 8, //!< A left handled trinket item
|
||||||
|
ITEM_TYPE_RIGHT_TRINKET = 9, //!< A right handed trinket item
|
||||||
|
ITEM_TYPE_BEHAVIOR = 10, //!< A behavior
|
||||||
|
ITEM_TYPE_PROPERTY = 11, //!< A property
|
||||||
|
ITEM_TYPE_MODEL = 12, //!< A model
|
||||||
|
ITEM_TYPE_COLLECTIBLE = 13, //!< A collectible item
|
||||||
|
ITEM_TYPE_CONSUMABLE = 14, //!< A consumable item
|
||||||
|
ITEM_TYPE_CHEST = 15, //!< A chest item
|
||||||
|
ITEM_TYPE_EGG = 16, //!< An egg
|
||||||
|
ITEM_TYPE_PET_FOOD = 17, //!< A pet food item
|
||||||
|
ITEM_TYPE_QUEST_OBJECT = 18, //!< A quest item
|
||||||
|
ITEM_TYPE_PET_INVENTORY_ITEM = 19, //!< A pet inventory item
|
||||||
|
ITEM_TYPE_PACKAGE = 20, //!< A package
|
||||||
|
ITEM_TYPE_LOOT_MODEL = 21, //!< A loot model
|
||||||
|
ITEM_TYPE_VEHICLE = 22, //!< A vehicle
|
||||||
|
ITEM_TYPE_CURRENCY = 23, //!< Currency
|
||||||
|
ITEM_TYPE_MOUNT = 24 //!< A Mount
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__EITEMTYPE__H__
|
13
dDatabase/CMakeLists.txt
Normal file
13
dDatabase/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
set(DDATABASE_SOURCES "CDClientDatabase.cpp"
|
||||||
|
"CDClientManager.cpp"
|
||||||
|
"Database.cpp"
|
||||||
|
"MigrationRunner.cpp")
|
||||||
|
|
||||||
|
add_subdirectory(Tables)
|
||||||
|
|
||||||
|
foreach(file ${DDATABASE_TABLES_SOURCES})
|
||||||
|
set(DDATABASE_SOURCES ${DDATABASE_SOURCES} "Tables/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_library(dDatabase STATIC ${DDATABASE_SOURCES})
|
||||||
|
target_link_libraries(dDatabase sqlite3 mariadbConnCpp)
|
@ -8,6 +8,8 @@ using namespace std;
|
|||||||
|
|
||||||
sql::Driver * Database::driver;
|
sql::Driver * Database::driver;
|
||||||
sql::Connection * Database::con;
|
sql::Connection * Database::con;
|
||||||
|
sql::Properties Database::props;
|
||||||
|
std::string Database::database;
|
||||||
|
|
||||||
void Database::Connect(const string& host, const string& database, const string& username, const string& password) {
|
void Database::Connect(const string& host, const string& database, const string& username, const string& password) {
|
||||||
|
|
||||||
@ -25,14 +27,26 @@ void Database::Connect(const string& host, const string& database, const string&
|
|||||||
properties["user"] = szUsername;
|
properties["user"] = szUsername;
|
||||||
properties["password"] = szPassword;
|
properties["password"] = szPassword;
|
||||||
properties["autoReconnect"] = "true";
|
properties["autoReconnect"] = "true";
|
||||||
con = driver->connect(properties);
|
|
||||||
con->setSchema(szDatabase);
|
|
||||||
} //Connect
|
|
||||||
|
|
||||||
void Database::Destroy(std::string source) {
|
Database::props = properties;
|
||||||
|
Database::database = database;
|
||||||
|
|
||||||
|
Database::Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::Connect() {
|
||||||
|
con = driver->connect(Database::props);
|
||||||
|
con->setSchema(Database::database);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::Destroy(std::string source, bool log) {
|
||||||
if (!con) return;
|
if (!con) return;
|
||||||
|
|
||||||
|
if (log) {
|
||||||
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!\n", source.c_str());
|
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!\n", source.c_str());
|
||||||
else Game::logger->Log("Database", "Destroying MySQL connection!\n");
|
else Game::logger->Log("Database", "Destroying MySQL connection!\n");
|
||||||
|
}
|
||||||
|
|
||||||
con->close();
|
con->close();
|
||||||
delete con;
|
delete con;
|
||||||
} //Destroy
|
} //Destroy
|
||||||
@ -48,13 +62,7 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
|
|||||||
sql::SQLString str(test, size);
|
sql::SQLString str(test, size);
|
||||||
|
|
||||||
if (!con) {
|
if (!con) {
|
||||||
//Connect to the MySQL Database
|
Connect();
|
||||||
std::string mysql_host = Game::config->GetValue("mysql_host");
|
|
||||||
std::string mysql_database = Game::config->GetValue("mysql_database");
|
|
||||||
std::string mysql_username = Game::config->GetValue("mysql_username");
|
|
||||||
std::string mysql_password = Game::config->GetValue("mysql_password");
|
|
||||||
|
|
||||||
Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
|
||||||
Game::logger->Log("Database", "Trying to reconnect to MySQL\n");
|
Game::logger->Log("Database", "Trying to reconnect to MySQL\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,13 +72,7 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
|
|||||||
|
|
||||||
con = nullptr;
|
con = nullptr;
|
||||||
|
|
||||||
//Connect to the MySQL Database
|
Connect();
|
||||||
std::string mysql_host = Game::config->GetValue("mysql_host");
|
|
||||||
std::string mysql_database = Game::config->GetValue("mysql_database");
|
|
||||||
std::string mysql_username = Game::config->GetValue("mysql_username");
|
|
||||||
std::string mysql_password = Game::config->GetValue("mysql_password");
|
|
||||||
|
|
||||||
Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
|
||||||
Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection\n");
|
Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,3 +81,6 @@ sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
|
|||||||
return stmt;
|
return stmt;
|
||||||
} //CreatePreppedStmt
|
} //CreatePreppedStmt
|
||||||
|
|
||||||
|
void Database::Commit() {
|
||||||
|
Database::con->commit();
|
||||||
|
}
|
@ -13,10 +13,17 @@ class Database {
|
|||||||
private:
|
private:
|
||||||
static sql::Driver *driver;
|
static sql::Driver *driver;
|
||||||
static sql::Connection *con;
|
static sql::Connection *con;
|
||||||
|
static sql::Properties props;
|
||||||
|
static std::string database;
|
||||||
public:
|
public:
|
||||||
static void Connect(const std::string& host, const std::string& database, const std::string& username, const std::string& password);
|
static void Connect(const std::string& host, const std::string& database, const std::string& username, const std::string& password);
|
||||||
static void Destroy(std::string source="");
|
static void Connect();
|
||||||
|
static void Destroy(std::string source = "", bool log = true);
|
||||||
|
|
||||||
static sql::Statement* CreateStmt();
|
static sql::Statement* CreateStmt();
|
||||||
static sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
static sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
||||||
|
static void Commit();
|
||||||
|
|
||||||
|
static std::string GetDatabase() { return database; }
|
||||||
|
static sql::Properties GetProperties() { return props; }
|
||||||
};
|
};
|
||||||
|
78
dDatabase/MigrationRunner.cpp
Normal file
78
dDatabase/MigrationRunner.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "MigrationRunner.h"
|
||||||
|
|
||||||
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
void MigrationRunner::RunMigrations() {
|
||||||
|
auto stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());");
|
||||||
|
stmt->executeQuery();
|
||||||
|
delete stmt;
|
||||||
|
|
||||||
|
sql::SQLString finalSQL = "";
|
||||||
|
Migration checkMigration{};
|
||||||
|
|
||||||
|
for (const auto& entry : GeneralUtils::GetFileNamesFromFolder("./migrations/")) {
|
||||||
|
auto migration = LoadMigration(entry);
|
||||||
|
|
||||||
|
if (migration.data.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMigration = migration;
|
||||||
|
|
||||||
|
stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
||||||
|
stmt->setString(1, migration.name);
|
||||||
|
auto res = stmt->executeQuery();
|
||||||
|
bool doExit = res->next();
|
||||||
|
delete res;
|
||||||
|
delete stmt;
|
||||||
|
if (doExit) continue;
|
||||||
|
|
||||||
|
Game::logger->Log("MigrationRunner", "Running migration: " + migration.name + "\n");
|
||||||
|
|
||||||
|
finalSQL.append(migration.data);
|
||||||
|
finalSQL.append('\n');
|
||||||
|
|
||||||
|
stmt = Database::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
||||||
|
stmt->setString(1, entry);
|
||||||
|
stmt->execute();
|
||||||
|
delete stmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!finalSQL.empty()) {
|
||||||
|
try {
|
||||||
|
auto simpleStatement = Database::CreateStmt();
|
||||||
|
simpleStatement->execute(finalSQL);
|
||||||
|
delete simpleStatement;
|
||||||
|
}
|
||||||
|
catch (sql::SQLException e) {
|
||||||
|
Game::logger->Log("MigrationRunner", std::string("Encountered error running migration: ") + e.what() + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Migration MigrationRunner::LoadMigration(std::string path) {
|
||||||
|
Migration migration{};
|
||||||
|
std::ifstream file("./migrations/" + path);
|
||||||
|
|
||||||
|
if (file.is_open()) {
|
||||||
|
std::hash<std::string> hash;
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::string total = "";
|
||||||
|
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
total += line;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
migration.name = path;
|
||||||
|
migration.data = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
return migration;
|
||||||
|
}
|
19
dDatabase/MigrationRunner.h
Normal file
19
dDatabase/MigrationRunner.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Database.h"
|
||||||
|
|
||||||
|
#include "dCommonVars.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dCommonVars.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
|
||||||
|
struct Migration {
|
||||||
|
std::string data;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MigrationRunner {
|
||||||
|
public:
|
||||||
|
static void RunMigrations();
|
||||||
|
static Migration LoadMigration(std::string path);
|
||||||
|
};
|
@ -24,7 +24,13 @@ CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) {
|
|||||||
entry.behaviorID = tableData.getIntField(0, -1);
|
entry.behaviorID = tableData.getIntField(0, -1);
|
||||||
entry.templateID = tableData.getIntField(1, -1);
|
entry.templateID = tableData.getIntField(1, -1);
|
||||||
entry.effectID = tableData.getIntField(2, -1);
|
entry.effectID = tableData.getIntField(2, -1);
|
||||||
entry.effectHandle = tableData.getStringField(3, "");
|
auto candidateToAdd = tableData.getStringField(3, "");
|
||||||
|
auto parameter = m_EffectHandles.find(candidateToAdd);
|
||||||
|
if (parameter != m_EffectHandles.end()) {
|
||||||
|
entry.effectHandle = parameter;
|
||||||
|
} else {
|
||||||
|
entry.effectHandle = m_EffectHandles.insert(candidateToAdd).first;
|
||||||
|
}
|
||||||
|
|
||||||
this->entries.push_back(entry);
|
this->entries.push_back(entry);
|
||||||
this->entriesMappedByBehaviorID.insert(std::make_pair(entry.behaviorID, entry));
|
this->entriesMappedByBehaviorID.insert(std::make_pair(entry.behaviorID, entry));
|
||||||
@ -62,7 +68,8 @@ const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behav
|
|||||||
if (entry == this->entriesMappedByBehaviorID.end()) {
|
if (entry == this->entriesMappedByBehaviorID.end()) {
|
||||||
CDBehaviorTemplate entryToReturn;
|
CDBehaviorTemplate entryToReturn;
|
||||||
entryToReturn.behaviorID = 0;
|
entryToReturn.behaviorID = 0;
|
||||||
entryToReturn.effectHandle = "";
|
entryToReturn.effectHandle = m_EffectHandles.end();
|
||||||
|
entryToReturn.effectID = 0;
|
||||||
return entryToReturn;
|
return entryToReturn;
|
||||||
} else {
|
} else {
|
||||||
return entry->second;
|
return entry->second;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\file CDBehaviorTemplateTable.hpp
|
\file CDBehaviorTemplateTable.hpp
|
||||||
@ -14,7 +15,7 @@ struct CDBehaviorTemplate {
|
|||||||
unsigned int behaviorID; //!< The Behavior ID
|
unsigned int behaviorID; //!< The Behavior ID
|
||||||
unsigned int templateID; //!< The Template ID (LOT)
|
unsigned int templateID; //!< The Template ID (LOT)
|
||||||
unsigned int effectID; //!< The Effect ID attached
|
unsigned int effectID; //!< The Effect ID attached
|
||||||
std::string effectHandle; //!< The effect handle
|
std::unordered_set<std::string>::iterator effectHandle; //!< The effect handle
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ class CDBehaviorTemplateTable : public CDTable {
|
|||||||
private:
|
private:
|
||||||
std::vector<CDBehaviorTemplate> entries;
|
std::vector<CDBehaviorTemplate> entries;
|
||||||
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
|
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
|
||||||
|
std::unordered_set<std::string> m_EffectHandles;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
|
38
dDatabase/Tables/CMakeLists.txt
Normal file
38
dDatabase/Tables/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
set(DDATABASE_TABLES_SOURCES "CDActivitiesTable.cpp"
|
||||||
|
"CDActivityRewardsTable.cpp"
|
||||||
|
"CDAnimationsTable.cpp"
|
||||||
|
"CDBehaviorParameterTable.cpp"
|
||||||
|
"CDBehaviorTemplateTable.cpp"
|
||||||
|
"CDBrickIDTableTable.cpp"
|
||||||
|
"CDComponentsRegistryTable.cpp"
|
||||||
|
"CDCurrencyTableTable.cpp"
|
||||||
|
"CDDestructibleComponentTable.cpp"
|
||||||
|
"CDEmoteTable.cpp"
|
||||||
|
"CDFeatureGatingTable.cpp"
|
||||||
|
"CDInventoryComponentTable.cpp"
|
||||||
|
"CDItemComponentTable.cpp"
|
||||||
|
"CDItemSetSkillsTable.cpp"
|
||||||
|
"CDItemSetsTable.cpp"
|
||||||
|
"CDLevelProgressionLookupTable.cpp"
|
||||||
|
"CDLootMatrixTable.cpp"
|
||||||
|
"CDLootTableTable.cpp"
|
||||||
|
"CDMissionEmailTable.cpp"
|
||||||
|
"CDMissionNPCComponentTable.cpp"
|
||||||
|
"CDMissionsTable.cpp"
|
||||||
|
"CDMissionTasksTable.cpp"
|
||||||
|
"CDMovementAIComponentTable.cpp"
|
||||||
|
"CDObjectSkillsTable.cpp"
|
||||||
|
"CDObjectsTable.cpp"
|
||||||
|
"CDPackageComponentTable.cpp"
|
||||||
|
"CDPhysicsComponentTable.cpp"
|
||||||
|
"CDPropertyEntranceComponentTable.cpp"
|
||||||
|
"CDPropertyTemplateTable.cpp"
|
||||||
|
"CDProximityMonitorComponentTable.cpp"
|
||||||
|
"CDRailActivatorComponent.cpp"
|
||||||
|
"CDRarityTableTable.cpp"
|
||||||
|
"CDRebuildComponentTable.cpp"
|
||||||
|
"CDRewardsTable.cpp"
|
||||||
|
"CDScriptComponentTable.cpp"
|
||||||
|
"CDSkillBehaviorTable.cpp"
|
||||||
|
"CDVendorComponentTable.cpp"
|
||||||
|
"CDZoneTableTable.cpp" PARENT_SCOPE)
|
59
dGame/CMakeLists.txt
Normal file
59
dGame/CMakeLists.txt
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
set(DGAME_SOURCES "Character.cpp"
|
||||||
|
"Entity.cpp"
|
||||||
|
"EntityManager.cpp"
|
||||||
|
"LeaderboardManager.cpp"
|
||||||
|
"Player.cpp"
|
||||||
|
"TeamManager.cpp"
|
||||||
|
"TradingManager.cpp"
|
||||||
|
"User.cpp"
|
||||||
|
"UserManager.cpp")
|
||||||
|
|
||||||
|
add_subdirectory(dBehaviors)
|
||||||
|
|
||||||
|
foreach(file ${DGAME_DBEHAVIORS_SOURCES})
|
||||||
|
set(DGAME_SOURCES ${DGAME_SOURCES} "dBehaviors/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_subdirectory(dComponents)
|
||||||
|
|
||||||
|
foreach(file ${DGAME_DCOMPONENTS_SOURCES})
|
||||||
|
set(DGAME_SOURCES ${DGAME_SOURCES} "dComponents/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_subdirectory(dEntity)
|
||||||
|
|
||||||
|
foreach(file ${DGAME_DENTITY_SOURCES})
|
||||||
|
set(DGAME_SOURCES ${DGAME_SOURCES} "dEntity/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_subdirectory(dGameMessages)
|
||||||
|
|
||||||
|
foreach(file ${DGAME_DGAMEMESSAGES_SOURCES})
|
||||||
|
set(DGAME_SOURCES ${DGAME_SOURCES} "dGameMessages/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_subdirectory(dInventory)
|
||||||
|
|
||||||
|
foreach(file ${DGAME_DINVENTORY_SOURCES})
|
||||||
|
set(DGAME_SOURCES ${DGAME_SOURCES} "dInventory/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_subdirectory(dMission)
|
||||||
|
|
||||||
|
foreach(file ${DGAME_DMISSION_SOURCES})
|
||||||
|
set(DGAME_SOURCES ${DGAME_SOURCES} "dMission/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_subdirectory(dUtilities)
|
||||||
|
|
||||||
|
foreach(file ${DGAME_DUTILITIES_SOURCES})
|
||||||
|
set(DGAME_SOURCES ${DGAME_SOURCES} "dUtilities/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(file ${DSCRIPT_SOURCES})
|
||||||
|
set(DGAME_SOURCES ${DGAME_SOURCES} "${PROJECT_SOURCE_DIR}/dScripts/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_library(dGame STATIC ${DGAME_SOURCES})
|
||||||
|
|
||||||
|
target_link_libraries(dGame dDatabase)
|
@ -109,6 +109,11 @@ Entity::~Entity() {
|
|||||||
|
|
||||||
m_Components.erase(pair.first);
|
m_Components.erase(pair.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto child : m_ChildEntities) {
|
||||||
|
if (child) child->RemoveParent();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_ParentEntity) {
|
if (m_ParentEntity) {
|
||||||
m_ParentEntity->RemoveChild(this);
|
m_ParentEntity->RemoveChild(this);
|
||||||
}
|
}
|
||||||
@ -1201,17 +1206,21 @@ void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Entity::Update(const float deltaTime) {
|
void Entity::Update(const float deltaTime) {
|
||||||
for (int i = 0; i < m_Timers.size(); i++) {
|
uint32_t timerPosition;
|
||||||
m_Timers[i]->Update(deltaTime);
|
timerPosition = 0;
|
||||||
if (m_Timers[i]->GetTime() <= 0) {
|
while (timerPosition < m_Timers.size()) {
|
||||||
const auto timerName = m_Timers[i]->GetName();
|
m_Timers[timerPosition]->Update(deltaTime);
|
||||||
|
if (m_Timers[timerPosition]->GetTime() <= 0) {
|
||||||
|
const auto timerName = m_Timers[timerPosition]->GetName();
|
||||||
|
|
||||||
delete m_Timers[i];
|
delete m_Timers[timerPosition];
|
||||||
m_Timers.erase(m_Timers.begin() + i);
|
m_Timers.erase(m_Timers.begin() + timerPosition);
|
||||||
|
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
||||||
script->OnTimerDone(this, timerName);
|
script->OnTimerDone(this, timerName);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
timerPosition++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1224,6 +1233,14 @@ void Entity::Update(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add pending timers to the list of timers so they start next tick.
|
||||||
|
if (m_PendingTimers.size() > 0) {
|
||||||
|
for (auto namedTimer : m_PendingTimers) {
|
||||||
|
m_Timers.push_back(namedTimer);
|
||||||
|
}
|
||||||
|
m_PendingTimers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (IsSleeping())
|
if (IsSleeping())
|
||||||
{
|
{
|
||||||
Sleep();
|
Sleep();
|
||||||
@ -1650,18 +1667,24 @@ void Entity::AddChild(Entity* child) {
|
|||||||
|
|
||||||
void Entity::RemoveChild(Entity* child) {
|
void Entity::RemoveChild(Entity* child) {
|
||||||
if (!child) return;
|
if (!child) return;
|
||||||
for (auto entity = m_ChildEntities.begin(); entity != m_ChildEntities.end(); entity++) {
|
uint32_t entityPosition = 0;
|
||||||
if (*entity && (*entity)->GetObjectID() == child->GetObjectID()) {
|
while (entityPosition < m_ChildEntities.size()) {
|
||||||
|
if (!m_ChildEntities[entityPosition] || (m_ChildEntities[entityPosition])->GetObjectID() == child->GetObjectID()) {
|
||||||
m_IsParentChildDirty = true;
|
m_IsParentChildDirty = true;
|
||||||
m_ChildEntities.erase(entity);
|
m_ChildEntities.erase(m_ChildEntities.begin() + entityPosition);
|
||||||
return;
|
} else {
|
||||||
|
entityPosition++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Entity::RemoveParent() {
|
||||||
|
this->m_ParentEntity = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Entity::AddTimer(std::string name, float time) {
|
void Entity::AddTimer(std::string name, float time) {
|
||||||
EntityTimer* timer = new EntityTimer(name, time);
|
EntityTimer* timer = new EntityTimer(name, time);
|
||||||
m_Timers.push_back(timer);
|
m_PendingTimers.push_back(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::AddCallbackTimer(float time, std::function<void()> callback) {
|
void Entity::AddCallbackTimer(float time, std::function<void()> callback) {
|
||||||
|
@ -144,6 +144,7 @@ public:
|
|||||||
|
|
||||||
void AddChild(Entity* child);
|
void AddChild(Entity* child);
|
||||||
void RemoveChild(Entity* child);
|
void RemoveChild(Entity* child);
|
||||||
|
void RemoveParent();
|
||||||
void AddTimer(std::string name, float time);
|
void AddTimer(std::string name, float time);
|
||||||
void AddCallbackTimer(float time, std::function<void()> callback);
|
void AddCallbackTimer(float time, std::function<void()> callback);
|
||||||
bool HasTimer(const std::string& name);
|
bool HasTimer(const std::string& name);
|
||||||
@ -309,6 +310,7 @@ protected:
|
|||||||
|
|
||||||
std::unordered_map<int32_t, Component*> m_Components; //The int is the ID of the component
|
std::unordered_map<int32_t, Component*> m_Components; //The int is the ID of the component
|
||||||
std::vector<EntityTimer*> m_Timers;
|
std::vector<EntityTimer*> m_Timers;
|
||||||
|
std::vector<EntityTimer*> m_PendingTimers;
|
||||||
std::vector<EntityCallbackTimer*> m_CallbackTimers;
|
std::vector<EntityCallbackTimer*> m_CallbackTimers;
|
||||||
|
|
||||||
bool m_ShouldDestroyAfterUpdate = false;
|
bool m_ShouldDestroyAfterUpdate = false;
|
||||||
|
@ -401,7 +401,7 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
|||||||
Game::server->Send(&stream, sysAddr, false);
|
Game::server->Send(&stream, sysAddr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketUtils::SavePacket("[24]_"+std::to_string(entity->GetObjectID()) + "_" + std::to_string(m_SerializationCounter) + ".bin", (char*)stream.GetData(), stream.GetNumberOfBytesUsed());
|
// PacketUtils::SavePacket("[24]_"+std::to_string(entity->GetObjectID()) + "_" + std::to_string(m_SerializationCounter) + ".bin", (char*)stream.GetData(), stream.GetNumberOfBytesUsed());
|
||||||
|
|
||||||
if (entity->IsPlayer())
|
if (entity->IsPlayer())
|
||||||
{
|
{
|
||||||
|
@ -369,10 +369,8 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet);
|
LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet);
|
||||||
objectID = GeneralUtils::ClearBit(objectID, OBJECT_BIT_CHARACTER);
|
|
||||||
objectID = GeneralUtils::ClearBit(objectID, OBJECT_BIT_PERSISTENT);
|
|
||||||
|
|
||||||
uint32_t charID = static_cast<uint32_t>(objectID);
|
uint32_t charID = static_cast<uint32_t>(objectID);
|
||||||
|
|
||||||
Game::logger->Log("UserManager", "Received char delete req for ID: %llu (%u)\n", objectID, charID);
|
Game::logger->Log("UserManager", "Received char delete req for ID: %llu (%u)\n", objectID, charID);
|
||||||
|
|
||||||
//Check if this user has this character:
|
//Check if this user has this character:
|
||||||
@ -402,10 +400,14 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM friends WHERE player_id=? OR friend_id=?;");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM friends WHERE player_id=? OR friend_id=?;");
|
||||||
stmt->setUInt64(1, charID);
|
stmt->setUInt(1, charID);
|
||||||
stmt->setUInt64(2, charID);
|
stmt->setUInt(2, charID);
|
||||||
stmt->execute();
|
stmt->execute();
|
||||||
delete stmt;
|
delete stmt;
|
||||||
|
CBITSTREAM;
|
||||||
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION);
|
||||||
|
bitStream.Write(objectID);
|
||||||
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM leaderboard WHERE character_id=?;");
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("DELETE FROM leaderboard WHERE character_id=?;");
|
||||||
|
@ -409,7 +409,7 @@ Behavior::Behavior(const uint32_t behaviorId)
|
|||||||
{
|
{
|
||||||
auto behaviorTemplateTable = CDClientManager::Instance()->GetTable<CDBehaviorTemplateTable>("BehaviorTemplate");
|
auto behaviorTemplateTable = CDClientManager::Instance()->GetTable<CDBehaviorTemplateTable>("BehaviorTemplate");
|
||||||
|
|
||||||
CDBehaviorTemplate templateInDatabase;
|
CDBehaviorTemplate templateInDatabase{};
|
||||||
|
|
||||||
if (behaviorTemplateTable) {
|
if (behaviorTemplateTable) {
|
||||||
auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId);
|
auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId);
|
||||||
@ -445,7 +445,7 @@ Behavior::Behavior(const uint32_t behaviorId)
|
|||||||
|
|
||||||
this->m_effectId = templateInDatabase.effectID;
|
this->m_effectId = templateInDatabase.effectID;
|
||||||
|
|
||||||
this->m_effectHandle = templateInDatabase.effectHandle != "" ? new std::string(templateInDatabase.effectHandle) : nullptr;
|
this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
51
dGame/dBehaviors/CMakeLists.txt
Normal file
51
dGame/dBehaviors/CMakeLists.txt
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp"
|
||||||
|
"AndBehavior.cpp"
|
||||||
|
"ApplyBuffBehavior.cpp"
|
||||||
|
"AreaOfEffectBehavior.cpp"
|
||||||
|
"AttackDelayBehavior.cpp"
|
||||||
|
"BasicAttackBehavior.cpp"
|
||||||
|
"Behavior.cpp"
|
||||||
|
"BehaviorBranchContext.cpp"
|
||||||
|
"BehaviorContext.cpp"
|
||||||
|
"BehaviorTemplates.cpp"
|
||||||
|
"BlockBehavior.cpp"
|
||||||
|
"BuffBehavior.cpp"
|
||||||
|
"CarBoostBehavior.cpp"
|
||||||
|
"ChainBehavior.cpp"
|
||||||
|
"ChangeOrientationBehavior.cpp"
|
||||||
|
"ChargeUpBehavior.cpp"
|
||||||
|
"ClearTargetBehavior.cpp"
|
||||||
|
"DamageAbsorptionBehavior.cpp"
|
||||||
|
"DamageReductionBehavior.cpp"
|
||||||
|
"DurationBehavior.cpp"
|
||||||
|
"EmptyBehavior.cpp"
|
||||||
|
"EndBehavior.cpp"
|
||||||
|
"ForceMovementBehavior.cpp"
|
||||||
|
"HealBehavior.cpp"
|
||||||
|
"ImaginationBehavior.cpp"
|
||||||
|
"ImmunityBehavior.cpp"
|
||||||
|
"InterruptBehavior.cpp"
|
||||||
|
"JetPackBehavior.cpp"
|
||||||
|
"KnockbackBehavior.cpp"
|
||||||
|
"LootBuffBehavior.cpp"
|
||||||
|
"MovementSwitchBehavior.cpp"
|
||||||
|
"NpcCombatSkillBehavior.cpp"
|
||||||
|
"OverTimeBehavior.cpp"
|
||||||
|
"PlayEffectBehavior.cpp"
|
||||||
|
"ProjectileAttackBehavior.cpp"
|
||||||
|
"PullToPointBehavior.cpp"
|
||||||
|
"RepairBehavior.cpp"
|
||||||
|
"SkillCastFailedBehavior.cpp"
|
||||||
|
"SkillEventBehavior.cpp"
|
||||||
|
"SpawnBehavior.cpp"
|
||||||
|
"SpawnQuickbuildBehavior.cpp"
|
||||||
|
"SpeedBehavior.cpp"
|
||||||
|
"StartBehavior.cpp"
|
||||||
|
"StunBehavior.cpp"
|
||||||
|
"SwitchBehavior.cpp"
|
||||||
|
"SwitchMultipleBehavior.cpp"
|
||||||
|
"TacArcBehavior.cpp"
|
||||||
|
"TargetCasterBehavior.cpp"
|
||||||
|
"TauntBehavior.cpp"
|
||||||
|
"VentureVisionBehavior.cpp"
|
||||||
|
"VerifyBehavior.cpp" PARENT_SCOPE)
|
40
dGame/dComponents/CMakeLists.txt
Normal file
40
dGame/dComponents/CMakeLists.txt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
|
||||||
|
"BouncerComponent.cpp"
|
||||||
|
"BuffComponent.cpp"
|
||||||
|
"BuildBorderComponent.cpp"
|
||||||
|
"CharacterComponent.cpp"
|
||||||
|
"Component.cpp"
|
||||||
|
"ControllablePhysicsComponent.cpp"
|
||||||
|
"DestroyableComponent.cpp"
|
||||||
|
"InventoryComponent.cpp"
|
||||||
|
"LUPExhibitComponent.cpp"
|
||||||
|
"MissionComponent.cpp"
|
||||||
|
"MissionOfferComponent.cpp"
|
||||||
|
"ModelComponent.cpp"
|
||||||
|
"ModuleAssemblyComponent.cpp"
|
||||||
|
"MovementAIComponent.cpp"
|
||||||
|
"MovingPlatformComponent.cpp"
|
||||||
|
"PetComponent.cpp"
|
||||||
|
"PhantomPhysicsComponent.cpp"
|
||||||
|
"PossessableComponent.cpp"
|
||||||
|
"PossessorComponent.cpp"
|
||||||
|
"PropertyComponent.cpp"
|
||||||
|
"PropertyEntranceComponent.cpp"
|
||||||
|
"PropertyManagementComponent.cpp"
|
||||||
|
"PropertyVendorComponent.cpp"
|
||||||
|
"ProximityMonitorComponent.cpp"
|
||||||
|
"RacingControlComponent.cpp"
|
||||||
|
"RailActivatorComponent.cpp"
|
||||||
|
"RebuildComponent.cpp"
|
||||||
|
"RenderComponent.cpp"
|
||||||
|
"RigidbodyPhantomPhysicsComponent.cpp"
|
||||||
|
"RocketLaunchLupComponent.cpp"
|
||||||
|
"RocketLaunchpadControlComponent.cpp"
|
||||||
|
"ScriptedActivityComponent.cpp"
|
||||||
|
"ShootingGalleryComponent.cpp"
|
||||||
|
"SimplePhysicsComponent.cpp"
|
||||||
|
"SkillComponent.cpp"
|
||||||
|
"SoundTriggerComponent.cpp"
|
||||||
|
"SwitchComponent.cpp"
|
||||||
|
"VehiclePhysicsComponent.cpp"
|
||||||
|
"VendorComponent.cpp" PARENT_SCOPE)
|
@ -179,6 +179,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SetLastRocketItemID(LWOOBJID lastRocketItemID) { m_LastRocketItemID = lastRocketItemID; }
|
void SetLastRocketItemID(LWOOBJID lastRocketItemID) { m_LastRocketItemID = lastRocketItemID; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the object ID of the mount item that is being used
|
||||||
|
* @return the object ID of the mount item that is being used
|
||||||
|
*/
|
||||||
|
LWOOBJID GetMountItemID() const { return m_MountItemID; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the object ID of the mount item that is being used
|
||||||
|
* @param m_MountItemID the object ID of the mount item that is being used
|
||||||
|
*/
|
||||||
|
void SetMountItemID(LWOOBJID mountItemID) { m_MountItemID = mountItemID; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives the player rewards for the last level that they leveled up from
|
* Gives the player rewards for the last level that they leveled up from
|
||||||
*/
|
*/
|
||||||
@ -579,6 +591,11 @@ private:
|
|||||||
* ID of the last rocket used
|
* ID of the last rocket used
|
||||||
*/
|
*/
|
||||||
LWOOBJID m_LastRocketItemID = LWOOBJID_EMPTY;
|
LWOOBJID m_LastRocketItemID = LWOOBJID_EMPTY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mount Item ID
|
||||||
|
*/
|
||||||
|
LWOOBJID m_MountItemID = LWOOBJID_EMPTY;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CHARACTERCOMPONENT_H
|
#endif // CHARACTERCOMPONENT_H
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "PropertyManagementComponent.h"
|
#include "PropertyManagementComponent.h"
|
||||||
#include "DestroyableComponent.h"
|
#include "DestroyableComponent.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
|
#include "eItemType.h"
|
||||||
|
|
||||||
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent)
|
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent)
|
||||||
{
|
{
|
||||||
@ -1024,13 +1025,13 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == ITEM_TYPE_LOOT_MODEL || type == ITEM_TYPE_VEHICLE)
|
if (type == eItemType::ITEM_TYPE_LOOT_MODEL || type == eItemType::ITEM_TYPE_VEHICLE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != ITEM_TYPE_LOOT_MODEL && type != ITEM_TYPE_MODEL)
|
if (type != eItemType::ITEM_TYPE_LOOT_MODEL && type != eItemType::ITEM_TYPE_MODEL)
|
||||||
{
|
{
|
||||||
if (!item->GetBound() && !item->GetPreconditionExpression()->Check(m_Parent))
|
if (!item->GetBound() && !item->GetPreconditionExpression()->Check(m_Parent))
|
||||||
{
|
{
|
||||||
@ -1411,15 +1412,15 @@ void InventoryComponent::RemoveDatabasePet(LWOOBJID id)
|
|||||||
BehaviorSlot InventoryComponent::FindBehaviorSlot(const eItemType type)
|
BehaviorSlot InventoryComponent::FindBehaviorSlot(const eItemType type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ITEM_TYPE_HAT:
|
case eItemType::ITEM_TYPE_HAT:
|
||||||
return BehaviorSlot::Head;
|
return BehaviorSlot::Head;
|
||||||
case ITEM_TYPE_NECK:
|
case eItemType::ITEM_TYPE_NECK:
|
||||||
return BehaviorSlot::Neck;
|
return BehaviorSlot::Neck;
|
||||||
case ITEM_TYPE_LEFT_HAND:
|
case eItemType::ITEM_TYPE_LEFT_HAND:
|
||||||
return BehaviorSlot::Offhand;
|
return BehaviorSlot::Offhand;
|
||||||
case ITEM_TYPE_RIGHT_HAND:
|
case eItemType::ITEM_TYPE_RIGHT_HAND:
|
||||||
return BehaviorSlot::Primary;
|
return BehaviorSlot::Primary;
|
||||||
case ITEM_TYPE_CONSUMABLE:
|
case eItemType::ITEM_TYPE_CONSUMABLE:
|
||||||
return BehaviorSlot::Consumable;
|
return BehaviorSlot::Consumable;
|
||||||
default:
|
default:
|
||||||
return BehaviorSlot::Invalid;
|
return BehaviorSlot::Invalid;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef INVENTORYCOMPONENT_H
|
#ifndef INVENTORYCOMPONENT_H
|
||||||
#define INVENTORYCOMPONENT_H
|
#define INVENTORYCOMPONENT_H
|
||||||
@ -25,6 +25,8 @@ class ItemSet;
|
|||||||
|
|
||||||
typedef std::map<std::string, EquippedItem> EquipmentMap;
|
typedef std::map<std::string, EquippedItem> EquipmentMap;
|
||||||
|
|
||||||
|
enum class eItemType : int32_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the inventory of entity, including the items they possess and have equipped. An entity can have inventories
|
* Handles the inventory of entity, including the items they possess and have equipped. An entity can have inventories
|
||||||
* of different types, each type representing a different group of items, see `eInventoryType` for a list of
|
* of different types, each type representing a different group of items, see `eInventoryType` for a list of
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
#include "PossessableComponent.h"
|
#include "PossessableComponent.h"
|
||||||
#include "PossessorComponent.h"
|
#include "PossessorComponent.h"
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
|
#include "Inventory.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
|
|
||||||
PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId) : Component(parent){
|
PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId) : Component(parent){
|
||||||
m_Possessor = LWOOBJID_EMPTY;
|
m_Possessor = LWOOBJID_EMPTY;
|
||||||
|
CDItemComponent item = Inventory::FindItemComponent(m_Parent->GetLOT());
|
||||||
|
m_AnimationFlag = static_cast<eAnimationFlags>(item.animationFlag);
|
||||||
|
|
||||||
// Get the possession Type from the CDClient
|
// Get the possession Type from the CDClient
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT possessionType, depossessOnHit FROM PossessableComponent WHERE id = ?;");
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT possessionType, depossessOnHit FROM PossessableComponent WHERE id = ?;");
|
||||||
|
@ -54,6 +54,18 @@ class PossessableComponent : public Component {
|
|||||||
*/
|
*/
|
||||||
void ForceDepossess() { m_ImmediatelyDepossess = true; m_DirtyPossessable = true;};
|
void ForceDepossess() { m_ImmediatelyDepossess = true; m_DirtyPossessable = true;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if the parent entity was spawned from an item
|
||||||
|
* @param value if the parent entity was spawned from an item
|
||||||
|
*/
|
||||||
|
void SetItemSpawned(bool value) { m_ItemSpawned = value;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the parent entity was spawned from an item
|
||||||
|
* @return if the parent entity was spawned from an item
|
||||||
|
*/
|
||||||
|
LWOOBJID GetItemSpawned() const { return m_ItemSpawned; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an OnUsed event by some other entity, if said entity has a Possessor it becomes the possessor
|
* Handles an OnUsed event by some other entity, if said entity has a Possessor it becomes the possessor
|
||||||
* of this entity
|
* of this entity
|
||||||
@ -95,4 +107,9 @@ class PossessableComponent : public Component {
|
|||||||
*/
|
*/
|
||||||
bool m_ImmediatelyDepossess = false;
|
bool m_ImmediatelyDepossess = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether the parent entity was spawned from an item
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool m_ItemSpawned = false;
|
||||||
};
|
};
|
||||||
|
@ -36,6 +36,18 @@ class PossessorComponent : public Component {
|
|||||||
*/
|
*/
|
||||||
LWOOBJID GetPossessable() const { return m_Possessable; }
|
LWOOBJID GetPossessable() const { return m_Possessable; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if we are busy mounting or dismounting
|
||||||
|
* @param value if we are busy mounting or dismounting
|
||||||
|
*/
|
||||||
|
void SetIsBusy(bool value) { m_IsBusy = value; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if we are busy mounting or dismounting
|
||||||
|
* @return if we are busy mounting or dismounting
|
||||||
|
*/
|
||||||
|
bool GetIsBusy() const { return m_IsBusy; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the possesible type that's currently used, merely used by the shooting gallery if it's 0
|
* Sets the possesible type that's currently used, merely used by the shooting gallery if it's 0
|
||||||
* @param value the possesible type to set
|
* @param value the possesible type to set
|
||||||
@ -60,4 +72,10 @@ class PossessorComponent : public Component {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool m_DirtyPossesor = false;
|
bool m_DirtyPossesor = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief if the possessor is busy mounting or dismounting
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool m_IsBusy = false;
|
||||||
};
|
};
|
||||||
|
@ -102,7 +102,7 @@ PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(Propert
|
|||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery, bool wantLimits) {
|
std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery, bool wantLimits) {
|
||||||
std::string base;
|
std::string base;
|
||||||
if (customQuery == "") {
|
if (customQuery == "") {
|
||||||
base = baseQueryForProperties;
|
base = baseQueryForProperties;
|
||||||
@ -115,15 +115,13 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe
|
|||||||
|
|
||||||
auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;");
|
auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;");
|
||||||
|
|
||||||
friendsListQuery->setInt64(1, entity->GetObjectID());
|
friendsListQuery->setUInt(1, character->GetID());
|
||||||
friendsListQuery->setInt64(2, entity->GetObjectID());
|
friendsListQuery->setUInt(2, character->GetID());
|
||||||
|
|
||||||
auto friendsListQueryResult = friendsListQuery->executeQuery();
|
auto friendsListQueryResult = friendsListQuery->executeQuery();
|
||||||
|
|
||||||
while (friendsListQueryResult->next()) {
|
while (friendsListQueryResult->next()) {
|
||||||
auto playerIDToConvert = friendsListQueryResult->getInt64(1);
|
auto playerIDToConvert = friendsListQueryResult->getInt(1);
|
||||||
playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_CHARACTER);
|
|
||||||
playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_PERSISTENT);
|
|
||||||
friendsList = friendsList + std::to_string(playerIDToConvert) + ",";
|
friendsList = friendsList + std::to_string(playerIDToConvert) + ",";
|
||||||
}
|
}
|
||||||
// Replace trailing comma with the closing parenthesis.
|
// Replace trailing comma with the closing parenthesis.
|
||||||
@ -193,7 +191,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
|
|||||||
|
|
||||||
entries.push_back(playerEntry);
|
entries.push_back(playerEntry);
|
||||||
|
|
||||||
const auto query = BuildQuery(entity, sortMethod);
|
const auto query = BuildQuery(entity, sortMethod, character);
|
||||||
|
|
||||||
auto propertyLookup = Database::CreatePreppedStmt(query);
|
auto propertyLookup = Database::CreatePreppedStmt(query);
|
||||||
|
|
||||||
@ -262,17 +260,17 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
|
|||||||
// Query to get friend and best friend fields
|
// Query to get friend and best friend fields
|
||||||
auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)");
|
auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)");
|
||||||
|
|
||||||
friendCheck->setInt64(1, entity->GetObjectID());
|
friendCheck->setUInt(1, character->GetID());
|
||||||
friendCheck->setInt64(2, ownerObjId);
|
friendCheck->setUInt(2, ownerObjId);
|
||||||
friendCheck->setInt64(3, ownerObjId);
|
friendCheck->setUInt(3, ownerObjId);
|
||||||
friendCheck->setInt64(4, entity->GetObjectID());
|
friendCheck->setUInt(4, character->GetID());
|
||||||
|
|
||||||
auto friendResult = friendCheck->executeQuery();
|
auto friendResult = friendCheck->executeQuery();
|
||||||
|
|
||||||
// If we got a result than the two players are friends.
|
// If we got a result than the two players are friends.
|
||||||
if (friendResult->next()) {
|
if (friendResult->next()) {
|
||||||
isFriend = true;
|
isFriend = true;
|
||||||
if (friendResult->getInt(1) == 2) {
|
if (friendResult->getInt(1) == 3) {
|
||||||
isBestFriend = true;
|
isBestFriend = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +324,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
|
|||||||
// Query here is to figure out whether or not to display the button to go to the next page or not.
|
// Query here is to figure out whether or not to display the button to go to the next page or not.
|
||||||
int32_t numberOfProperties = 0;
|
int32_t numberOfProperties = 0;
|
||||||
|
|
||||||
auto buttonQuery = BuildQuery(entity, sortMethod, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ", false);
|
auto buttonQuery = BuildQuery(entity, sortMethod, character, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ", false);
|
||||||
auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery);
|
auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery);
|
||||||
|
|
||||||
propertiesLeft->setUInt(1, this->m_MapID);
|
propertiesLeft->setUInt(1, this->m_MapID);
|
||||||
|
@ -60,7 +60,7 @@ class PropertyEntranceComponent : public Component {
|
|||||||
|
|
||||||
PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f);
|
PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f);
|
||||||
|
|
||||||
std::string BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery = "", bool wantLimits = true);
|
std::string BuildQuery(Entity* entity, int32_t sortMethod, Character* character, std::string customQuery = "", bool wantLimits = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
2
dGame/dEntity/CMakeLists.txt
Normal file
2
dGame/dEntity/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
set(DGAME_DENTITY_SOURCES "EntityCallbackTimer.cpp"
|
||||||
|
"EntityTimer.cpp" PARENT_SCOPE)
|
4
dGame/dGameMessages/CMakeLists.txt
Normal file
4
dGame/dGameMessages/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
set(DGAME_DGAMEMESSAGES_SOURCES "GameMessageHandler.cpp"
|
||||||
|
"GameMessages.cpp"
|
||||||
|
"PropertyDataMessage.cpp"
|
||||||
|
"PropertySelectQueryProperty.cpp" PARENT_SCOPE)
|
@ -3986,6 +3986,47 @@ void GameMessages::SendDisplayChatBubble(LWOOBJID objectId, const std::u16string
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mounts
|
||||||
|
|
||||||
|
void GameMessages::SendSetMountInventoryID(Entity* entity, const LWOOBJID& objectID, const SystemAddress& sysAddr){
|
||||||
|
CBITSTREAM;
|
||||||
|
CMSGHEADER;
|
||||||
|
|
||||||
|
bitStream.Write(entity->GetObjectID());
|
||||||
|
bitStream.Write(GAME_MSG::GAME_MSG_SET_MOUNT_INVENTORY_ID);
|
||||||
|
bitStream.Write(objectID);
|
||||||
|
|
||||||
|
SEND_PACKET_BROADCAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GameMessages::HandleDismountComplete(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr){
|
||||||
|
LWOOBJID objectId{};
|
||||||
|
inStream->Read(objectId);
|
||||||
|
auto* mount = EntityManager::Instance()->GetEntity(objectId);
|
||||||
|
|
||||||
|
if (objectId != LWOOBJID_EMPTY) {
|
||||||
|
PossessorComponent* possessor;
|
||||||
|
if (entity->TryGetComponent(COMPONENT_TYPE_POSSESSOR, possessor)) {
|
||||||
|
if (mount) {
|
||||||
|
possessor->SetIsBusy(false);
|
||||||
|
possessor->SetPossessable(LWOOBJID_EMPTY);
|
||||||
|
possessor->SetPossessableType(ePossessionType::NO_POSSESSION);
|
||||||
|
|
||||||
|
GameMessages::SendSetStunned(entity->GetObjectID(), eStunState::POP, UNASSIGNED_SYSTEM_ADDRESS, LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
|
||||||
|
|
||||||
|
EntityManager::Instance()->SerializeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GameMessages::HandleAcknowledgePossession(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||||
|
Game::logger->Log("HandleAcknowledgePossession", "Got AcknowledgePossession from %i\n", entity->GetLOT());
|
||||||
|
EntityManager::Instance()->SerializeEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
//Racing
|
//Racing
|
||||||
|
|
||||||
void GameMessages::HandleModuleAssemblyQueryData(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr)
|
void GameMessages::HandleModuleAssemblyQueryData(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr)
|
||||||
@ -4042,14 +4083,6 @@ void GameMessages::HandleRacingClientReady(RakNet::BitStream* inStream, Entity*
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GameMessages::HandleAcknowledgePossession(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr)
|
|
||||||
{
|
|
||||||
Game::logger->Log("HandleAcknowledgePossession", "Got AcknowledgePossession from %i\n", entity->GetLOT());
|
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr)
|
void GameMessages::HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr)
|
||||||
{
|
{
|
||||||
bool bClientDeath;
|
bool bClientDeath;
|
||||||
|
@ -328,6 +328,34 @@ namespace GameMessages {
|
|||||||
|
|
||||||
void SendDisplayChatBubble(LWOOBJID objectId, const std::u16string& text, const SystemAddress& sysAddr);
|
void SendDisplayChatBubble(LWOOBJID objectId, const std::u16string& text, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
|
// Mounts
|
||||||
|
/**
|
||||||
|
* @brief Set the Inventory LWOOBJID of the mount
|
||||||
|
*
|
||||||
|
* @param entity The entity that is mounting
|
||||||
|
* @param sysAddr the system address to send game message responses to
|
||||||
|
* @param objectID LWOOBJID of the item in inventory that is being used
|
||||||
|
*/
|
||||||
|
void SendSetMountInventoryID(Entity* entity, const LWOOBJID& objectID, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle client dismounting mount
|
||||||
|
*
|
||||||
|
* @param inStream Raknet BitStream of incoming data
|
||||||
|
* @param entity The Entity that is dismounting
|
||||||
|
* @param sysAddr the system address to send game message responses to
|
||||||
|
*/
|
||||||
|
void HandleDismountComplete(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle acknowledging that the client possessed something
|
||||||
|
*
|
||||||
|
* @param inStream Raknet BitStream of incoming data
|
||||||
|
* @param entity The Entity that is possessing
|
||||||
|
* @param sysAddr the system address to send game message responses to
|
||||||
|
*/
|
||||||
|
void HandleAcknowledgePossession(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
//Racing:
|
//Racing:
|
||||||
void HandleModuleAssemblyQueryData(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
void HandleModuleAssemblyQueryData(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
@ -337,8 +365,6 @@ namespace GameMessages {
|
|||||||
|
|
||||||
void HandleRacingClientReady(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
void HandleRacingClientReady(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
void HandleAcknowledgePossession(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
|
||||||
|
|
||||||
void HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
void HandleRequestDie(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
void HandleVehicleNotifyServerAddPassiveBoostAction(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
void HandleVehicleNotifyServerAddPassiveBoostAction(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||||
|
5
dGame/dInventory/CMakeLists.txt
Normal file
5
dGame/dInventory/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
set(DGAME_DINVENTORY_SOURCES "EquippedItem.cpp"
|
||||||
|
"Inventory.cpp"
|
||||||
|
"Item.cpp"
|
||||||
|
"ItemSet.cpp"
|
||||||
|
"ItemSetPassiveAbility.cpp" PARENT_SCOPE)
|
@ -1,7 +1,8 @@
|
|||||||
#include "Inventory.h"
|
#include "Inventory.h"
|
||||||
#include "GameMessages.h"
|
#include "GameMessages.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
|
#include "eItemType.h"
|
||||||
|
|
||||||
std::vector<LOT> Inventory::m_GameMasterRestrictedItems = {
|
std::vector<LOT> Inventory::m_GameMasterRestrictedItems = {
|
||||||
1727, // GM Only - JetPack
|
1727, // GM Only - JetPack
|
||||||
@ -274,40 +275,41 @@ eInventoryType Inventory::FindInventoryTypeForLot(const LOT lot)
|
|||||||
const auto itemType = static_cast<eItemType>(itemComponent.itemType);
|
const auto itemType = static_cast<eItemType>(itemComponent.itemType);
|
||||||
|
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
case ITEM_TYPE_BRICK:
|
case eItemType::ITEM_TYPE_BRICK:
|
||||||
return BRICKS;
|
return BRICKS;
|
||||||
|
|
||||||
case ITEM_TYPE_BEHAVIOR:
|
case eItemType::ITEM_TYPE_BEHAVIOR:
|
||||||
return BEHAVIORS;
|
return BEHAVIORS;
|
||||||
|
|
||||||
case ITEM_TYPE_PROPERTY:
|
case eItemType::ITEM_TYPE_PROPERTY:
|
||||||
return PROPERTY_DEEDS;
|
return PROPERTY_DEEDS;
|
||||||
|
|
||||||
case ITEM_TYPE_MODEL:
|
case eItemType::ITEM_TYPE_MODEL:
|
||||||
case ITEM_TYPE_VEHICLE:
|
case eItemType::ITEM_TYPE_VEHICLE:
|
||||||
case ITEM_TYPE_LOOT_MODEL:
|
case eItemType::ITEM_TYPE_LOOT_MODEL:
|
||||||
|
case eItemType::ITEM_TYPE_MOUNT:
|
||||||
return MODELS;
|
return MODELS;
|
||||||
|
|
||||||
case ITEM_TYPE_HAT:
|
case eItemType::ITEM_TYPE_HAT:
|
||||||
case ITEM_TYPE_HAIR:
|
case eItemType::ITEM_TYPE_HAIR:
|
||||||
case ITEM_TYPE_NECK:
|
case eItemType::ITEM_TYPE_NECK:
|
||||||
case ITEM_TYPE_LEFT_HAND:
|
case eItemType::ITEM_TYPE_LEFT_HAND:
|
||||||
case ITEM_TYPE_RIGHT_HAND:
|
case eItemType::ITEM_TYPE_RIGHT_HAND:
|
||||||
case ITEM_TYPE_LEGS:
|
case eItemType::ITEM_TYPE_LEGS:
|
||||||
case ITEM_TYPE_LEFT_TRINKET:
|
case eItemType::ITEM_TYPE_LEFT_TRINKET:
|
||||||
case ITEM_TYPE_RIGHT_TRINKET:
|
case eItemType::ITEM_TYPE_RIGHT_TRINKET:
|
||||||
case ITEM_TYPE_COLLECTIBLE:
|
case eItemType::ITEM_TYPE_COLLECTIBLE:
|
||||||
case ITEM_TYPE_CONSUMABLE:
|
case eItemType::ITEM_TYPE_CONSUMABLE:
|
||||||
case ITEM_TYPE_CHEST:
|
case eItemType::ITEM_TYPE_CHEST:
|
||||||
case ITEM_TYPE_EGG:
|
case eItemType::ITEM_TYPE_EGG:
|
||||||
case ITEM_TYPE_PET_FOOD:
|
case eItemType::ITEM_TYPE_PET_FOOD:
|
||||||
case ITEM_TYPE_PET_INVENTORY_ITEM:
|
case eItemType::ITEM_TYPE_PET_INVENTORY_ITEM:
|
||||||
case ITEM_TYPE_PACKAGE:
|
case eItemType::ITEM_TYPE_PACKAGE:
|
||||||
case ITEM_TYPE_CURRENCY:
|
case eItemType::ITEM_TYPE_CURRENCY:
|
||||||
return ITEMS;
|
return ITEMS;
|
||||||
|
|
||||||
case ITEM_TYPE_QUEST_OBJECT:
|
case eItemType::ITEM_TYPE_QUEST_OBJECT:
|
||||||
case ITEM_TYPE_UNKNOWN:
|
case eItemType::ITEM_TYPE_UNKNOWN:
|
||||||
default:
|
default:
|
||||||
return HIDDEN;
|
return HIDDEN;
|
||||||
}
|
}
|
||||||
|
3
dGame/dMission/CMakeLists.txt
Normal file
3
dGame/dMission/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
set(DGAME_DMISSION_SOURCES "Mission.cpp"
|
||||||
|
"MissionPrerequisites.cpp"
|
||||||
|
"MissionTask.cpp" PARENT_SCOPE)
|
9
dGame/dUtilities/CMakeLists.txt
Normal file
9
dGame/dUtilities/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
set(DGAME_DUTILITIES_SOURCES "BrickDatabase.cpp"
|
||||||
|
"dLocale.cpp"
|
||||||
|
"GameConfig.cpp"
|
||||||
|
"GUID.cpp"
|
||||||
|
"Loot.cpp"
|
||||||
|
"Mail.cpp"
|
||||||
|
"Preconditions.cpp"
|
||||||
|
"SlashCommandHandler.cpp"
|
||||||
|
"VanityUtilities.cpp" PARENT_SCOPE)
|
@ -2017,11 +2017,15 @@ void SlashCommandHandler::SendAnnouncement(const std::string& title, const std::
|
|||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ANNOUNCEMENT);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ANNOUNCEMENT);
|
||||||
|
|
||||||
RakNet::RakString rsTitle(title.c_str());
|
bitStream.Write<uint32_t>(title.size());
|
||||||
RakNet::RakString rsMsg(message.c_str());
|
for (auto character : title) {
|
||||||
|
bitStream.Write<char>(character);
|
||||||
|
}
|
||||||
|
|
||||||
bitStream.Write(rsTitle);
|
bitStream.Write<uint32_t>(message.size());
|
||||||
bitStream.Write(rsMsg);
|
for (auto character : message) {
|
||||||
|
bitStream.Write<char>(character);
|
||||||
|
}
|
||||||
|
|
||||||
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||||
}
|
}
|
||||||
|
10
dMasterServer/CMakeLists.txt
Normal file
10
dMasterServer/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
set(DMASTERSERVER_SOURCES "InstanceManager.cpp"
|
||||||
|
"MasterServer.cpp"
|
||||||
|
"ObjectIDManager.cpp")
|
||||||
|
|
||||||
|
add_executable(MasterServer ${DMASTERSERVER_SOURCES})
|
||||||
|
target_link_libraries(MasterServer ${COMMON_LIBRARIES})
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
add_dependencies(MasterServer WorldServer AuthServer ChatServer)
|
||||||
|
endif()
|
@ -19,6 +19,7 @@
|
|||||||
#include "CDClientDatabase.h"
|
#include "CDClientDatabase.h"
|
||||||
#include "CDClientManager.h"
|
#include "CDClientManager.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
|
#include "MigrationRunner.h"
|
||||||
#include "Diagnostics.h"
|
#include "Diagnostics.h"
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
@ -127,6 +128,13 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argc > 1 && (strcmp(argv[1], "-m") == 0 || strcmp(argv[1], "--migrations") == 0)) {
|
||||||
|
MigrationRunner::RunMigrations();
|
||||||
|
Game::logger->Log("MigrationRunner", "Finished running migrations\n");
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
//If the first command line argument is -a or --account then make the user
|
//If the first command line argument is -a or --account then make the user
|
||||||
//input a username and password, with the password being hidden.
|
//input a username and password, with the password being hidden.
|
||||||
if (argc > 1 &&
|
if (argc > 1 &&
|
||||||
@ -491,7 +499,10 @@ void HandlePacket(Packet* packet) {
|
|||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_NEW_SESSION_ALERT);
|
PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_NEW_SESSION_ALERT);
|
||||||
bitStream.Write(sessionKey);
|
bitStream.Write(sessionKey);
|
||||||
bitStream.Write(RakNet::RakString(username.c_str()));
|
bitStream.Write<uint32_t>(username.size());
|
||||||
|
for (auto character : username) {
|
||||||
|
bitStream.Write(character);
|
||||||
|
}
|
||||||
SEND_PACKET_BROADCAST;
|
SEND_PACKET_BROADCAST;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -566,14 +577,20 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
uint32_t mapId;
|
uint32_t mapId;
|
||||||
LWOCLONEID cloneId;
|
LWOCLONEID cloneId;
|
||||||
RakNet::RakString password;
|
std::string password;
|
||||||
|
|
||||||
inStream.Read(mapId);
|
inStream.Read(mapId);
|
||||||
inStream.Read(cloneId);
|
inStream.Read(cloneId);
|
||||||
inStream.Read(password);
|
|
||||||
|
|
||||||
Game::im->CreatePrivateInstance(mapId, cloneId,
|
uint32_t len;
|
||||||
password.C_String());
|
inStream.Read<uint32_t>(len);
|
||||||
|
for (int i = 0; len > i; i++) {
|
||||||
|
char character;
|
||||||
|
inStream.Read<char>(character);
|
||||||
|
password += character;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::im->CreatePrivateInstance(mapId, cloneId, password.c_str());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -585,15 +602,22 @@ void HandlePacket(Packet* packet) {
|
|||||||
uint64_t requestID = 0;
|
uint64_t requestID = 0;
|
||||||
uint8_t mythranShift = false;
|
uint8_t mythranShift = false;
|
||||||
|
|
||||||
RakNet::RakString password;
|
std::string password;
|
||||||
|
|
||||||
inStream.Read(requestID);
|
inStream.Read(requestID);
|
||||||
inStream.Read(mythranShift);
|
inStream.Read(mythranShift);
|
||||||
inStream.Read(password);
|
|
||||||
|
|
||||||
auto* instance = Game::im->FindPrivateInstance(password.C_String());
|
uint32_t len;
|
||||||
|
inStream.Read<uint32_t>(len);
|
||||||
|
|
||||||
Game::logger->Log( "MasterServer", "Join private zone: %llu %d %s %p\n", requestID, mythranShift, password.C_String(), instance);
|
for (int i = 0; i < len; i++) {
|
||||||
|
char character; inStream.Read<char>(character);
|
||||||
|
password += character;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* instance = Game::im->FindPrivateInstance(password.c_str());
|
||||||
|
|
||||||
|
Game::logger->Log( "MasterServer", "Join private zone: %llu %d %s %p\n", requestID, mythranShift, password.c_str(), instance);
|
||||||
|
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
11
dNet/CMakeLists.txt
Normal file
11
dNet/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
set(DNET_SOURCES "AuthPackets.cpp"
|
||||||
|
"ChatPackets.cpp"
|
||||||
|
"ClientPackets.cpp"
|
||||||
|
"dServer.cpp"
|
||||||
|
"MasterPackets.cpp"
|
||||||
|
"PacketUtils.cpp"
|
||||||
|
"WorldPackets.cpp"
|
||||||
|
"ZoneInstanceManager.cpp")
|
||||||
|
|
||||||
|
add_library(dNet STATIC ${DNET_SOURCES})
|
||||||
|
target_link_libraries(dNet dCommon dDatabase)
|
@ -43,8 +43,10 @@ void MasterPackets::SendZoneCreatePrivate(dServer* server, uint32_t zoneID, uint
|
|||||||
bitStream.Write(zoneID);
|
bitStream.Write(zoneID);
|
||||||
bitStream.Write(cloneID);
|
bitStream.Write(cloneID);
|
||||||
|
|
||||||
RakNet::RakString passwd(password.c_str());
|
bitStream.Write<uint32_t>(password.size());
|
||||||
bitStream.Write(passwd);
|
for (auto character : password) {
|
||||||
|
bitStream.Write<char>(character);
|
||||||
|
}
|
||||||
|
|
||||||
server->SendToMaster(&bitStream);
|
server->SendToMaster(&bitStream);
|
||||||
}
|
}
|
||||||
@ -56,8 +58,10 @@ void MasterPackets::SendZoneRequestPrivate(dServer* server, uint64_t requestID,
|
|||||||
bitStream.Write(requestID);
|
bitStream.Write(requestID);
|
||||||
bitStream.Write(static_cast<uint8_t>(mythranShift));
|
bitStream.Write(static_cast<uint8_t>(mythranShift));
|
||||||
|
|
||||||
RakNet::RakString passwd(password.c_str());
|
bitStream.Write<uint32_t>(password.size());
|
||||||
bitStream.Write(passwd);
|
for (auto character : password) {
|
||||||
|
bitStream.Write<char>(character);
|
||||||
|
}
|
||||||
|
|
||||||
server->SendToMaster(&bitStream);
|
server->SendToMaster(&bitStream);
|
||||||
}
|
}
|
||||||
|
@ -535,8 +535,10 @@ enum GAME_MSG : unsigned short {
|
|||||||
GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666,
|
GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666,
|
||||||
GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667,
|
GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667,
|
||||||
GAME_MSG_PLAYER_SET_CAMERA_CYCLING_MODE = 1676,
|
GAME_MSG_PLAYER_SET_CAMERA_CYCLING_MODE = 1676,
|
||||||
|
GAME_MSG_SET_MOUNT_INVENTORY_ID = 1726,
|
||||||
GAME_MSG_NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE = 1734,
|
GAME_MSG_NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE = 1734,
|
||||||
GAME_MSG_NOTIFY_LEVEL_REWARDS = 1735,
|
GAME_MSG_NOTIFY_LEVEL_REWARDS = 1735,
|
||||||
|
GAME_MSG_DISMOUNT_COMPLETE = 1756,
|
||||||
GAME_MSG_MARK_INVENTORY_ITEM_AS_ACTIVE = 1767,
|
GAME_MSG_MARK_INVENTORY_ITEM_AS_ACTIVE = 1767,
|
||||||
END
|
END
|
||||||
};
|
};
|
9
dPhysics/CMakeLists.txt
Normal file
9
dPhysics/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
set(DPHYSICS_SOURCES "dpCollisionChecks.cpp"
|
||||||
|
"dpEntity.cpp"
|
||||||
|
"dpGrid.cpp"
|
||||||
|
"dpShapeBase.cpp"
|
||||||
|
"dpShapeBox.cpp"
|
||||||
|
"dpShapeSphere.cpp"
|
||||||
|
"dpWorld.cpp")
|
||||||
|
|
||||||
|
add_library(dPhysics STATIC ${DPHYSICS_SOURCES})
|
@ -169,11 +169,10 @@ void BasePropertyServer::BaseZonePropertyRented(Entity* self, Entity* player) co
|
|||||||
EntityManager::Instance()->DestructEntity(plaque);
|
EntityManager::Instance()->DestructEntity(plaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->GetVar<int32_t>(brickLinkMissionIDFlag) != 0) {
|
auto brickLinkMissionID = self->GetVar<uint32_t>(brickLinkMissionIDFlag);
|
||||||
auto plaques = EntityManager::Instance()->GetEntitiesInGroup(self->GetVar<std::string>(PropertyPlaqueGroup));
|
if (brickLinkMissionID != 0) {
|
||||||
for (auto* plaque : plaques) {
|
auto missionComponent = player->GetComponent<MissionComponent>();
|
||||||
EntityManager::Instance()->DestructEntity(plaque);
|
if (missionComponent) missionComponent->CompleteMission(brickLinkMissionID, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivateSpawner(self->GetVar<std::string>(PropObjsSpawner));
|
ActivateSpawner(self->GetVar<std::string>(PropObjsSpawner));
|
||||||
|
253
dScripts/CMakeLists.txt
Normal file
253
dScripts/CMakeLists.txt
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
set(DSCRIPT_SOURCES "ActivityManager.cpp"
|
||||||
|
"ActMine.cpp"
|
||||||
|
"ActNinjaTurret.cpp"
|
||||||
|
"ActParadoxPipeFix.cpp"
|
||||||
|
"ActPlayerDeathTrigger.cpp"
|
||||||
|
"ActSharkPlayerDeathTrigger.cpp"
|
||||||
|
"ActVehicleDeathTrigger.cpp"
|
||||||
|
"AgBugsprayer.cpp"
|
||||||
|
"AgBusDoor.cpp"
|
||||||
|
"AgCagedBricksServer.cpp"
|
||||||
|
"AgDarkSpiderling.cpp"
|
||||||
|
"AgFans.cpp"
|
||||||
|
"AgImagSmashable.cpp"
|
||||||
|
"AgJetEffectServer.cpp"
|
||||||
|
"AgLaserSensorServer.cpp"
|
||||||
|
"AgMonumentBirds.cpp"
|
||||||
|
"AgMonumentLaserServer.cpp"
|
||||||
|
"AgMonumentRaceCancel.cpp"
|
||||||
|
"AgMonumentRaceGoal.cpp"
|
||||||
|
"AgPicnicBlanket.cpp"
|
||||||
|
"AgPropGuard.cpp"
|
||||||
|
"AgPropguards.cpp"
|
||||||
|
"AgQbElevator.cpp"
|
||||||
|
"AgSalutingNpcs.cpp"
|
||||||
|
"AgShipPlayerDeathTrigger.cpp"
|
||||||
|
"AgShipPlayerShockServer.cpp"
|
||||||
|
"AgSpaceStuff.cpp"
|
||||||
|
"AgStagePlatforms.cpp"
|
||||||
|
"AgStromlingProperty.cpp"
|
||||||
|
"AgSurvivalBuffStation.cpp"
|
||||||
|
"AgSurvivalMech.cpp"
|
||||||
|
"AgSurvivalSpiderling.cpp"
|
||||||
|
"AgSurvivalStromling.cpp"
|
||||||
|
"AgTurret.cpp"
|
||||||
|
"AllCrateChicken.cpp"
|
||||||
|
"AmBlueX.cpp"
|
||||||
|
"AmBridge.cpp"
|
||||||
|
"AmConsoleTeleportServer.cpp"
|
||||||
|
"AmDarklingDragon.cpp"
|
||||||
|
"AmDarklingMech.cpp"
|
||||||
|
"AmDrawBridge.cpp"
|
||||||
|
"AmDropshipComputer.cpp"
|
||||||
|
"AmScrollReaderServer.cpp"
|
||||||
|
"AmShieldGenerator.cpp"
|
||||||
|
"AmShieldGeneratorQuickbuild.cpp"
|
||||||
|
"AmSkeletonEngineer.cpp"
|
||||||
|
"AmSkullkinDrill.cpp"
|
||||||
|
"AmSkullkinDrillStand.cpp"
|
||||||
|
"AmSkullkinTower.cpp"
|
||||||
|
"AmTeapotServer.cpp"
|
||||||
|
"AmTemplateSkillVolume.cpp"
|
||||||
|
"AnvilOfArmor.cpp"
|
||||||
|
"BankInteractServer.cpp"
|
||||||
|
"BaseConsoleTeleportServer.cpp"
|
||||||
|
"BaseEnemyApe.cpp"
|
||||||
|
"BaseEnemyMech.cpp"
|
||||||
|
"BaseFootRaceManager.cpp"
|
||||||
|
"BaseInteractDropLootServer.cpp"
|
||||||
|
"BasePropertyServer.cpp"
|
||||||
|
"BaseRandomServer.cpp"
|
||||||
|
"BaseSurvivalServer.cpp"
|
||||||
|
"BaseWavesGenericEnemy.cpp"
|
||||||
|
"BaseWavesServer.cpp"
|
||||||
|
"Binoculars.cpp"
|
||||||
|
"BootyDigServer.cpp"
|
||||||
|
"BossSpiderQueenEnemyServer.cpp"
|
||||||
|
"BuccaneerValiantShip.cpp"
|
||||||
|
"BurningTile.cpp"
|
||||||
|
"CatapultBaseServer.cpp"
|
||||||
|
"CatapultBouncerServer.cpp"
|
||||||
|
"CauldronOfLife.cpp"
|
||||||
|
"CavePrisonCage.cpp"
|
||||||
|
"ChooseYourDestinationNsToNt.cpp"
|
||||||
|
"ClRing.cpp"
|
||||||
|
"CppScripts.cpp"
|
||||||
|
"CrabServer.cpp"
|
||||||
|
"DamagingPets.cpp"
|
||||||
|
"Darkitect.cpp"
|
||||||
|
"DLUVanityNPC.cpp"
|
||||||
|
"EnemyNjBuff.cpp"
|
||||||
|
"EnemyRoninSpawner.cpp"
|
||||||
|
"EnemySkeletonSpawner.cpp"
|
||||||
|
"EnemySpiderSpawner.cpp"
|
||||||
|
"ExplodingAsset.cpp"
|
||||||
|
"FallingTile.cpp"
|
||||||
|
"FireFirstSkillonStartup.cpp"
|
||||||
|
"FlameJetServer.cpp"
|
||||||
|
"ForceVolumeServer.cpp"
|
||||||
|
"FountainOfImagination.cpp"
|
||||||
|
"FvBounceOverWall.cpp"
|
||||||
|
"FvBrickPuzzleServer.cpp"
|
||||||
|
"FvCandle.cpp"
|
||||||
|
"FvConsoleLeftQuickbuild.cpp"
|
||||||
|
"FvConsoleRightQuickbuild.cpp"
|
||||||
|
"FvDragonSmashingGolemQb.cpp"
|
||||||
|
"FvFacilityBrick.cpp"
|
||||||
|
"FvFlyingCreviceDragon.cpp"
|
||||||
|
"FvFong.cpp"
|
||||||
|
"FvFreeGfNinjas.cpp"
|
||||||
|
"FvHorsemenTrigger.cpp"
|
||||||
|
"FvMaelstromCavalry.cpp"
|
||||||
|
"FvMaelstromDragon.cpp"
|
||||||
|
"FvNinjaGuard.cpp"
|
||||||
|
"FvPandaServer.cpp"
|
||||||
|
"FvPandaSpawnerServer.cpp"
|
||||||
|
"FvPassThroughWall.cpp"
|
||||||
|
"FvRaceSmashEggImagineServer.cpp"
|
||||||
|
"GfApeSmashingQB.cpp"
|
||||||
|
"GfBanana.cpp"
|
||||||
|
"GfBananaCluster.cpp"
|
||||||
|
"GfCampfire.cpp"
|
||||||
|
"GfCaptainsCannon.cpp"
|
||||||
|
"GfJailkeepMission.cpp"
|
||||||
|
"GfJailWalls.cpp"
|
||||||
|
"GfOrgan.cpp"
|
||||||
|
"GfTikiTorch.cpp"
|
||||||
|
"GrowingFlower.cpp"
|
||||||
|
"HydrantBroken.cpp"
|
||||||
|
"HydrantSmashable.cpp"
|
||||||
|
"ImaginationBackpackHealServer.cpp"
|
||||||
|
"ImaginationShrineServer.cpp"
|
||||||
|
"ImgBrickConsoleQB.cpp"
|
||||||
|
"InstanceExitTransferPlayerToLastNonInstance.cpp"
|
||||||
|
"InvalidScript.cpp"
|
||||||
|
"LegoDieRoll.cpp"
|
||||||
|
"Lieutenant.cpp"
|
||||||
|
"MaestromExtracticatorServer.cpp"
|
||||||
|
"MailBoxServer.cpp"
|
||||||
|
"MastTeleport.cpp"
|
||||||
|
"MinigameTreasureChestServer.cpp"
|
||||||
|
"MonCoreNookDoors.cpp"
|
||||||
|
"MonCoreSmashableDoors.cpp"
|
||||||
|
"NjColeNPC.cpp"
|
||||||
|
"NjDragonEmblemChestServer.cpp"
|
||||||
|
"NjEarthDragonPetServer.cpp"
|
||||||
|
"NjEarthPetServer.cpp"
|
||||||
|
"NjGarmadonCelebration.cpp"
|
||||||
|
"NjhubLavaPlayerDeathTrigger.cpp"
|
||||||
|
"NjIceRailActivator.cpp"
|
||||||
|
"NjJayMissionItems.cpp"
|
||||||
|
"NjMonastryBossInstance.cpp"
|
||||||
|
"NjNPCMissionSpinjitzuServer.cpp"
|
||||||
|
"NjNyaMissionitems.cpp"
|
||||||
|
"NjRailActivatorsServer.cpp"
|
||||||
|
"NjRailPostServer.cpp"
|
||||||
|
"NjRailSwitch.cpp"
|
||||||
|
"NjScrollChestServer.cpp"
|
||||||
|
"NjWuNPC.cpp"
|
||||||
|
"NPCAddRemoveItem.cpp"
|
||||||
|
"NpcAgCourseStarter.cpp"
|
||||||
|
"NpcCowboyServer.cpp"
|
||||||
|
"NpcEpsilonServer.cpp"
|
||||||
|
"NpcNjAssistantServer.cpp"
|
||||||
|
"NpcNpSpacemanBob.cpp"
|
||||||
|
"NpcPirateServer.cpp"
|
||||||
|
"NpcWispServer.cpp"
|
||||||
|
"NsConcertChoiceBuild.cpp"
|
||||||
|
"NsConcertChoiceBuildManager.cpp"
|
||||||
|
"NsConcertInstrument.cpp"
|
||||||
|
"NsConcertQuickBuild.cpp"
|
||||||
|
"NsGetFactionMissionServer.cpp"
|
||||||
|
"NsJohnnyMissionServer.cpp"
|
||||||
|
"NsLegoClubDoor.cpp"
|
||||||
|
"NsLupTeleport.cpp"
|
||||||
|
"NsModularBuild.cpp"
|
||||||
|
"NsQbImaginationStatue.cpp"
|
||||||
|
"NsTokenConsoleServer.cpp"
|
||||||
|
"NtAssemblyTubeServer.cpp"
|
||||||
|
"NtBeamImaginationCollectors.cpp"
|
||||||
|
"NtCombatChallengeDummy.cpp"
|
||||||
|
"NtCombatChallengeExplodingDummy.cpp"
|
||||||
|
"NtCombatChallengeServer.cpp"
|
||||||
|
"NtConsoleTeleportServer.cpp"
|
||||||
|
"NtDarkitectRevealServer.cpp"
|
||||||
|
"NtDirtCloudServer.cpp"
|
||||||
|
"NtDukeServer.cpp"
|
||||||
|
"NtFactionSpyServer.cpp"
|
||||||
|
"NtHaelServer.cpp"
|
||||||
|
"NtImagBeamBuffer.cpp"
|
||||||
|
"NtOverbuildServer.cpp"
|
||||||
|
"NtParadoxPanelServer.cpp"
|
||||||
|
"NtParadoxTeleServer.cpp"
|
||||||
|
"NtSentinelWalkwayServer.cpp"
|
||||||
|
"NtSleepingGuard.cpp"
|
||||||
|
"NtVandaServer.cpp"
|
||||||
|
"NtVentureCannonServer.cpp"
|
||||||
|
"NtVentureSpeedPadServer.cpp"
|
||||||
|
"NtXRayServer.cpp"
|
||||||
|
"PersonalFortress.cpp"
|
||||||
|
"PetDigBuild.cpp"
|
||||||
|
"PetDigServer.cpp"
|
||||||
|
"PetFromDigServer.cpp"
|
||||||
|
"PetFromObjectServer.cpp"
|
||||||
|
"PropertyBankInteract.cpp"
|
||||||
|
"PropertyDeathPlane.cpp"
|
||||||
|
"PropertyDevice.cpp"
|
||||||
|
"PropertyFXDamage.cpp"
|
||||||
|
"PropertyPlatform.cpp"
|
||||||
|
"PrSeagullFly.cpp"
|
||||||
|
"PrWhistle.cpp"
|
||||||
|
"QbEnemyStunner.cpp"
|
||||||
|
"RaceImagineCrateServer.cpp"
|
||||||
|
"RaceImaginePowerup.cpp"
|
||||||
|
"RaceMaelstromGeiser.cpp"
|
||||||
|
"RaceSmashServer.cpp"
|
||||||
|
"RainOfArrows.cpp"
|
||||||
|
"RandomSpawnerFin.cpp"
|
||||||
|
"RandomSpawnerPit.cpp"
|
||||||
|
"RandomSpawnerStr.cpp"
|
||||||
|
"RandomSpawnerZip.cpp"
|
||||||
|
"RemoveRentalGear.cpp"
|
||||||
|
"RockHydrantBroken.cpp"
|
||||||
|
"RockHydrantSmashable.cpp"
|
||||||
|
"ScriptComponent.cpp"
|
||||||
|
"ScriptedPowerupSpawner.cpp"
|
||||||
|
"SGCannon.cpp"
|
||||||
|
"SpawnGryphonServer.cpp"
|
||||||
|
"SpawnLionServer.cpp"
|
||||||
|
"SpawnPetBaseServer.cpp"
|
||||||
|
"SpawnSaberCatServer.cpp"
|
||||||
|
"SpawnShrakeServer.cpp"
|
||||||
|
"SpawnStegoServer.cpp"
|
||||||
|
"SpecialImaginePowerupSpawner.cpp"
|
||||||
|
"SpiderBossTreasureChestServer.cpp"
|
||||||
|
"SsModularBuildServer.cpp"
|
||||||
|
"StinkyFishTarget.cpp"
|
||||||
|
"StoryBoxInteractServer.cpp"
|
||||||
|
"Sunflower.cpp"
|
||||||
|
"TokenConsoleServer.cpp"
|
||||||
|
"TouchMissionUpdateServer.cpp"
|
||||||
|
"TreasureChestDragonServer.cpp"
|
||||||
|
"TriggerAmbush.cpp"
|
||||||
|
"VeBricksampleServer.cpp"
|
||||||
|
"VeEpsilonServer.cpp"
|
||||||
|
"VeMech.cpp"
|
||||||
|
"VeMissionConsole.cpp"
|
||||||
|
"WaveBossApe.cpp"
|
||||||
|
"WaveBossHammerling.cpp"
|
||||||
|
"WaveBossHorsemen.cpp"
|
||||||
|
"WaveBossSpiderling.cpp"
|
||||||
|
"WhFans.cpp"
|
||||||
|
"WildAmbients.cpp"
|
||||||
|
"WishingWellServer.cpp"
|
||||||
|
"ZoneAgMedProperty.cpp"
|
||||||
|
"ZoneAgProperty.cpp"
|
||||||
|
"ZoneAgSpiderQueen.cpp"
|
||||||
|
"ZoneAgSurvival.cpp"
|
||||||
|
"ZoneFvProperty.cpp"
|
||||||
|
"ZoneGfProperty.cpp"
|
||||||
|
"ZoneNsMedProperty.cpp"
|
||||||
|
"ZoneNsProperty.cpp"
|
||||||
|
"ZoneNsWaves.cpp"
|
||||||
|
"ZoneSGServer.cpp" PARENT_SCOPE)
|
6
dWorldServer/CMakeLists.txt
Normal file
6
dWorldServer/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
set(DWORLDSERVER_SOURCES "ObjectIDManager.cpp"
|
||||||
|
"PerformanceManager.cpp"
|
||||||
|
"WorldServer.cpp")
|
||||||
|
|
||||||
|
add_executable(WorldServer ${DWORLDSERVER_SOURCES})
|
||||||
|
target_link_libraries(WorldServer ${COMMON_LIBRARIES} dChatFilter dGame dZoneManager dPhysics detour recast tinyxml2)
|
@ -546,18 +546,31 @@ void HandlePacketChat(Packet* packet) {
|
|||||||
LWOOBJID header;
|
LWOOBJID header;
|
||||||
inStream.Read(header);
|
inStream.Read(header);
|
||||||
|
|
||||||
RakNet::RakString title;
|
std::string title;
|
||||||
RakNet::RakString msg;
|
std::string msg;
|
||||||
|
|
||||||
inStream.Read(title);
|
uint32_t len;
|
||||||
inStream.Read(msg);
|
inStream.Read<uint32_t>(len);
|
||||||
|
for (int i = 0; len > i; i++) {
|
||||||
|
char character;
|
||||||
|
inStream.Read<char>(character);
|
||||||
|
title += character;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
inStream.Read<uint32_t>(len);
|
||||||
|
for (int i = 0; len > i; i++) {
|
||||||
|
char character;
|
||||||
|
inStream.Read<char>(character);
|
||||||
|
msg += character;
|
||||||
|
}
|
||||||
|
|
||||||
//Send to our clients:
|
//Send to our clients:
|
||||||
AMFArrayValue args;
|
AMFArrayValue args;
|
||||||
auto* titleValue = new AMFStringValue();
|
auto* titleValue = new AMFStringValue();
|
||||||
titleValue->SetStringValue(title.C_String());
|
titleValue->SetStringValue(title.c_str());
|
||||||
auto* messageValue = new AMFStringValue();
|
auto* messageValue = new AMFStringValue();
|
||||||
messageValue->SetStringValue(msg.C_String());
|
messageValue->SetStringValue(msg.c_str());
|
||||||
|
|
||||||
args.InsertValue("title", titleValue);
|
args.InsertValue("title", titleValue);
|
||||||
args.InsertValue("message", messageValue);
|
args.InsertValue("message", messageValue);
|
||||||
@ -669,10 +682,12 @@ void HandlePacket(Packet* packet) {
|
|||||||
Game::logger->Log("WorldServer", "Deleting player %llu\n", entity->GetObjectID());
|
Game::logger->Log("WorldServer", "Deleting player %llu\n", entity->GetObjectID());
|
||||||
|
|
||||||
EntityManager::Instance()->DestroyEntity(entity);
|
EntityManager::Instance()->DestroyEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION);
|
||||||
bitStream.Write(c->GetObjectID());
|
bitStream.Write(user->GetLoggedInChar());
|
||||||
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,19 +817,27 @@ void HandlePacket(Packet* packet) {
|
|||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
uint64_t header = inStream.Read(header);
|
uint64_t header = inStream.Read(header);
|
||||||
uint32_t sessionKey = inStream.Read(sessionKey);
|
uint32_t sessionKey = inStream.Read(sessionKey);
|
||||||
RakNet::RakString username;
|
|
||||||
inStream.Read(username);
|
std::string username;
|
||||||
|
|
||||||
|
uint32_t len;
|
||||||
|
inStream.Read(len);
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
char character; inStream.Read<char>(character);
|
||||||
|
username += character;
|
||||||
|
}
|
||||||
|
|
||||||
//Find them:
|
//Find them:
|
||||||
User* user = UserManager::Instance()->GetUser(username.C_String());
|
User* user = UserManager::Instance()->GetUser(username.c_str());
|
||||||
if (!user) {
|
if (!user) {
|
||||||
Game::logger->Log("WorldServer", "Got new session alert for user %s, but they're not logged in.\n", username.C_String());
|
Game::logger->Log("WorldServer", "Got new session alert for user %s, but they're not logged in.\n", username.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check the key:
|
//Check the key:
|
||||||
if (sessionKey != std::atoi(user->GetSessionKey().c_str())) {
|
if (sessionKey != std::atoi(user->GetSessionKey().c_str())) {
|
||||||
Game::logger->Log("WorldServer", "Got new session alert for user %s, but the session key is invalid.\n", username.C_String());
|
Game::logger->Log("WorldServer", "Got new session alert for user %s, but the session key is invalid.\n", username.c_str());
|
||||||
Game::server->Disconnect(user->GetSystemAddress(), SERVER_DISCON_INVALID_SESSION_KEY);
|
Game::server->Disconnect(user->GetSystemAddress(), SERVER_DISCON_INVALID_SESSION_KEY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -930,6 +953,19 @@ void HandlePacket(Packet* packet) {
|
|||||||
playerID = GeneralUtils::ClearBit(playerID, OBJECT_BIT_CHARACTER);
|
playerID = GeneralUtils::ClearBit(playerID, OBJECT_BIT_CHARACTER);
|
||||||
playerID = GeneralUtils::ClearBit(playerID, OBJECT_BIT_PERSISTENT);
|
playerID = GeneralUtils::ClearBit(playerID, OBJECT_BIT_PERSISTENT);
|
||||||
|
|
||||||
|
auto user = UserManager::Instance()->GetUser(packet->systemAddress);
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
auto lastCharacter = user->GetLoggedInChar();
|
||||||
|
// This means we swapped characters and we need to remove the previous player from the container.
|
||||||
|
if (static_cast<uint32_t>(lastCharacter) != playerID) {
|
||||||
|
CBITSTREAM;
|
||||||
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION);
|
||||||
|
bitStream.Write(lastCharacter);
|
||||||
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UserManager::Instance()->LoginCharacter(packet->systemAddress, static_cast<uint32_t>(playerID));
|
UserManager::Instance()->LoginCharacter(packet->systemAddress, static_cast<uint32_t>(playerID));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1107,14 +1143,12 @@ void HandlePacket(Packet* packet) {
|
|||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_ADDED_NOTIFICATION);
|
PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_PLAYER_ADDED_NOTIFICATION);
|
||||||
bitStream.Write(player->GetObjectID());
|
bitStream.Write(player->GetObjectID());
|
||||||
bitStream.Write<uint16_t>(playerName.size());
|
bitStream.Write<uint32_t>(playerName.size());
|
||||||
for (size_t i = 0; i < playerName.size(); i++)
|
for (size_t i = 0; i < playerName.size(); i++)
|
||||||
{
|
{
|
||||||
bitStream.Write(playerName[i]);
|
bitStream.Write(playerName[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//bitStream.Write(playerName);
|
|
||||||
|
|
||||||
auto zone = dZoneManager::Instance()->GetZone()->GetZoneID();
|
auto zone = dZoneManager::Instance()->GetZone()->GetZoneID();
|
||||||
bitStream.Write(zone.GetMapID());
|
bitStream.Write(zone.GetMapID());
|
||||||
bitStream.Write(zone.GetInstanceID());
|
bitStream.Write(zone.GetInstanceID());
|
||||||
|
6
dZoneManager/CMakeLists.txt
Normal file
6
dZoneManager/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
set(DZONEMANAGER_SOURCES "dZoneManager.cpp"
|
||||||
|
"Level.cpp"
|
||||||
|
"Spawner.cpp"
|
||||||
|
"Zone.cpp")
|
||||||
|
|
||||||
|
add_library(dZoneManager STATIC ${DZONEMANAGER_SOURCES})
|
@ -1,2 +1 @@
|
|||||||
-- File added April 9th, 2022
|
|
||||||
UPDATE ItemComponent SET itemType = 5 where id = 7082;
|
UPDATE ItemComponent SET itemType = 5 where id = 7082;
|
||||||
|
@ -1 +1 @@
|
|||||||
ALTER TABLE bug_reports ADD reporter_id INT NOT NULL DEFAULT 0;
|
ALTER TABLE bug_reports ADD (reporter_id) INT NOT NULL DEFAULT 0;
|
||||||
|
1
migrations/dlu/4_friends_list_objectids.sql
Normal file
1
migrations/dlu/4_friends_list_objectids.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
UPDATE friends SET player_id = player_id % 0x100000000, friend_id = friend_id % 0x100000000;
|
@ -60,3 +60,7 @@ classic_survival_scoring=0
|
|||||||
|
|
||||||
# If this value is 1, pets will consume imagination as they did in live. if 0 they will not consume imagination at all.
|
# If this value is 1, pets will consume imagination as they did in live. if 0 they will not consume imagination at all.
|
||||||
pets_take_imagination=1
|
pets_take_imagination=1
|
||||||
|
|
||||||
|
# If you would like to increase the maximum number of best friends a player can have on the server
|
||||||
|
# Change the value below to what you would like this to be (5 is live accurate)
|
||||||
|
max_number_of_best_friends=5
|
@ -7,11 +7,7 @@ create_test_sourcelist (Tests
|
|||||||
|
|
||||||
# add the executable
|
# add the executable
|
||||||
add_executable (CommonCxxTests ${Tests})
|
add_executable (CommonCxxTests ${Tests})
|
||||||
target_link_libraries(CommonCxxTests dCommon raknet)
|
target_link_libraries(CommonCxxTests ${COMMON_LIBRARIES})
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
target_link_libraries(CommonCxxTests ws2_32)
|
|
||||||
endif(WIN32)
|
|
||||||
|
|
||||||
# remove the test driver source file
|
# remove the test driver source file
|
||||||
set (TestsToRun ${Tests})
|
set (TestsToRun ${Tests})
|
||||||
|
102
thirdparty/CMakeLists.txt
vendored
102
thirdparty/CMakeLists.txt
vendored
@ -1,50 +1,50 @@
|
|||||||
# Source Code for raknet
|
# Source Code for raknet
|
||||||
file(
|
file(
|
||||||
GLOB SOURCES_RAKNET
|
GLOB SOURCES_RAKNET
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/raknet/Source/*.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/raknet/Source/*.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Source Code for recast
|
# Source Code for recast
|
||||||
file(
|
file(
|
||||||
GLOB SOURCES_RECAST
|
GLOB SOURCES_RECAST
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Recast/Source/*.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Recast/Source/*.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Source Code for detour
|
# Source Code for detour
|
||||||
file(
|
file(
|
||||||
GLOB SOURCES_DETOUR
|
GLOB SOURCES_DETOUR
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Detour/Source/*.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Detour/Source/*.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Source Code for tinyxml2
|
# Source Code for tinyxml2
|
||||||
file(
|
file(
|
||||||
GLOB SOURCES_TINYXML2
|
GLOB SOURCES_TINYXML2
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tinyxml2/tinyxml2.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tinyxml2/tinyxml2.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Source Code for libbcrypt
|
# Source Code for libbcrypt
|
||||||
file(
|
file(
|
||||||
GLOB SOURCES_LIBBCRYPT
|
GLOB SOURCES_LIBBCRYPT
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/*.c
|
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/*.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/src/*.c
|
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/src/*.c
|
||||||
)
|
)
|
||||||
|
|
||||||
file(
|
file(
|
||||||
GLOB SOURCES_SQLITE3
|
GLOB SOURCES_SQLITE3
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.c
|
${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# mariadb connector cpp
|
# mariadb connector cpp
|
||||||
@ -147,7 +147,6 @@ else() # Build from source
|
|||||||
set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/RelWithDebInfo/${MARIADB_SHARED_LIBRARY_NAME}")
|
set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/RelWithDebInfo/${MARIADB_SHARED_LIBRARY_NAME}")
|
||||||
set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}/$<CONFIG>")
|
set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}/$<CONFIG>")
|
||||||
set(MARIADB_PLUGINS_LOCATION "${BINARY_DIR}/libmariadb/RelWithDebInfo")
|
set(MARIADB_PLUGINS_LOCATION "${BINARY_DIR}/libmariadb/RelWithDebInfo")
|
||||||
message(STATUS "1 ${CMAKE_SOURCE_DIR}")
|
|
||||||
else()
|
else()
|
||||||
set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/${MARIADB_SHARED_LIBRARY_NAME}")
|
set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/${MARIADB_SHARED_LIBRARY_NAME}")
|
||||||
set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}")
|
set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}")
|
||||||
@ -179,16 +178,19 @@ if(EXISTS "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/test/CMakeLists.
|
|||||||
file(REMOVE "${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
|
||||||
add_library(mariadbConnCpp SHARED IMPORTED GLOBAL)
|
add_library(mariadbConnCpp SHARED IMPORTED GLOBAL)
|
||||||
set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_LOCATION ${MARIADB_SHARED_LIBRARY_LOCATION})
|
set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_LOCATION ${MARIADB_SHARED_LIBRARY_LOCATION})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_IMPLIB ${MARIADB_IMPLIB_LOCATION})
|
set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_IMPLIB ${MARIADB_IMPLIB_LOCATION})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Add directories to include lists
|
||||||
target_include_directories(mariadbConnCpp INTERFACE ${MARIADB_INCLUDE_DIR})
|
target_include_directories(mariadbConnCpp INTERFACE ${MARIADB_INCLUDE_DIR})
|
||||||
add_dependencies(mariadbConnCpp mariadb_connector_cpp)
|
add_dependencies(mariadbConnCpp mariadb_connector_cpp)
|
||||||
|
|
||||||
# 3rdparty static libraries:
|
# Create our third party library objects
|
||||||
#add_library(zlib ${SOURCES_ZLIB})
|
|
||||||
add_library(raknet ${SOURCES_RAKNET})
|
add_library(raknet ${SOURCES_RAKNET})
|
||||||
add_library(tinyxml2 ${SOURCES_TINYXML2})
|
add_library(tinyxml2 ${SOURCES_TINYXML2})
|
||||||
add_library(detour ${SOURCES_DETOUR})
|
add_library(detour ${SOURCES_DETOUR})
|
||||||
@ -196,11 +198,39 @@ add_library(recast ${SOURCES_RECAST})
|
|||||||
add_library(libbcrypt ${SOURCES_LIBBCRYPT})
|
add_library(libbcrypt ${SOURCES_LIBBCRYPT})
|
||||||
add_library(sqlite3 ${SOURCES_SQLITE3})
|
add_library(sqlite3 ${SOURCES_SQLITE3})
|
||||||
|
|
||||||
if(UNIX)
|
if(WIN32)
|
||||||
target_link_libraries(sqlite3 pthread dl m)
|
# Link Win Sockets 2 to RakNet
|
||||||
|
target_link_libraries(raknet ws2_32)
|
||||||
|
elseif(UNIX)
|
||||||
|
# Add warning disable flags and link Unix libraries to sqlite3
|
||||||
|
target_link_libraries(sqlite3 pthread dl m)
|
||||||
|
|
||||||
# -Wno-unused-result -Wno-unknown-pragmas -fpermissive
|
# -Wno-unused-result -Wno-unknown-pragmas -fpermissive
|
||||||
target_compile_options(sqlite3 PRIVATE "-Wno-return-local-addr" "-Wno-maybe-uninitialized")
|
target_compile_options(sqlite3 PRIVATE "-Wno-return-local-addr" "-Wno-maybe-uninitialized")
|
||||||
target_compile_options(raknet PRIVATE "-Wno-write-strings" "-Wformat-overflow=0" "-Wformat=0")
|
target_compile_options(raknet PRIVATE "-Wno-write-strings" "-Wformat-overflow=0" "-Wformat=0")
|
||||||
target_compile_options(libbcrypt PRIVATE "-Wno-implicit-function-declaration" "-Wno-int-conversion")
|
target_compile_options(libbcrypt PRIVATE "-Wno-implicit-function-declaration" "-Wno-int-conversion")
|
||||||
endif(UNIX)
|
endif()
|
||||||
|
|
||||||
|
# Download Backtrace if configured
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
include(FetchContent)
|
||||||
|
if (__include_backtrace__ AND __compile_backtrace__)
|
||||||
|
FetchContent_Declare(
|
||||||
|
backtrace
|
||||||
|
GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace.git
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(backtrace)
|
||||||
|
|
||||||
|
if (NOT EXISTS ${backtrace_SOURCE_DIR}/.libs)
|
||||||
|
set(backtrace_make_cmd "${backtrace_SOURCE_DIR}/configure --prefix=\"/usr\" --enable-shared --with-system-libunwind")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND bash -c "cd ${backtrace_SOURCE_DIR} && ${backtrace_make_cmd} && make && cd ${CMAKE_SOURCE_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
link_directories(${backtrace_SOURCE_DIR}/.libs/)
|
||||||
|
include_directories(${backtrace_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
2
thirdparty/cpplinq/cpplinq.hpp
vendored
2
thirdparty/cpplinq/cpplinq.hpp
vendored
@ -14,6 +14,8 @@
|
|||||||
#ifndef CPPLINQ__HEADER_GUARD
|
#ifndef CPPLINQ__HEADER_GUARD
|
||||||
# define CPPLINQ__HEADER_GUARD
|
# define CPPLINQ__HEADER_GUARD
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user