mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 03:37:08 -06:00
Compare commits
174 Commits
automation
...
fixDestCom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8a4da0679 | ||
|
|
623da4bed9 | ||
|
|
50921cce2d | ||
|
|
3806891db0 | ||
|
|
ba91058736 | ||
|
|
73e70badb7 | ||
|
|
e4cae35edb | ||
|
|
c6087ce77a | ||
|
|
e96fd56fbd | ||
|
|
500ae4d6e5 | ||
|
|
094797881b | ||
|
|
3dd2791066 | ||
| 570c597148 | |||
|
|
ad003634f4 | ||
| d8ac148cee | |||
|
|
471d65707c | ||
|
|
94f8a99fba | ||
|
|
288991ef49 | ||
|
|
74cc4176e1 | ||
| b33e9935f5 | |||
|
|
258ee5c1ee | ||
|
|
a8820c14f2 | ||
| 1ec8da8bf7 | |||
|
|
b24775f472 | ||
|
|
bd65fc6e33 | ||
|
|
44f466ac72 | ||
|
|
51540568fb | ||
| 08020cd86d | |||
| ca78a166d9 | |||
| 2e386d29df | |||
| d893ecddeb | |||
|
|
f4f13e081a | ||
|
|
c26086aff5 | ||
|
|
0337449aa7 | ||
|
|
598f4e1663 | ||
|
|
5eca25e42a | ||
|
|
d233c7e2aa | ||
| beaceb947b | |||
|
|
2cc13c6499 | ||
|
|
ad81e341da | ||
|
|
fe6be21008 | ||
| cefdfc696a | |||
| 7e2747a2d2 | |||
| a29253d2f0 | |||
|
|
e5b69745aa | ||
|
|
040a78c386 | ||
|
|
d8a5fd49a4 | ||
|
|
208ed02158 | ||
| 952786c166 | |||
|
|
9a07020a51 | ||
| a22ecf385f | |||
| c2b4aa4026 | |||
|
|
0d48cfe8c0 | ||
| e299bf9b62 | |||
|
|
304af7922a | ||
|
|
0610fe99f8 | ||
|
|
d1316cfc9f | ||
| bd5ead40f6 | |||
|
|
c791d1a237 | ||
|
|
54454973a1 | ||
|
|
b87537c637 | ||
|
|
a625d2eae5 | ||
|
|
887e2a25f0 | ||
|
|
34392932b3 | ||
|
|
cc251d0986 | ||
|
|
0c0f7216a1 | ||
|
|
342da56678 | ||
|
|
11b0097488 | ||
|
|
3e3148e910 | ||
|
|
080a833144 | ||
|
|
455f9470a5 | ||
| 9375c36c7b | |||
|
|
5cc7479f29 | ||
|
|
c4135eac46 | ||
| 41898bef86 | |||
|
|
787dac7cd9 | ||
|
|
e32cec6691 | ||
|
|
85aa82b4b9 | ||
|
|
393733cc67 | ||
|
|
8156e5cc91 | ||
|
|
d0e79d19fc | ||
|
|
45256a0338 | ||
|
|
238fc98ea5 | ||
|
|
d340874284 | ||
|
|
fe23c7c5f7 | ||
|
|
132d31d3ab | ||
|
|
2d31b7e4bb | ||
|
|
f46bc33dd4 | ||
|
|
0d6bd33f9e | ||
| 1a74c028c2 | |||
|
|
2a0f63c0a1 | ||
|
|
12d7ab9034 | ||
|
|
c99e2a372b | ||
|
|
dab075fc39 | ||
|
|
b4aa5db305 | ||
|
|
259f0c8371 | ||
|
|
a5e63529dc | ||
|
|
c572f2a58d | ||
|
|
5bff441c01 | ||
|
|
96fc6e81d8 | ||
|
|
59d7121978 | ||
|
|
b589755655 | ||
|
|
8ae1e1bc6b | ||
|
|
9fabff16e4 | ||
|
|
8267823ca4 | ||
|
|
b8878da61b | ||
|
|
47deca6f4f | ||
|
|
8a1f275176 | ||
|
|
e1a7b4993e | ||
|
|
0ecc5d83c3 | ||
|
|
a43e03255c | ||
|
|
83da45575e | ||
|
|
f5f599764d | ||
|
|
7b1626901a | ||
|
|
a595347211 | ||
|
|
0107d05d55 | ||
|
|
f26e66da4d | ||
|
|
e47169fec5 | ||
|
|
238751f14e | ||
| 59387e5fe3 | |||
|
|
f9b52ad01c | ||
|
|
1f3df08730 | ||
| 9708ea28dc | |||
|
|
8a065ad074 | ||
|
|
2117a18d62 | ||
|
|
4fe335cc66 | ||
| 9d105a287d | |||
| 1af70161eb | |||
| 739eae5244 | |||
|
|
07803a7ca2 | ||
|
|
61ae619886 | ||
|
|
8a8006bee5 | ||
|
|
c5afd7d4a3 | ||
| a809f36548 | |||
| 0e01948414 | |||
| 6e6a05fc1d | |||
| 5af5b0f1c1 | |||
| bf0ae6f181 | |||
| b1cd2776fa | |||
|
|
af1abe9e74 | ||
|
|
4dba8d9225 | ||
|
|
3448426caf | ||
|
|
7a067e7b48 | ||
|
|
411c9eaf1f | ||
|
|
fcf5c5ea8a | ||
|
|
6c2312fe87 | ||
|
|
d98ad4b94f | ||
|
|
5c086909ed | ||
|
|
1c7ac93d4b | ||
|
|
0f307ac4be | ||
|
|
bc518be654 | ||
|
|
820b375c50 | ||
|
|
3b8f18d2be | ||
|
|
0faef7d791 | ||
|
|
28a0492201 | ||
|
|
2ab995b9c3 | ||
|
|
8de528e77c | ||
|
|
a3626a3b53 | ||
|
|
b5e3bd22e3 | ||
|
|
48264e2cf4 | ||
|
|
10a2c24d5e | ||
|
|
89f427ace0 | ||
|
|
08220d6852 | ||
|
|
42870028e4 | ||
|
|
fcb088d263 | ||
|
|
ed2639ce4e | ||
|
|
41355cea58 | ||
|
|
c91f0d16b3 | ||
|
|
c02963013b | ||
|
|
308d56968a | ||
|
|
47445ada54 | ||
|
|
426bc963fe | ||
|
|
1e4e1b914c | ||
|
|
b432a3f5da |
@@ -14,4 +14,4 @@ EXTERNAL_IP=localhost
|
|||||||
MARIADB_USER=darkflame
|
MARIADB_USER=darkflame
|
||||||
MARIADB_PASSWORD=SECRET_VALUE_CHANGE_ME
|
MARIADB_PASSWORD=SECRET_VALUE_CHANGE_ME
|
||||||
MARIADB_ROOT_PASSWORD=SECRET_VALUE_CHANGE_ME
|
MARIADB_ROOT_PASSWORD=SECRET_VALUE_CHANGE_ME
|
||||||
MARIADB_DATABASE=darkflame
|
MARIADB_DATABASE=darkflame
|
||||||
|
|||||||
4
.github/workflows/build-and-test.yml
vendored
4
.github/workflows/build-and-test.yml
vendored
@@ -2,9 +2,9 @@ name: CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main, automation ]
|
branches: [ main ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main, automation ]
|
branches: [ main ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-test:
|
build-and-test:
|
||||||
|
|||||||
116
.github/workflows/publishing.yml
vendored
116
.github/workflows/publishing.yml
vendored
@@ -1,116 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- versions.txt
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-test:
|
|
||||||
name: Build & Test (${{ matrix.os }})
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
continue-on-error: true
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ windows-2022, ubuntu-20.04, macos-11 ]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- name: Add msbuild to PATH (Windows only)
|
|
||||||
if: ${{ matrix.os == 'windows-2022' }}
|
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
|
||||||
with:
|
|
||||||
vs-version: '[17,18)'
|
|
||||||
msbuild-architecture: x64
|
|
||||||
- name: Install libssl (Mac Only)
|
|
||||||
if: ${{ matrix.os == 'macos-11' }}
|
|
||||||
run: brew install openssl@3
|
|
||||||
- name: cmake
|
|
||||||
uses: lukka/run-cmake@v10
|
|
||||||
with:
|
|
||||||
configurePreset: "ci-${{matrix.os}}"
|
|
||||||
buildPreset: "ci-${{matrix.os}}"
|
|
||||||
testPreset: "ci-${{matrix.os}}"
|
|
||||||
- name: artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: build-${{matrix.os}}
|
|
||||||
path: |
|
|
||||||
build/*Server*
|
|
||||||
build/*.ini
|
|
||||||
build/*.so
|
|
||||||
build/*.dll
|
|
||||||
build/vanity/
|
|
||||||
build/navmeshes/
|
|
||||||
build/migrations/
|
|
||||||
build/*.dcf
|
|
||||||
!build/*.pdb
|
|
||||||
!build/d*/
|
|
||||||
|
|
||||||
draft-release:
|
|
||||||
needs: build-and-test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Get Previous Tag
|
|
||||||
id: previoustag
|
|
||||||
uses: "WyriHaximus/github-action-get-previous-tag@v1"
|
|
||||||
with:
|
|
||||||
fallback: v1.0
|
|
||||||
|
|
||||||
- name: Generate Changelog
|
|
||||||
uses: Bullrich/generate-release-changelog@master
|
|
||||||
id: changelog
|
|
||||||
env:
|
|
||||||
REPO: ${{ github.repository }}
|
|
||||||
with:
|
|
||||||
from-tag: ${{ steps.previoustag.outputs.tag }}
|
|
||||||
to-tag: HEAD
|
|
||||||
|
|
||||||
|
|
||||||
- name: Take a gander at versions.txt to get updated information
|
|
||||||
run: |
|
|
||||||
IFS=" - " read -ra PARTS <<< "$(head -n 1 versions.txt)"
|
|
||||||
echo "VERSION=${PARTS[0]}" >> $GITHUB_ENV
|
|
||||||
echo "DESCRIPTION=$(IFS=' '; echo "${PARTS[*]:1}")" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Create Release
|
|
||||||
id: create_release
|
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
tag_name: v${{ env.VERSION }}
|
|
||||||
release_name: Release v${{ env.VERSION }}
|
|
||||||
body: "Draft release for version v${{ env.VERSION }} \n\n ${{ env.DESCRIPTION }} \n\n ${{ steps.changelog.outputs.changelog }}"
|
|
||||||
draft: true
|
|
||||||
|
|
||||||
- name: Download all workflow run artifacts
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
path: artifacts
|
|
||||||
|
|
||||||
- name: Upload Release Assets
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
cd artifacts
|
|
||||||
for folder in */; do
|
|
||||||
zip -r "${folder%/}.zip" "$folder"
|
|
||||||
done
|
|
||||||
ls
|
|
||||||
for file in *.zip; do
|
|
||||||
echo "Uploading $file"
|
|
||||||
curl --progress-bar \
|
|
||||||
-X POST \
|
|
||||||
-H "Accept: application/vnd.github+json" \
|
|
||||||
-H "Authorization: token ${{ env.GITHUB_TOKEN }}" \
|
|
||||||
--upload-file "$file" \
|
|
||||||
-H "Content-Type: $(file --mime-type -b $file)" \
|
|
||||||
"https://uploads.github.com/repos/${{ github.repository }}/releases/${{ steps.create_release.outputs.id }}/assets?name=$(basename $file)"
|
|
||||||
done
|
|
||||||
@@ -97,15 +97,56 @@ make_directory(${CMAKE_BINARY_DIR}/logs)
|
|||||||
|
|
||||||
# Copy resource files on first build
|
# Copy resource files on first build
|
||||||
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
||||||
foreach(resource_file ${RESOURCE_FILES})
|
message(STATUS "Checking resource file integrity")
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
foreach (resource_file ${RESOURCE_FILES})
|
||||||
|
set(file_size 0)
|
||||||
|
if (EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
||||||
|
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
|
||||||
|
endif()
|
||||||
|
if (${file_size} EQUAL 0)
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
message("Moved ${resource_file} to project binary directory")
|
message(STATUS "Moved " ${resource_file} " to project binary directory")
|
||||||
|
elseif (resource_file MATCHES ".ini")
|
||||||
|
message(STATUS "Checking " ${resource_file} " for missing config options")
|
||||||
|
file(READ ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
|
||||||
|
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
|
||||||
|
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
|
||||||
|
set(parsed_current_file_contents "")
|
||||||
|
# Remove comment lines so they do not interfere with the variable parsing
|
||||||
|
foreach (line ${current_file_contents})
|
||||||
|
string(FIND ${line} "#" is_comment)
|
||||||
|
if (NOT ${is_comment} EQUAL 0)
|
||||||
|
string(APPEND parsed_current_file_contents ${line})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
file(READ ${CMAKE_SOURCE_DIR}/resources/${resource_file} depot_file_contents)
|
||||||
|
string(REPLACE "\\\n" "" depot_file_contents ${depot_file_contents})
|
||||||
|
string(REPLACE "\n" ";" depot_file_contents ${depot_file_contents})
|
||||||
|
set(line_to_add "")
|
||||||
|
foreach (line ${depot_file_contents})
|
||||||
|
string(FIND ${line} "#" is_comment)
|
||||||
|
if (NOT ${is_comment} EQUAL 0)
|
||||||
|
string(REPLACE "=" ";" line_split ${line})
|
||||||
|
list(GET line_split 0 variable_name)
|
||||||
|
if (NOT ${parsed_current_file_contents} MATCHES ${variable_name})
|
||||||
|
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
||||||
|
set(line_to_add ${line_to_add} ${line})
|
||||||
|
foreach (line_to_append ${line_to_add})
|
||||||
|
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
|
||||||
|
endforeach()
|
||||||
|
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
|
||||||
|
endif()
|
||||||
|
set(line_to_add "")
|
||||||
|
else()
|
||||||
|
set(line_to_add ${line_to_add} ${line})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
message(STATUS "Resource file integrity check complete")
|
||||||
|
|
||||||
# Copy navmesh data on first build and extract it
|
# Copy navmesh data on first build and extract it
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/)
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/)
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
PROJECT_VERSION_MAJOR=1
|
PROJECT_VERSION_MAJOR=1
|
||||||
PROJECT_VERSION_MINOR=0
|
PROJECT_VERSION_MINOR=1
|
||||||
PROJECT_VERSION_PATCH=4
|
PROJECT_VERSION_PATCH=1
|
||||||
# LICENSE
|
# LICENSE
|
||||||
LICENSE=AGPL-3.0
|
LICENSE=AGPL-3.0
|
||||||
# The network version.
|
|
||||||
# 171023 - Darkflame Universe client
|
|
||||||
# 171022 - Unmodded client
|
|
||||||
NET_VERSION=171022
|
|
||||||
# Debugging
|
# Debugging
|
||||||
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
||||||
__dynamic=1
|
__dynamic=1
|
||||||
@@ -22,3 +18,5 @@ __maria_db_connector_compile_jobs__=1
|
|||||||
__enable_testing__=1
|
__enable_testing__=1
|
||||||
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
|
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
|
||||||
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
|
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
|
||||||
|
# Uncomment the below line to cache the entire CDClient into memory
|
||||||
|
# CDCLIENT_CACHE_ALL=1
|
||||||
|
|||||||
264
ComponentDefinitions.py
Normal file
264
ComponentDefinitions.py
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
components = {
|
||||||
|
'COMPONENT_TYPE_CONTROLLABLE_PHYSICS': 1,
|
||||||
|
'COMPONENT_TYPE_RENDER': 2,
|
||||||
|
'COMPONENT_TYPE_SIMPLE_PHYSICS': 3,
|
||||||
|
'COMPONENT_TYPE_CHARACTER': 4,
|
||||||
|
'COMPONENT_TYPE_SCRIPT': 5,
|
||||||
|
'COMPONENT_TYPE_BOUNCER': 6,
|
||||||
|
'COMPONENT_TYPE_DESTROYABLE': 7,
|
||||||
|
'COMPONENT_TYPE_GHOST': 8,
|
||||||
|
'COMPONENT_TYPE_SKILL': 9,
|
||||||
|
'COMPONENT_TYPE_SPAWNER': 10,
|
||||||
|
'COMPONENT_TYPE_ITEM': 11,
|
||||||
|
'COMPONENT_TYPE_MODULAR_BUILD': 12,
|
||||||
|
'COMPONENT_TYPE_BUILD_CONTROLLER': 13,
|
||||||
|
'COMPONENT_TYPE_REBUILD_ACTIVATOR': 14,
|
||||||
|
'COMPONENT_TYPE_ICON_ONLY': 15,
|
||||||
|
'COMPONENT_TYPE_VENDOR': 16,
|
||||||
|
'COMPONENT_TYPE_INVENTORY': 17,
|
||||||
|
'COMPONENT_TYPE_PROJECTILE_PHYSICS': 18,
|
||||||
|
'COMPONENT_TYPE_SHOOTING_GALLERY': 19,
|
||||||
|
'COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS': 20,
|
||||||
|
'COMPONENT_TYPE_DROP_EFFECT': 21,
|
||||||
|
'COMPONENT_TYPE_CHEST': 22,
|
||||||
|
'COMPONENT_TYPE_COLLECTIBLE': 23,
|
||||||
|
'COMPONENT_TYPE_BLUEPRINT': 24,
|
||||||
|
'COMPONENT_TYPE_MOVING_PLATFORM': 25,
|
||||||
|
'COMPONENT_TYPE_PET': 26,
|
||||||
|
'COMPONENT_TYPE_PLATFORM_BOUNDARY': 27,
|
||||||
|
'COMPONENT_TYPE_MODULE': 28,
|
||||||
|
'COMPONENT_TYPE_ARCADE': 29,
|
||||||
|
'COMPONENT_TYPE_HAVOK_VEHICLE_PHYSICS': 30,
|
||||||
|
'COMPONENT_TYPE_MOVEMENT_AI': 31,
|
||||||
|
'COMPONENT_TYPE_EXHIBIT': 32,
|
||||||
|
'COMPONENT_TYPE_OVERHEAD_ICON': 33,
|
||||||
|
'COMPONENT_TYPE_PET_CONTROL': 34,
|
||||||
|
'COMPONENT_TYPE_MINIFIG': 35,
|
||||||
|
'COMPONENT_TYPE_PROPERTY': 36,
|
||||||
|
'COMPONENT_TYPE_PET_CREATOR': 37,
|
||||||
|
'COMPONENT_TYPE_MODEL_BUILDER': 38,
|
||||||
|
'COMPONENT_TYPE_SCRIPTED_ACTIVITY': 39,
|
||||||
|
'COMPONENT_TYPE_PHANTOM_PHYSICS': 40,
|
||||||
|
'COMPONENT_TYPE_SPRING_PAD': 41,
|
||||||
|
'COMPONENT_TYPE_MODEL': 42,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_ENTRANCE': 43,
|
||||||
|
'COMPONENT_TYPE_FX': 44,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_MANAGEMENT': 45,
|
||||||
|
'COMPONENT_TYPE_VEHICLE_PHYSICS': 46,
|
||||||
|
'COMPONENT_TYPE_PHYSICS_SYSTEM': 47,
|
||||||
|
'COMPONENT_TYPE_REBUILD': 48,
|
||||||
|
'COMPONENT_TYPE_SWITCH': 49,
|
||||||
|
'COMPONENT_TYPE_ZONE_CONTROL': 50,
|
||||||
|
'COMPONENT_TYPE_CHANGELING': 51,
|
||||||
|
'COMPONENT_TYPE_CHOICE_BUILD': 52,
|
||||||
|
'COMPONENT_TYPE_PACKAGE': 53,
|
||||||
|
'COMPONENT_TYPE_SOUND_REPEATER': 54,
|
||||||
|
'COMPONENT_TYPE_SOUND_AMBIENT_2D': 55,
|
||||||
|
'COMPONENT_TYPE_SOUND_AMBIENT_3D': 56,
|
||||||
|
'COMPONENT_TYPE_PRECONDITION': 57,
|
||||||
|
'COMPONENT_TYPE_PLAYER_FLAG': 58,
|
||||||
|
'COMPONENT_TYPE_CUSTOM_BUILD_ASSEMBLY': 59,
|
||||||
|
'COMPONENT_TYPE_BASE_COMBAT_AI': 60,
|
||||||
|
'COMPONENT_TYPE_MODULE_ASSEMBLY': 61,
|
||||||
|
'COMPONENT_TYPE_SHOWCASE_MODEL_HANDLER': 62,
|
||||||
|
'COMPONENT_TYPE_RACING_MODULE': 63,
|
||||||
|
'COMPONENT_TYPE_GENERIC_ACTIVATOR': 64,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_VENDOR': 65,
|
||||||
|
'COMPONENT_TYPE_HF_LIGHT_DIRECTION_GADGET': 66,
|
||||||
|
'COMPONENT_TYPE_ROCKET_LAUNCH': 67,
|
||||||
|
'COMPONENT_TYPE_ROCKET_LANDING_COMPONENT': 68,
|
||||||
|
'COMPONENT_TYPE_TRIGGER': 69,
|
||||||
|
'COMPONENT_TYPE_DROPPED_LOOT': 70,
|
||||||
|
'COMPONENT_TYPE_RACING_CONTROL': 71,
|
||||||
|
'COMPONENT_TYPE_FACTION_TRIGGER': 72,
|
||||||
|
'COMPONENT_TYPE_MISSION_OFFER': 73,
|
||||||
|
'COMPONENT_TYPE_RACING_STATS': 74,
|
||||||
|
'COMPONENT_TYPE_LUP_EXHIBIT': 75,
|
||||||
|
'COMPONENT_TYPE_BBB': 76,
|
||||||
|
'COMPONENT_TYPE_SOUND_TRIGGER': 77,
|
||||||
|
'COMPONENT_TYPE_PROXIMITY_MONITOR': 78,
|
||||||
|
'COMPONENT_TYPE_RACING_SOUND_TRIGGER': 79,
|
||||||
|
'COMPONENT_TYPE_CHAT': 80,
|
||||||
|
'COMPONENT_TYPE_FRIENDS_LIST': 81,
|
||||||
|
'COMPONENT_TYPE_GUILD': 82,
|
||||||
|
'COMPONENT_TYPE_LOCAL_SYSTEM': 83,
|
||||||
|
'COMPONENT_TYPE_MISSION': 84,
|
||||||
|
'COMPONENT_TYPE_MUTUABLE_MODEL_BEHAVIORS': 85,
|
||||||
|
'COMPONENT_TYPE_PATHFINDING_CONTROL': 86,
|
||||||
|
'COMPONENT_TYPE_PLAYER_PET_TAMING': 87,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_EDITOR': 88,
|
||||||
|
'COMPONENT_TYPE_SKINNED_RENDER': 89,
|
||||||
|
'COMPONENT_TYPE_SLASH_COMMAND': 90,
|
||||||
|
'COMPONENT_TYPE_STATUS_EFFECT': 91,
|
||||||
|
'COMPONENT_TYPE_TEAMS': 92,
|
||||||
|
'COMPONENT_TYPE_TEXT_EFFECT': 93,
|
||||||
|
'COMPONENT_TYPE_TRADE': 94,
|
||||||
|
'COMPONENT_TYPE_USER_CONTROL': 95,
|
||||||
|
'COMPONENT_TYPE_IGNORE_LIST': 96,
|
||||||
|
'COMPONENT_TYPE_ROCKET_LAUNCH_LUP': 97,
|
||||||
|
'COMPONENT_TYPE_BUFF': 98,
|
||||||
|
'COMPONENT_TYPE_INTERACTION_MANAGER': 99,
|
||||||
|
'COMPONENT_TYPE_DONATION_VENDOR': 100,
|
||||||
|
'COMPONENT_TYPE_COMBAT_MEDIATOR': 101,
|
||||||
|
'COMPONENT_TYPE_ACHIEVEMENT_VENDOR': 102,
|
||||||
|
'COMPONENT_TYPE_GATE_RUSH': 103,
|
||||||
|
'COMPONENT_TYPE_RAIL_ACTIVATOR': 104,
|
||||||
|
'COMPONENT_TYPE_ROLLER': 105,
|
||||||
|
'COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT': 106,
|
||||||
|
'COMPONENT_TYPE_CRAFTING': 107,
|
||||||
|
'COMPONENT_TYPE_POSSESSABLE': 108,
|
||||||
|
'COMPONENT_TYPE_LEVEL_PROGRESSION': 109,
|
||||||
|
'COMPONENT_TYPE_POSSESSOR': 110,
|
||||||
|
'COMPONENT_TYPE_MOUNT_CONTROL': 111,
|
||||||
|
'UNKNOWN_112': 112,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_PLAQUE': 113,
|
||||||
|
'COMPONENT_TYPE_BUILD_BORDER': 114,
|
||||||
|
'UNKNOWN_115': 115,
|
||||||
|
'COMPONENT_TYPE_CULLING_PLANE': 116,
|
||||||
|
'INVALID': 4294967295
|
||||||
|
}
|
||||||
|
|
||||||
|
component_initialization_order = [
|
||||||
|
'COMPONENT_TYPE_POSSESSABLE',
|
||||||
|
'COMPONENT_TYPE_BLUEPRINT',
|
||||||
|
'COMPONENT_TYPE_MODULE_ASSEMBLY',
|
||||||
|
'COMPONENT_TYPE_CONTROLLABLE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_PROJECTILE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_PHYSICS_SYSTEM',
|
||||||
|
'COMPONENT_TYPE_VEHICLE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_HAVOK_VEHICLE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_SIMPLE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_PHANTOM_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_DESTROYABLE',
|
||||||
|
'COMPONENT_TYPE_MINIFIG',
|
||||||
|
'COMPONENT_TYPE_CHARACTER',
|
||||||
|
'COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT',
|
||||||
|
'COMPONENT_TYPE_POSSESSOR',
|
||||||
|
'COMPONENT_TYPE_MOUNT_CONTROL',
|
||||||
|
'COMPONENT_TYPE_PET',
|
||||||
|
'COMPONENT_TYPE_INVENTORY',
|
||||||
|
'COMPONENT_TYPE_PROXIMITY_MONITOR',
|
||||||
|
'COMPONENT_TYPE_MOVEMENT_AI',
|
||||||
|
'COMPONENT_TYPE_SCRIPT',
|
||||||
|
'COMPONENT_TYPE_SKILL',
|
||||||
|
'COMPONENT_TYPE_BASE_COMBAT_AI',
|
||||||
|
'COMPONENT_TYPE_SPAWNER',
|
||||||
|
'COMPONENT_TYPE_ITEM',
|
||||||
|
'COMPONENT_TYPE_REBUILD',
|
||||||
|
'COMPONENT_TYPE_BUILD_BORDER',
|
||||||
|
'COMPONENT_TYPE_MODULE',
|
||||||
|
'COMPONENT_TYPE_BUILD_CONTROLLER',
|
||||||
|
'COMPONENT_TYPE_REBUILD_ACTIVATOR',
|
||||||
|
'COMPONENT_TYPE_MODULAR_BUILD',
|
||||||
|
'COMPONENT_TYPE_MISSION_OFFER',
|
||||||
|
'COMPONENT_TYPE_VENDOR',
|
||||||
|
'COMPONENT_TYPE_DONATION_VENDOR',
|
||||||
|
'COMPONENT_TYPE_ACHIEVEMENT_VENDOR',
|
||||||
|
'COMPONENT_TYPE_SHOOTING_GALLERY',
|
||||||
|
'COMPONENT_TYPE_ROLLER',
|
||||||
|
'COMPONENT_TYPE_SCRIPTED_ACTIVITY',
|
||||||
|
'COMPONENT_TYPE_COLLECTIBLE',
|
||||||
|
'COMPONENT_TYPE_MOVING_PLATFORM',
|
||||||
|
'COMPONENT_TYPE_CHANGELING',
|
||||||
|
'COMPONENT_TYPE_CHOICE_BUILD',
|
||||||
|
'COMPONENT_TYPE_PACKAGE',
|
||||||
|
'COMPONENT_TYPE_PLATFORM_BOUNDARY',
|
||||||
|
'COMPONENT_TYPE_HF_LIGHT_DIRECTION_GADGET',
|
||||||
|
'COMPONENT_TYPE_CULLING_PLANE',
|
||||||
|
'COMPONENT_TYPE_EXHIBIT',
|
||||||
|
'COMPONENT_TYPE_LUP_EXHIBIT',
|
||||||
|
'COMPONENT_TYPE_PROPERTY',
|
||||||
|
'COMPONENT_TYPE_PROPERTY_PLAQUE',
|
||||||
|
'COMPONENT_TYPE_MODEL',
|
||||||
|
'COMPONENT_TYPE_PROPERTY_ENTRANCE',
|
||||||
|
'COMPONENT_TYPE_ROCKET_LAUNCH_LUP',
|
||||||
|
'COMPONENT_TYPE_PROPERTY_MANAGEMENT',
|
||||||
|
'COMPONENT_TYPE_RAIL_ACTIVATOR',
|
||||||
|
'COMPONENT_TYPE_BOUNCER',
|
||||||
|
'COMPONENT_TYPE_SPRING_PAD',
|
||||||
|
'COMPONENT_TYPE_SWITCH',
|
||||||
|
'COMPONENT_TYPE_ZONE_CONTROL',
|
||||||
|
'COMPONENT_TYPE_MODEL_BUILDER',
|
||||||
|
'COMPONENT_TYPE_SOUND_REPEATER',
|
||||||
|
'COMPONENT_TYPE_CHEST',
|
||||||
|
'COMPONENT_TYPE_SHOWCASE_MODEL_HANDLER',
|
||||||
|
'COMPONENT_TYPE_ARCADE',
|
||||||
|
'COMPONENT_TYPE_RENDER',
|
||||||
|
'COMPONENT_TYPE_SOUND_AMBIENT_2D',
|
||||||
|
'COMPONENT_TYPE_SOUND_AMBIENT_3D',
|
||||||
|
'COMPONENT_TYPE_SOUND_TRIGGER',
|
||||||
|
'COMPONENT_TYPE_RACING_SOUND_TRIGGER',
|
||||||
|
'COMPONENT_TYPE_CUSTOM_BUILD_ASSEMBLY',
|
||||||
|
'COMPONENT_TYPE_GENERIC_ACTIVATOR',
|
||||||
|
'COMPONENT_TYPE_PROPERTY_VENDOR',
|
||||||
|
'COMPONENT_TYPE_ROCKET_LAUNCH',
|
||||||
|
'COMPONENT_TYPE_ROCKET_LANDING_COMPONENT',
|
||||||
|
'COMPONENT_TYPE_FACTION_TRIGGER',
|
||||||
|
'COMPONENT_TYPE_RACING_CONTROL',
|
||||||
|
'COMPONENT_TYPE_GATE_RUSH',
|
||||||
|
'COMPONENT_TYPE_BBB',
|
||||||
|
'COMPONENT_TYPE_CRAFTING'
|
||||||
|
]
|
||||||
|
component_order_as_ints = {}
|
||||||
|
|
||||||
|
component_int_to_name = {}
|
||||||
|
|
||||||
|
for component in component_initialization_order:
|
||||||
|
component_order_as_ints[components[component]] = component
|
||||||
|
|
||||||
|
for component in components:
|
||||||
|
component_int_to_name[components[component]] = component
|
||||||
|
|
||||||
|
class GameObject:
|
||||||
|
type = ""
|
||||||
|
|
||||||
|
class ObjectLoadState:
|
||||||
|
createdGameObject = GameObject()
|
||||||
|
components = []
|
||||||
|
hasPhysicsComponent = False
|
||||||
|
hasDestroyable = False
|
||||||
|
hasPathfindingComponent = False
|
||||||
|
hasProximityMonitorComponent = False
|
||||||
|
hasScriptComponent = False
|
||||||
|
hasDroppedLootComponent = False
|
||||||
|
hasModelbehaviors = False
|
||||||
|
somethingOrNothing = False
|
||||||
|
physicsComponentId = -1
|
||||||
|
|
||||||
|
# Begin custom attributes
|
||||||
|
serializedOrder = []
|
||||||
|
hasMissionOffer = False
|
||||||
|
|
||||||
|
class NiPoint3:
|
||||||
|
x = 0.0
|
||||||
|
y = 0.0
|
||||||
|
z = 0.0
|
||||||
|
|
||||||
|
class NiQuaternion:
|
||||||
|
w = 0.0
|
||||||
|
x = 0.0
|
||||||
|
y = 0.0
|
||||||
|
z = 0.0
|
||||||
|
|
||||||
|
class LoadObject:
|
||||||
|
objId = 0
|
||||||
|
owner = 0
|
||||||
|
lotToSpawn = 0
|
||||||
|
isLocalPlayer = False
|
||||||
|
hasDropEffect = False
|
||||||
|
bIsSmashable = False
|
||||||
|
dynamicPhysics = False
|
||||||
|
spawnPosition = NiPoint3()
|
||||||
|
spawnRotation = NiQuaternion()
|
||||||
|
scale = 0.0
|
||||||
|
legoBrickID = 0
|
||||||
|
legoColorID = 0
|
||||||
|
configData = {}
|
||||||
|
isHFPaletteObject = False
|
||||||
|
objType = 0
|
||||||
|
useSimplePhysics = False
|
||||||
|
bDelayedLoad = False
|
||||||
|
|
||||||
|
# Don't know the name yet of this
|
||||||
|
field8_0x20 = True
|
||||||
408
ComponentFactories.py
Normal file
408
ComponentFactories.py
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
import ComponentDefinitions as cd
|
||||||
|
|
||||||
|
def ApplyComponentWhitelist():
|
||||||
|
# Dont care to actually do this, just want the call for now.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def ControllablePhysFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasModelbehaviors:
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
if not loadObject.useSimplePhysics:
|
||||||
|
objectLoadState.components.append('CONTROLLABLE_PHYSICS')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
else:
|
||||||
|
loadObject.physicsComponentId = componentId
|
||||||
|
|
||||||
|
def RenderFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if loadObject.lotToSpawn == 176:
|
||||||
|
return
|
||||||
|
gmlevel = loadObject.configData.get('gmlevel', 0)
|
||||||
|
if gmlevel > 0 and gmlevel < 6:
|
||||||
|
componentId = 9940 # Override the componentId of the render component to be 9940, the Mythran Render Component
|
||||||
|
renderDisabled = loadObject.configData.get('renderDisabled', False)
|
||||||
|
if renderDisabled:
|
||||||
|
return
|
||||||
|
if objectLoadState.createdGameObject.type == 'BlockingVolume':
|
||||||
|
return
|
||||||
|
rejectedLots = [5937, 5938, 9741, 9742, 9862, 9863]
|
||||||
|
if loadObject.lotToSpawn in rejectedLots:
|
||||||
|
return
|
||||||
|
if loadObject.lotToSpawn == 6368:
|
||||||
|
FxFactory(loadObject, objectLoadState, componentId)
|
||||||
|
return
|
||||||
|
FxFactory(loadObject, objectLoadState, componentId)
|
||||||
|
defaultWrapperAsset = ""
|
||||||
|
hasNifAsset = False
|
||||||
|
hasKfmAsset = False
|
||||||
|
allowRenderWrapping = False
|
||||||
|
nifName = loadObject.configData.get('nif_name', '')
|
||||||
|
if nifName == '':
|
||||||
|
print('TODO query cdc for this data in the Render component')
|
||||||
|
nifName = 'mesh/something.nif' # if empty get nifname as the render_asset column of the RenderComponent table from the database
|
||||||
|
if nifName[-1] == 'f':
|
||||||
|
hasNifAsset = True
|
||||||
|
elif nifName[-1] == 'm':
|
||||||
|
hasKfmAsset = True
|
||||||
|
if defaultWrapperAsset != '':
|
||||||
|
if defaultWrapperAsset[-1] == 'm':
|
||||||
|
allowRenderWrapping = not loadObject.configData.get('preventRenderWrapping', False)
|
||||||
|
if allowRenderWrapping or hasKfmAsset or (not defaultWrapperAsset == 'PrimitiveModels' and not hasNifAsset and not loadObject.configData.get('CreateNULLRender', False)):
|
||||||
|
objectLoadState.components.append('SKINNED_RENDER')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('RENDER')
|
||||||
|
|
||||||
|
def FxFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('FX')
|
||||||
|
|
||||||
|
def SimplePhysFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasModelbehaviors:
|
||||||
|
objectLoadState.physicsComponentId = componentId
|
||||||
|
return
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
return
|
||||||
|
markedAsPhantom = loadObject.configData.get('markedAsPhantom', False)
|
||||||
|
if markedAsPhantom:
|
||||||
|
objectLoadState.components.append('PHANTOM_PHYSICS')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def CharacterFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('POSSESSOR')
|
||||||
|
objectLoadState.components.append('MOUNT_CONTROL')
|
||||||
|
objectLoadState.components.append('PET_CREATOR')
|
||||||
|
objectLoadState.components.append('LEVEL_PROGRESSION')
|
||||||
|
objectLoadState.components.append('PLAYER_FORCED_MOVEMENT')
|
||||||
|
objectLoadState.components.append('CHARACTER')
|
||||||
|
|
||||||
|
def ScriptFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int, add_pathfinding_control: bool):
|
||||||
|
custom_script_client = loadObject.configData.get('custom_script_client', '')
|
||||||
|
custom_script_server = loadObject.configData.get('custom_script_server', '')
|
||||||
|
if componentId == 0 and custom_script_client == '' and custom_script_server == '':
|
||||||
|
return
|
||||||
|
objectLoadState.components.append('SCRIPT')
|
||||||
|
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
if not objectLoadState.hasPathfindingComponent and add_pathfinding_control:
|
||||||
|
objectLoadState.components.append('PATHFINDING_CONTROL')
|
||||||
|
objectLoadState.hasPathfindingComponent = True
|
||||||
|
|
||||||
|
def BouncerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BOUNCER')
|
||||||
|
|
||||||
|
def DestroyableFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('STATUS_EFFECT')
|
||||||
|
objectLoadState.components.append('BUFF')
|
||||||
|
objectLoadState.components.append('DESTROYABLE')
|
||||||
|
objectLoadState.hasDestroyable = True
|
||||||
|
|
||||||
|
def SkillFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SKILL')
|
||||||
|
|
||||||
|
def SpawnerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SPAWNER')
|
||||||
|
# If game state is happy flower
|
||||||
|
spawntemplate = loadObject.configData.get('spawntemplate', '')
|
||||||
|
|
||||||
|
print('TODO query cdc for this data in the Spawner component')
|
||||||
|
render_asset = loadObject.configData.get('render_asset', 'test.nif') # Get this from RenderComponent table
|
||||||
|
render_id = loadObject.configData.get('render_id', '') # Get this from RenderComponent table
|
||||||
|
|
||||||
|
if render_asset[-1] == 'f':
|
||||||
|
objectLoadState.components.append('SKINNED_RENDER')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('RENDER')
|
||||||
|
|
||||||
|
def ItemFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ITEM')
|
||||||
|
|
||||||
|
def ModularBuildFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MODULAR_BUILD')
|
||||||
|
|
||||||
|
def BuildControllerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BUILD_CONTROLLER')
|
||||||
|
|
||||||
|
def VendorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
objectLoadState.components.append('VENDOR')
|
||||||
|
|
||||||
|
def InventoryFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('INVENTORY')
|
||||||
|
|
||||||
|
def ProjectilePhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
objectLoadState.components.append('PROJECTILE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def ShootingGalleryFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SHOOTING_GALLERY')
|
||||||
|
|
||||||
|
def RigibBodyPhantomPhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RIGID_BODY_PHANTOM_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def ChestFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CHEST')
|
||||||
|
|
||||||
|
def CollectibleFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('COLLECTIBLE')
|
||||||
|
if not objectLoadState.hasDestroyable:
|
||||||
|
objectLoadState.components.append('DESTROYABLE')
|
||||||
|
objectLoadState.hasDestroyable = True
|
||||||
|
|
||||||
|
def BlueprintFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BLUEPRINT')
|
||||||
|
|
||||||
|
def MovingPlatformFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MOVING_PLATFORM')
|
||||||
|
|
||||||
|
def PetFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
inInventory = loadObject.configData.get('inInventory', False)
|
||||||
|
if inInventory:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not objectLoadState.hasPathfindingComponent:
|
||||||
|
objectLoadState.components.append('PATHFINDING_CONTROL')
|
||||||
|
objectLoadState.hasPathfindingComponent = True
|
||||||
|
objectLoadState.components.append('PET')
|
||||||
|
|
||||||
|
def PlatformBoundaryFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PLATFORM_BOUNDARY')
|
||||||
|
|
||||||
|
def ModuleFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MODULE')
|
||||||
|
|
||||||
|
def ArcadeFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ARCADE')
|
||||||
|
|
||||||
|
def HavokVehiclePhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
use_simple_physics = loadObject.configData.get('use_simple_physics', False)
|
||||||
|
if use_simple_physics:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
else:
|
||||||
|
objectWorldState = loadObject.configData.get('objectWorldState', '')
|
||||||
|
if objectWorldState == 0 or objectWorldState != 2:
|
||||||
|
objectLoadState.components.append('HAVOK_VEHICLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def MovementAiFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MOVEMENT_AI')
|
||||||
|
|
||||||
|
def ExhibitFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
# Sorry aron, doesnt do anything :(
|
||||||
|
pass
|
||||||
|
|
||||||
|
def MinifigFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MINIFIG')
|
||||||
|
|
||||||
|
def PropertyFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY')
|
||||||
|
|
||||||
|
def ModelBuilderFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MODEL_BUILDER')
|
||||||
|
|
||||||
|
def ScriptedActivityFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SCRIPTED_ACTIVITY')
|
||||||
|
|
||||||
|
def PhantomPhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
objectLoadState.components.append('PHANTOM_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def SpringPadFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SPRING_PAD')
|
||||||
|
|
||||||
|
def ModelFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
modelType = loadObject.configData.get('modelType', 0)
|
||||||
|
if not objectLoadState.hasModelbehaviors:
|
||||||
|
if not objectLoadState.hasPhysicsComponent:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
elif not objectLoadState.hasPhysicsComponent:
|
||||||
|
if modelType == 0:
|
||||||
|
objectLoadState.components.append('CONTROLLABLE_PHYSICS')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
if modelType != 0 and not objectLoadState.hasPathfindingComponent:
|
||||||
|
objectLoadState.components.append('PATHFINDING_CONTROL')
|
||||||
|
objectLoadState.hasPathfindingComponent = True
|
||||||
|
|
||||||
|
hasPropertyObjectID = loadObject.configData.get('propertyObjectID', 0) != 0
|
||||||
|
inInventory = loadObject.configData.get('inInventory', False)
|
||||||
|
if hasPropertyObjectID and inInventory:
|
||||||
|
objectLoadState.components.append('MODEL_BEHAVIORS')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('MUTABLE_MODEL_BEHAVIORS')
|
||||||
|
|
||||||
|
def PropertyEntranceFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY_ENTRANCE')
|
||||||
|
|
||||||
|
def PropertyManagementFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY_MANAGEMENT')
|
||||||
|
|
||||||
|
def VehiclePhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('VEHICLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def PhysicsSystemFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasModelbehaviors:
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
objectLoadState.components.append('PHYSICS_SYSTEM')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def RebuildFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('REBUILD')
|
||||||
|
if not objectLoadState.hasDestroyable:
|
||||||
|
objectLoadState.components.append('DESTROYABLE')
|
||||||
|
objectLoadState.hasDestroyable = True
|
||||||
|
loadObject.bIsSmashable = True
|
||||||
|
|
||||||
|
def BaseCombatAiFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int, add_pathfinding_control: bool):
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
if not objectLoadState.hasPathfindingComponent and add_pathfinding_control:
|
||||||
|
objectLoadState.components.append('PATHFINDING_CONTROL')
|
||||||
|
objectLoadState.hasPathfindingComponent = True
|
||||||
|
|
||||||
|
objectLoadState.components.append('BASE_COMBAT_AI')
|
||||||
|
|
||||||
|
def ProximityMonitorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
print('TODO query cdc for this data in prox mon')
|
||||||
|
# There must be a row for this component in the ProximityMonitorComponent table to get this component
|
||||||
|
LoadOnClient = loadObject.configData.get('LoadOnClient', False) # Get this from ProximityMonitorComponent table if you know there is a column for it
|
||||||
|
if LoadOnClient:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
def DonationVendorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
objectLoadState.components.append('DONATION_VENDOR')
|
||||||
|
|
||||||
|
def AchievmentVendorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
objectLoadState.components.append('ACHIEVEMENT_VENDOR')
|
||||||
|
|
||||||
|
def CraftingFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
# Game verson must be above 999 for this to work!
|
||||||
|
gameVersion = 1000
|
||||||
|
if gameVersion > 999:
|
||||||
|
objectLoadState.components.append('CRAFTING')
|
||||||
|
|
||||||
|
# Technically Possessable and Possessor are the exact same thing
|
||||||
|
def PossessableFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('POSSESSABLE')
|
||||||
|
|
||||||
|
def PossessorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('POSSESSOR')
|
||||||
|
|
||||||
|
def PropertyPlaqueFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY_PLAQUE')
|
||||||
|
|
||||||
|
def BuildBorderFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BUILD_BORDER')
|
||||||
|
|
||||||
|
def CullingPlaneFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CULLING_PLANE')
|
||||||
|
|
||||||
|
def GateRushFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('GATE_RUSH')
|
||||||
|
|
||||||
|
def RailActivatorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RAIL_ACTIVATOR')
|
||||||
|
|
||||||
|
def RollerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ROLLER')
|
||||||
|
|
||||||
|
def PlayerForcedMovementFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PLAYER_FORCED_MOVEMENT')
|
||||||
|
|
||||||
|
def RacingSoundTriggerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RACING_SOUND_TRIGGER')
|
||||||
|
|
||||||
|
def RocketLaunchLupFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ROCKET_LAUNCH_LUP')
|
||||||
|
|
||||||
|
|
||||||
|
def ModuleAssemblyFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MODULE_ASSEMBLY')
|
||||||
|
|
||||||
|
def ShowcaseModelHandlerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SHOWCASE_MODEL_HANDLER')
|
||||||
|
|
||||||
|
def GenericActivatorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('GENERIC_ACTIVATOR')
|
||||||
|
|
||||||
|
def PropertyVendorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY_VENDOR')
|
||||||
|
|
||||||
|
def RocketLaunchFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ROCKET_LAUNCH')
|
||||||
|
|
||||||
|
def RocketLandingComponentFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ROCKET_LANDING_COMPONENT')
|
||||||
|
|
||||||
|
def RacingControlFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RACING_CONTROL')
|
||||||
|
|
||||||
|
def FactionTriggerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('FACTION_TRIGGER')
|
||||||
|
|
||||||
|
def MissionOfferFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MISSION_OFFER')
|
||||||
|
objectLoadState.hasMissionOffer = True
|
||||||
|
|
||||||
|
def RacingStatsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RACING_STATS')
|
||||||
|
|
||||||
|
def LupExhibitFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('LUP_EXHIBIT')
|
||||||
|
|
||||||
|
def BBBFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BBB')
|
||||||
|
|
||||||
|
def SoundTriggerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SOUND_TRIGGER')
|
||||||
|
|
||||||
|
def SwitchFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SWITCH')
|
||||||
|
|
||||||
|
def ZoneControlFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ZONE_CONTROL')
|
||||||
|
|
||||||
|
def ChanglingFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CHANGELING')
|
||||||
|
|
||||||
|
def ChoiceBuildFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CHOICE_BUILD')
|
||||||
|
|
||||||
|
def PackageFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
# Literally returns nothing
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SoundRepeaterFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SOUND_REPEATER')
|
||||||
|
|
||||||
|
def SoundAmbient2DFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if loadObject.isLocalPlayer:
|
||||||
|
objectLoadState.components.append('SOUND_AMBIENT_2D')
|
||||||
|
|
||||||
|
def SoundAmbient3DFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SOUND_AMBIENT_3D')
|
||||||
|
|
||||||
|
def CustomBuildAssemblyFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CUSTOM_BUILD_ASSEMBLY')
|
||||||
306
DoObjectPreLoad.py
Normal file
306
DoObjectPreLoad.py
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
import ComponentDefinitions as cd
|
||||||
|
import ComponentFactories as cf
|
||||||
|
|
||||||
|
# If we have any of these components, we need pathfinding control
|
||||||
|
def CheckIfNeedsPathfindingControl(components_to_load: dict):
|
||||||
|
add_pathfinding_control = cd.components['COMPONENT_TYPE_CONTROLLABLE_PHYSICS'] in components_to_load
|
||||||
|
add_pathfinding_control |= cd.components['COMPONENT_TYPE_PROJECTILE_PHYSICS'] in components_to_load
|
||||||
|
add_pathfinding_control |= cd.components['COMPONENT_TYPE_HAVOK_VEHICLE_PHYSICS'] in components_to_load
|
||||||
|
add_pathfinding_control |= cd.components['COMPONENT_TYPE_VEHICLE_PHYSICS'] in components_to_load
|
||||||
|
return add_pathfinding_control
|
||||||
|
|
||||||
|
def DoObjectPreLoad(components_to_load: dict):
|
||||||
|
isHfActive = False
|
||||||
|
cf.ApplyComponentWhitelist()
|
||||||
|
objectLoadState = cd.ObjectLoadState()
|
||||||
|
loadObject = cd.LoadObject()
|
||||||
|
|
||||||
|
for componentType in cd.component_order_as_ints.keys():
|
||||||
|
try:
|
||||||
|
componentId = components_to_load[componentType]
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
match cd.component_int_to_name[componentType]:
|
||||||
|
case 'COMPONENT_TYPE_CONTROLLABLE_PHYSICS':
|
||||||
|
if objectLoadState.hasDroppedLootComponent: continue
|
||||||
|
cf.ControllablePhysFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RENDER':
|
||||||
|
cf.RenderFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SIMPLE_PHYSICS':
|
||||||
|
if objectLoadState.hasDroppedLootComponent: continue
|
||||||
|
cf.SimplePhysFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CHARACTER':
|
||||||
|
cf.CharacterFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SCRIPT':
|
||||||
|
cf.ScriptFactory(loadObject, objectLoadState, componentId, CheckIfNeedsPathfindingControl(components_to_load))
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BOUNCER':
|
||||||
|
cf.BouncerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_DESTROYABLE':
|
||||||
|
cf.DestroyableFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SKILL':
|
||||||
|
cf.SkillFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SPAWNER':
|
||||||
|
cf.SpawnerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ITEM':
|
||||||
|
cf.ItemFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODULAR_BUILD':
|
||||||
|
cf.ModularBuildFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BUILD_CONTROLLER':
|
||||||
|
cf.BuildControllerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_VENDOR':
|
||||||
|
cf.VendorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_INVENTORY':
|
||||||
|
cf.InventoryFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROJECTILE_PHYSICS':
|
||||||
|
if objectLoadState.hasDroppedLootComponent: continue
|
||||||
|
cf.ProjectilePhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SHOOTING_GALLERY':
|
||||||
|
cf.ShootingGalleryFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS':
|
||||||
|
cf.RigibBodyPhantomPhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CHEST':
|
||||||
|
cf.ChestFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_COLLECTIBLE':
|
||||||
|
cf.CollectibleFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BLUEPRINT':
|
||||||
|
cf.BlueprintFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MOVING_PLATFORM':
|
||||||
|
cf.MovingPlatformFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PET':
|
||||||
|
cf.PetFactory(loadObject, objectLoadState, componentId)
|
||||||
|
print('Deleting COMPONENT_TYPE_MODEL and COMPONENT_TYPE_ITEM due to COMPONENT_TYPE_PET being loaded')
|
||||||
|
toDel = cd.components['COMPONENT_TYPE_MODEL']
|
||||||
|
del components_to_load[toDel]
|
||||||
|
toDel = cd.components['COMPONENT_TYPE_ITEM']
|
||||||
|
del components_to_load[toDel]
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PLATFORM_BOUNDARY':
|
||||||
|
cf.PlatformBoundaryFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODULE':
|
||||||
|
cf.ModuleFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ARCADE':
|
||||||
|
cf.ArcadeFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_HAVOK_VEHICLE_PHYSICS':
|
||||||
|
cf.HavokVehiclePhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MOVEMENT_AI':
|
||||||
|
cf.MovementAiFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_EXHIBIT':
|
||||||
|
cf.ExhibitFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MINIFIG':
|
||||||
|
cf.MinifigFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY':
|
||||||
|
cf.PropertyFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODEL_BUILDER':
|
||||||
|
cf.ModelBuilderFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SCRIPTED_ACTIVITY':
|
||||||
|
cf.ScriptedActivityFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PHANTOM_PHYSICS':
|
||||||
|
if objectLoadState.hasDroppedLootComponent: continue
|
||||||
|
cf.PhantomPhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SPRING_PAD':
|
||||||
|
cf.SpringPadFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODEL':
|
||||||
|
cf.ModelFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY_ENTRANCE':
|
||||||
|
cf.PropertyEntranceFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY_MANAGEMENT':
|
||||||
|
cf.PropertyManagementFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_VEHICLE_PHYSICS':
|
||||||
|
cf.VehiclePhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PHYSICS_SYSTEM':
|
||||||
|
cf.PhysicsSystemFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_REBUILD':
|
||||||
|
cf.RebuildFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SWITCH':
|
||||||
|
cf.SwitchFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ZONE_CONTROL':
|
||||||
|
cf.ZoneControlFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CHANGELING':
|
||||||
|
cf.ChanglingFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CHOICE_BUILD':
|
||||||
|
cf.ChoiceBuildFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PACKAGE':
|
||||||
|
cf.PackageFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SOUND_REPEATER':
|
||||||
|
cf.SoundRepeaterFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SOUND_AMBIENT_2D':
|
||||||
|
cf.SoundAmbient2DFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SOUND_AMBIENT_3D':
|
||||||
|
cf.SoundAmbient3DFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CUSTOM_BUILD_ASSEMBLY':
|
||||||
|
cf.CustomBuildAssemblyFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BASE_COMBAT_AI':
|
||||||
|
cf.BaseCombatAiFactory(loadObject, objectLoadState, componentId, CheckIfNeedsPathfindingControl(components_to_load))
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODULE_ASSEMBLY':
|
||||||
|
cf.ModuleAssemblyFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SHOWCASE_MODEL_HANDLER':
|
||||||
|
cf.ShowcaseModelHandlerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_GENERIC_ACTIVATOR':
|
||||||
|
cf.GenericActivatorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY_VENDOR':
|
||||||
|
cf.PropertyVendorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ROCKET_LAUNCH':
|
||||||
|
cf.RocketLaunchFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ROCKET_LANDING_COMPONENT':
|
||||||
|
cf.RocketLandingComponentFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RACING_CONTROL':
|
||||||
|
cf.RacingControlFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_FACTION_TRIGGER':
|
||||||
|
cf.FactionTriggerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MISSION_OFFER':
|
||||||
|
cf.MissionOfferFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RACING_STATS':
|
||||||
|
cf.RacingStatsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_LUP_EXHIBIT':
|
||||||
|
cf.LupExhibitFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BBB':
|
||||||
|
cf.BBBFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SOUND_TRIGGER':
|
||||||
|
cf.SoundTriggerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROXIMITY_MONITOR':
|
||||||
|
cf.ProximityMonitorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RACING_SOUND_TRIGGER':
|
||||||
|
cf.RacingSoundTriggerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ROCKET_LAUNCH_LUP':
|
||||||
|
cf.RocketLaunchLupFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_DONATION_VENDOR':
|
||||||
|
cf.DonationVendorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ACHIEVEMENT_VENDOR':
|
||||||
|
cf.AchievmentVendorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_GATE_RUSH':
|
||||||
|
cf.GateRushFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RAIL_ACTIVATOR':
|
||||||
|
cf.RailActivatorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ROLLER':
|
||||||
|
cf.RollerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT':
|
||||||
|
cf.PlayerForcedMovementFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CRAFTING':
|
||||||
|
cf.CraftingFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_POSSESSABLE':
|
||||||
|
cf.PossessableFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_POSSESSOR':
|
||||||
|
cf.PossessorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY_PLAQUE':
|
||||||
|
cf.PropertyPlaqueFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BUILD_BORDER':
|
||||||
|
cf.BuildBorderFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CULLING_PLANE':
|
||||||
|
cf.CullingPlaneFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
print(f'Unknown component: {componentType}')
|
||||||
|
|
||||||
|
if not 'is_smashable' in loadObject.configData and loadObject.bIsSmashable:
|
||||||
|
loadObject.configData['is_smashable'] = True
|
||||||
|
|
||||||
|
is_smashable = loadObject.configData['is_smashable']
|
||||||
|
if is_smashable and not objectLoadState.hasDestroyable and loadObject.lotToSpawn != 176:
|
||||||
|
objectLoadState.components.append('DESTROYABLE')
|
||||||
|
|
||||||
|
if objectLoadState.hasMissionOffer and not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
if loadObject.field8_0x20 and loadObject.owner != 0:
|
||||||
|
objectLoadState.components.append('OVERHEAD_ICON')
|
||||||
|
|
||||||
|
trigger_id = loadObject.configData.get('trigger_id', 0)
|
||||||
|
if trigger_id != 0:
|
||||||
|
objectLoadState.components.append('TRIGGER')
|
||||||
|
|
||||||
|
return objectLoadState
|
||||||
|
|
||||||
|
components_to_load = {}
|
||||||
|
|
||||||
|
# Testing code to load all components
|
||||||
|
for i in range(110):
|
||||||
|
components_to_load[i] = i
|
||||||
|
|
||||||
|
objectLoadState = DoObjectPreLoad(components_to_load)
|
||||||
|
|
||||||
|
# Convert the components to ints
|
||||||
|
components_to_int = []
|
||||||
|
for component in objectLoadState.components:
|
||||||
|
components_to_int.append([cd.components[f'COMPONENT_TYPE_{component}'], component])
|
||||||
|
|
||||||
|
# Print out the components in a more readable format
|
||||||
|
for comp in components_to_int:
|
||||||
|
print(comp[0], comp[1])
|
||||||
@@ -179,7 +179,7 @@ If you would like to build the server faster, append `-j<number>` where number i
|
|||||||
### Notes
|
### Notes
|
||||||
Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building:
|
Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building:
|
||||||
* If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory.
|
* If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory.
|
||||||
* If you are using a Darkflame Universe client, ensure NET_VERSION is changed to 171023.
|
* If you are using a Darkflame Universe client, ensure `client_net_version` in `build/sharedconfig.ini` is changed to 171023.
|
||||||
|
|
||||||
## Configuring your server
|
## Configuring your server
|
||||||
This server has a few steps that need to be taken to configure the server for your use case.
|
This server has a few steps that need to be taken to configure the server for your use case.
|
||||||
@@ -338,7 +338,7 @@ This is a Work in Progress, but below are some quick links to documentaion for s
|
|||||||
## Former Contributors
|
## Former Contributors
|
||||||
* TheMachine
|
* TheMachine
|
||||||
* Matthew
|
* Matthew
|
||||||
* [Raine](https://github.com/Rainebannister)
|
* [Raine](https://github.com/uwainium)
|
||||||
* Bricknave
|
* Bricknave
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
|||||||
BIN
__pycache__/ComponentDefinitions.cpython-310.pyc
Normal file
BIN
__pycache__/ComponentDefinitions.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ComponentFactories.cpython-310.pyc
Normal file
BIN
__pycache__/ComponentFactories.cpython-310.pyc
Normal file
Binary file not shown.
@@ -29,6 +29,7 @@ namespace Game {
|
|||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
dConfig* config = nullptr;
|
dConfig* config = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
|
std::mt19937 randomEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger* SetupLogger();
|
dLogger* SetupLogger();
|
||||||
@@ -83,6 +84,8 @@ int main(int argc, char** argv) {
|
|||||||
delete res;
|
delete res;
|
||||||
delete stmt;
|
delete stmt;
|
||||||
|
|
||||||
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
|
|
||||||
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
||||||
uint32_t maxClients = 50;
|
uint32_t maxClients = 50;
|
||||||
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
|
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "PacketUtils.h"
|
#include "PacketUtils.h"
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
@@ -75,11 +76,11 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
|
|
||||||
//Now, we need to send the friendlist to the server they came from:
|
//Now, we need to send the friendlist to the server they came from:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(playerID);
|
bitStream.Write(playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(0);
|
bitStream.Write<uint8_t>(0);
|
||||||
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
||||||
bitStream.Write((uint16_t)friends.size());
|
bitStream.Write((uint16_t)friends.size());
|
||||||
@@ -412,21 +413,21 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
const auto otherName = std::string(otherMember->playerName.c_str());
|
const auto otherName = std::string(otherMember->playerName.c_str());
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(otherMember->playerID);
|
bitStream.Write(otherMember->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(otherMember->playerID);
|
bitStream.Write(otherMember->playerID);
|
||||||
bitStream.Write<uint8_t>(8);
|
bitStream.Write<uint8_t>(8);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
PacketUtils::WritePacketWString(senderName, 33, &bitStream);
|
bitStream.Write(LUWString(senderName));
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
PacketUtils::WritePacketWString(otherName, 33, &bitStream);
|
bitStream.Write(LUWString(otherName));
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(0); //teams?
|
bitStream.Write<uint8_t>(0); //teams?
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = otherMember->sysAddr;
|
SystemAddress sysAddr = otherMember->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -434,7 +435,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||||
LWOOBJID senderID = PacketUtils::ReadPacketS64(0x08, packet);
|
LWOOBJID senderID = PacketUtils::ReadS64(0x08, packet);
|
||||||
std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
|
std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
|
||||||
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
||||||
|
|
||||||
@@ -451,21 +452,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
//To the sender:
|
//To the sender:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint8_t>(7);
|
bitStream.Write<uint8_t>(7);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
PacketUtils::WritePacketWString(goonAName, 33, &bitStream);
|
bitStream.Write(LUWString(goonAName));
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
PacketUtils::WritePacketWString(goonBName, 33, &bitStream);
|
bitStream.Write(LUWString(goonBName));
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(0); //success
|
bitStream.Write<uint8_t>(0); //success
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = goonA->sysAddr;
|
SystemAddress sysAddr = goonA->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -474,21 +475,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
//To the receiver:
|
//To the receiver:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(goonB->playerID);
|
bitStream.Write(goonB->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint8_t>(7);
|
bitStream.Write<uint8_t>(7);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
PacketUtils::WritePacketWString(goonAName, 33, &bitStream);
|
bitStream.Write(LUWString(goonAName));
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
PacketUtils::WritePacketWString(goonBName, 33, &bitStream);
|
bitStream.Write(LUWString(goonBName));
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(3); //new whisper
|
bitStream.Write<uint8_t>(3); //new whisper
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = goonB->sysAddr;
|
SystemAddress sysAddr = goonB->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -709,13 +710,13 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
||||||
|
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
@@ -724,7 +725,7 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -751,7 +752,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -776,7 +777,7 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -793,7 +794,7 @@ void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64Play
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -822,7 +823,7 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -848,7 +849,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -882,16 +883,16 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
|
|||||||
[bool] - is FTP*/
|
[bool] - is FTP*/
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(friendData->playerID);
|
bitStream.Write(friendData->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
||||||
bitStream.Write<uint8_t>(notifyType);
|
bitStream.Write<uint8_t>(notifyType);
|
||||||
|
|
||||||
std::string playerName = playerData->playerName.c_str();
|
std::string playerName = playerData->playerName.c_str();
|
||||||
|
|
||||||
PacketUtils::WritePacketWString(playerName, 33, &bitStream);
|
bitStream.Write(LUWString(playerName));
|
||||||
|
|
||||||
bitStream.Write(playerData->zoneID.GetMapID());
|
bitStream.Write(playerData->zoneID.GetMapID());
|
||||||
bitStream.Write(playerData->zoneID.GetInstanceID());
|
bitStream.Write(playerData->zoneID.GetInstanceID());
|
||||||
@@ -921,12 +922,12 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
@@ -937,16 +938,16 @@ void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sen
|
|||||||
if (!receiver || !sender) return;
|
if (!receiver || !sender) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
// Portion that will get routed:
|
// Portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
||||||
bitStream.Write(responseCode);
|
bitStream.Write(responseCode);
|
||||||
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
||||||
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
// Then write the player name
|
// Then write the player name
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
// Then if this is an acceptance code, write the following extra info.
|
// Then if this is an acceptance code, write the following extra info.
|
||||||
if (responseCode == eAddFriendResponseType::ACCEPTED) {
|
if (responseCode == eAddFriendResponseType::ACCEPTED) {
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
@@ -962,13 +963,13 @@ void ChatPacketHandler::SendRemoveFriend(PlayerData* receiver, std::string& pers
|
|||||||
if (!receiver) return;
|
if (!receiver) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
||||||
PacketUtils::WritePacketWString(personToRemove, 33, &bitStream);
|
bitStream.Write(LUWString(personToRemove));
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ namespace Game {
|
|||||||
dChatFilter* chatFilter = nullptr;
|
dChatFilter* chatFilter = nullptr;
|
||||||
AssetManager* assetManager = nullptr;
|
AssetManager* assetManager = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
|
std::mt19937 randomEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -114,6 +115,8 @@ int main(int argc, char** argv) {
|
|||||||
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::shouldShutdown);
|
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::shouldShutdown);
|
||||||
|
|
||||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
|
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
|
||||||
|
|
||||||
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
|
|
||||||
//Run it until server gets a kill message from Master:
|
//Run it until server gets a kill message from Master:
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
#include "ChatPacketHandler.h"
|
#include "ChatPacketHandler.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "PacketUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatInternalMessageType.h"
|
||||||
|
#include "ChatPackets.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
|
||||||
PlayerContainer::PlayerContainer() {
|
PlayerContainer::PlayerContainer() {
|
||||||
}
|
}
|
||||||
@@ -18,6 +20,10 @@ PlayerContainer::~PlayerContainer() {
|
|||||||
mPlayers.clear();
|
mPlayers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TeamData::TeamData() {
|
||||||
|
lootFlag = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
void PlayerContainer::InsertPlayer(Packet* packet) {
|
void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
PlayerData* data = new PlayerData();
|
PlayerData* data = new PlayerData();
|
||||||
@@ -146,7 +152,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
|||||||
|
|
||||||
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(player);
|
bitStream.Write(player);
|
||||||
bitStream.Write(time);
|
bitStream.Write(time);
|
||||||
@@ -207,6 +213,14 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
||||||
|
if (team->memberIDs.size() >= 4){
|
||||||
|
Game::logger->Log("PlayerContainer", "Tried to add player to team that already had 4 players");
|
||||||
|
auto* player = GetPlayerData(playerID);
|
||||||
|
if (!player) return;
|
||||||
|
ChatPackets::SendSystemMessage(player->sysAddr, u"The teams is full! You have not been added to a team!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
||||||
|
|
||||||
if (index != team->memberIDs.end()) return;
|
if (index != team->memberIDs.end()) return;
|
||||||
@@ -345,7 +359,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
|||||||
|
|
||||||
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(team->teamID);
|
bitStream.Write(team->teamID);
|
||||||
bitStream.Write(deleteTeam);
|
bitStream.Write(deleteTeam);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ struct PlayerData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TeamData {
|
struct TeamData {
|
||||||
|
TeamData();
|
||||||
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
||||||
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
||||||
std::vector<LWOOBJID> memberIDs{};
|
std::vector<LWOOBJID> memberIDs{};
|
||||||
|
|||||||
@@ -1,77 +1,79 @@
|
|||||||
#include "AMFDeserialize.h"
|
#include "AMFDeserialize.h"
|
||||||
|
|
||||||
#include "AMFFormat.h"
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AMF3 Reference document https://rtmp.veriskope.com/pdf/amf3-file-format-spec.pdf
|
* AMF3 Reference document https://rtmp.veriskope.com/pdf/amf3-file-format-spec.pdf
|
||||||
* AMF3 Deserializer written by EmosewaMC
|
* AMF3 Deserializer written by EmosewaMC
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::Read(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream* inStream) {
|
||||||
if (!inStream) return nullptr;
|
if (!inStream) return nullptr;
|
||||||
AMFValue* returnValue = nullptr;
|
AMFBaseValue* returnValue = nullptr;
|
||||||
// Read in the value type from the bitStream
|
// Read in the value type from the bitStream
|
||||||
int8_t marker;
|
eAmf marker;
|
||||||
inStream->Read(marker);
|
inStream->Read(marker);
|
||||||
// Based on the typing, create the value associated with that and return the base value class
|
// Based on the typing, create the value associated with that and return the base value class
|
||||||
switch (marker) {
|
switch (marker) {
|
||||||
case AMFValueType::AMFUndefined: {
|
case eAmf::Undefined: {
|
||||||
returnValue = new AMFUndefinedValue();
|
returnValue = new AMFBaseValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFNull: {
|
case eAmf::Null: {
|
||||||
returnValue = new AMFNullValue();
|
returnValue = new AMFNullValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFFalse: {
|
case eAmf::False: {
|
||||||
returnValue = new AMFFalseValue();
|
returnValue = new AMFBoolValue(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFTrue: {
|
case eAmf::True: {
|
||||||
returnValue = new AMFTrueValue();
|
returnValue = new AMFBoolValue(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFInteger: {
|
case eAmf::Integer: {
|
||||||
returnValue = ReadAmfInteger(inStream);
|
returnValue = ReadAmfInteger(inStream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFDouble: {
|
case eAmf::Double: {
|
||||||
returnValue = ReadAmfDouble(inStream);
|
returnValue = ReadAmfDouble(inStream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFString: {
|
case eAmf::String: {
|
||||||
returnValue = ReadAmfString(inStream);
|
returnValue = ReadAmfString(inStream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFArray: {
|
case eAmf::Array: {
|
||||||
returnValue = ReadAmfArray(inStream);
|
returnValue = ReadAmfArray(inStream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO We do not need these values, but if someone wants to implement them
|
// These values are unimplemented in the live client and will remain unimplemented
|
||||||
// then please do so and add the corresponding unit tests.
|
// unless someone modifies the client to allow serializing of these values.
|
||||||
case AMFValueType::AMFXMLDoc:
|
case eAmf::XMLDoc:
|
||||||
case AMFValueType::AMFDate:
|
case eAmf::Date:
|
||||||
case AMFValueType::AMFObject:
|
case eAmf::Object:
|
||||||
case AMFValueType::AMFXML:
|
case eAmf::XML:
|
||||||
case AMFValueType::AMFByteArray:
|
case eAmf::ByteArray:
|
||||||
case AMFValueType::AMFVectorInt:
|
case eAmf::VectorInt:
|
||||||
case AMFValueType::AMFVectorUInt:
|
case eAmf::VectorUInt:
|
||||||
case AMFValueType::AMFVectorDouble:
|
case eAmf::VectorDouble:
|
||||||
case AMFValueType::AMFVectorObject:
|
case eAmf::VectorObject:
|
||||||
case AMFValueType::AMFDictionary: {
|
case eAmf::Dictionary: {
|
||||||
throw static_cast<AMFValueType>(marker);
|
throw marker;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw static_cast<AMFValueType>(marker);
|
throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast<int32_t>(marker)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
@@ -99,7 +101,7 @@ uint32_t AMFDeserialize::ReadU29(RakNet::BitStream* inStream) {
|
|||||||
return actualNumber;
|
return actualNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
|
const std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
|
||||||
auto length = ReadU29(inStream);
|
auto length = ReadU29(inStream);
|
||||||
// Check if this is a reference
|
// Check if this is a reference
|
||||||
bool isReference = length % 2 == 1;
|
bool isReference = length % 2 == 1;
|
||||||
@@ -113,48 +115,39 @@ std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
|
|||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
// Length is a reference to a previous index - use that as the read in value
|
// Length is a reference to a previous index - use that as the read in value
|
||||||
return accessedElements[length];
|
return accessedElements.at(length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) {
|
||||||
auto doubleValue = new AMFDoubleValue();
|
|
||||||
double value;
|
double value;
|
||||||
inStream->Read<double>(value);
|
inStream->Read<double>(value);
|
||||||
doubleValue->SetDoubleValue(value);
|
return new AMFDoubleValue(value);
|
||||||
return doubleValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) {
|
||||||
auto arrayValue = new AMFArrayValue();
|
auto arrayValue = new AMFArrayValue();
|
||||||
|
|
||||||
// Read size of dense array
|
// Read size of dense array
|
||||||
auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
||||||
|
// Then read associative portion
|
||||||
// Then read Key'd portion
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto key = ReadString(inStream);
|
auto key = ReadString(inStream);
|
||||||
// No more values when we encounter an empty string
|
// No more associative values when we encounter an empty string key
|
||||||
if (key.size() == 0) break;
|
if (key.size() == 0) break;
|
||||||
arrayValue->InsertValue(key, Read(inStream));
|
arrayValue->Insert(key, Read(inStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally read dense portion
|
// Finally read dense portion
|
||||||
for (uint32_t i = 0; i < sizeOfDenseArray; i++) {
|
for (uint32_t i = 0; i < sizeOfDenseArray; i++) {
|
||||||
arrayValue->PushBackValue(Read(inStream));
|
arrayValue->Insert(i, Read(inStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
return arrayValue;
|
return arrayValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) {
|
||||||
auto stringValue = new AMFStringValue();
|
return new AMFStringValue(ReadString(inStream));
|
||||||
stringValue->SetStringValue(ReadString(inStream));
|
|
||||||
return stringValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) {
|
||||||
auto integerValue = new AMFIntegerValue();
|
return new AMFIntValue(ReadU29(inStream));
|
||||||
integerValue->SetIntegerValue(ReadU29(inStream));
|
|
||||||
return integerValue;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class AMFValue;
|
class AMFBaseValue;
|
||||||
|
|
||||||
class AMFDeserialize {
|
class AMFDeserialize {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -14,7 +15,7 @@ public:
|
|||||||
* @param inStream inStream to read value from.
|
* @param inStream inStream to read value from.
|
||||||
* @return Returns an AMFValue with all the information from the bitStream in it.
|
* @return Returns an AMFValue with all the information from the bitStream in it.
|
||||||
*/
|
*/
|
||||||
AMFValue* Read(RakNet::BitStream* inStream);
|
AMFBaseValue* Read(RakNet::BitStream* inStream);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Private method to read a U29 integer from a bitstream
|
* @brief Private method to read a U29 integer from a bitstream
|
||||||
@@ -30,7 +31,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return The read string
|
* @return The read string
|
||||||
*/
|
*/
|
||||||
std::string ReadString(RakNet::BitStream* inStream);
|
const std::string ReadString(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFDouble value from a bitStream
|
* @brief Read an AMFDouble value from a bitStream
|
||||||
@@ -38,7 +39,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Double value represented as an AMFValue
|
* @return Double value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
AMFValue* ReadAmfDouble(RakNet::BitStream* inStream);
|
AMFBaseValue* ReadAmfDouble(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFArray from a bitStream
|
* @brief Read an AMFArray from a bitStream
|
||||||
@@ -46,7 +47,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Array value represented as an AMFValue
|
* @return Array value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
AMFValue* ReadAmfArray(RakNet::BitStream* inStream);
|
AMFBaseValue* ReadAmfArray(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFString from a bitStream
|
* @brief Read an AMFString from a bitStream
|
||||||
@@ -54,7 +55,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return String value represented as an AMFValue
|
* @return String value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
AMFValue* ReadAmfString(RakNet::BitStream* inStream);
|
AMFBaseValue* ReadAmfString(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFInteger from a bitStream
|
* @brief Read an AMFInteger from a bitStream
|
||||||
@@ -62,7 +63,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Integer value represented as an AMFValue
|
* @return Integer value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
AMFValue* ReadAmfInteger(RakNet::BitStream* inStream);
|
AMFBaseValue* ReadAmfInteger(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of strings read so far saved to be read by reference.
|
* List of strings read so far saved to be read by reference.
|
||||||
|
|||||||
@@ -1,156 +0,0 @@
|
|||||||
#include "AMFFormat.h"
|
|
||||||
|
|
||||||
// AMFInteger
|
|
||||||
void AMFIntegerValue::SetIntegerValue(uint32_t value) {
|
|
||||||
this->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t AMFIntegerValue::GetIntegerValue() {
|
|
||||||
return this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFDouble
|
|
||||||
void AMFDoubleValue::SetDoubleValue(double value) {
|
|
||||||
this->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AMFDoubleValue::GetDoubleValue() {
|
|
||||||
return this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFString
|
|
||||||
void AMFStringValue::SetStringValue(const std::string& value) {
|
|
||||||
this->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AMFStringValue::GetStringValue() {
|
|
||||||
return this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFXMLDoc
|
|
||||||
void AMFXMLDocValue::SetXMLDocValue(const std::string& value) {
|
|
||||||
this->xmlData = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AMFXMLDocValue::GetXMLDocValue() {
|
|
||||||
return this->xmlData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFDate
|
|
||||||
void AMFDateValue::SetDateValue(uint64_t value) {
|
|
||||||
this->millisecondTimestamp = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t AMFDateValue::GetDateValue() {
|
|
||||||
return this->millisecondTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Insert Value
|
|
||||||
void AMFArrayValue::InsertValue(const std::string& key, AMFValue* value) {
|
|
||||||
this->associative.insert(std::make_pair(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Remove Value
|
|
||||||
void AMFArrayValue::RemoveValue(const std::string& key) {
|
|
||||||
_AMFArrayMap_::iterator it = this->associative.find(key);
|
|
||||||
if (it != this->associative.end()) {
|
|
||||||
this->associative.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Associative Iterator Begin
|
|
||||||
_AMFArrayMap_::iterator AMFArrayValue::GetAssociativeIteratorValueBegin() {
|
|
||||||
return this->associative.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Associative Iterator End
|
|
||||||
_AMFArrayMap_::iterator AMFArrayValue::GetAssociativeIteratorValueEnd() {
|
|
||||||
return this->associative.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Push Back Value
|
|
||||||
void AMFArrayValue::PushBackValue(AMFValue* value) {
|
|
||||||
this->dense.push_back(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Pop Back Value
|
|
||||||
void AMFArrayValue::PopBackValue() {
|
|
||||||
this->dense.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Dense List Size
|
|
||||||
uint32_t AMFArrayValue::GetDenseValueSize() {
|
|
||||||
return (uint32_t)this->dense.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Dense Iterator Begin
|
|
||||||
_AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorBegin() {
|
|
||||||
return this->dense.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Dense Iterator End
|
|
||||||
_AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorEnd() {
|
|
||||||
return this->dense.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
AMFArrayValue::~AMFArrayValue() {
|
|
||||||
for (auto valueToDelete : GetDenseArray()) {
|
|
||||||
if (valueToDelete) delete valueToDelete;
|
|
||||||
}
|
|
||||||
for (auto valueToDelete : GetAssociativeMap()) {
|
|
||||||
if (valueToDelete.second) delete valueToDelete.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Constructor
|
|
||||||
AMFObjectValue::AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits) {
|
|
||||||
this->traits.reserve(traits.size());
|
|
||||||
std::vector<std::pair<std::string, AMFValueType>>::iterator it = traits.begin();
|
|
||||||
while (it != traits.end()) {
|
|
||||||
this->traits.insert(std::make_pair(it->first, std::make_pair(it->second, new AMFNullValue())));
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Set Value
|
|
||||||
void AMFObjectValue::SetTraitValue(const std::string& trait, AMFValue* value) {
|
|
||||||
if (value) {
|
|
||||||
_AMFObjectTraits_::iterator it = this->traits.find(trait);
|
|
||||||
if (it != this->traits.end()) {
|
|
||||||
if (it->second.first == value->GetValueType()) {
|
|
||||||
it->second.second = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Get Value
|
|
||||||
AMFValue* AMFObjectValue::GetTraitValue(const std::string& trait) {
|
|
||||||
_AMFObjectTraits_::iterator it = this->traits.find(trait);
|
|
||||||
if (it != this->traits.end()) {
|
|
||||||
return it->second.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Get Trait Iterator Begin
|
|
||||||
_AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorBegin() {
|
|
||||||
return this->traits.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Get Trait Iterator End
|
|
||||||
_AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorEnd() {
|
|
||||||
return this->traits.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Get Trait Size
|
|
||||||
uint32_t AMFObjectValue::GetTraitArrayCount() {
|
|
||||||
return (uint32_t)this->traits.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
AMFObjectValue::~AMFObjectValue() {
|
|
||||||
for (auto valueToDelete = GetTraitsIteratorBegin(); valueToDelete != GetTraitsIteratorEnd(); valueToDelete++) {
|
|
||||||
if (valueToDelete->second.second) delete valueToDelete->second.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,413 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Custom Classes
|
|
||||||
#include "dCommonVars.h"
|
|
||||||
|
|
||||||
// C++
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file AMFFormat.hpp
|
|
||||||
\brief A class for managing AMF values
|
|
||||||
*/
|
|
||||||
|
|
||||||
class AMFValue; // Forward declaration
|
|
||||||
|
|
||||||
// Definitions
|
|
||||||
#define _AMFArrayMap_ std::unordered_map<std::string, AMFValue*>
|
|
||||||
#define _AMFArrayList_ std::vector<AMFValue*>
|
|
||||||
|
|
||||||
#define _AMFObjectTraits_ std::unordered_map<std::string, std::pair<AMFValueType, AMFValue*>>
|
|
||||||
#define _AMFObjectDynamicTraits_ std::unordered_map<std::string, AMFValue*>
|
|
||||||
|
|
||||||
//! An enum for each AMF value type
|
|
||||||
enum AMFValueType : unsigned char {
|
|
||||||
AMFUndefined = 0x00, //!< An undefined AMF Value
|
|
||||||
AMFNull = 0x01, //!< A null AMF value
|
|
||||||
AMFFalse = 0x02, //!< A false AMF value
|
|
||||||
AMFTrue = 0x03, //!< A true AMF value
|
|
||||||
AMFInteger = 0x04, //!< An integer AMF value
|
|
||||||
AMFDouble = 0x05, //!< A double AMF value
|
|
||||||
AMFString = 0x06, //!< A string AMF value
|
|
||||||
AMFXMLDoc = 0x07, //!< An XML Doc AMF value
|
|
||||||
AMFDate = 0x08, //!< A date AMF value
|
|
||||||
AMFArray = 0x09, //!< An array AMF value
|
|
||||||
AMFObject = 0x0A, //!< An object AMF value
|
|
||||||
AMFXML = 0x0B, //!< An XML AMF value
|
|
||||||
AMFByteArray = 0x0C, //!< A byte array AMF value
|
|
||||||
AMFVectorInt = 0x0D, //!< An integer vector AMF value
|
|
||||||
AMFVectorUInt = 0x0E, //!< An unsigned integer AMF value
|
|
||||||
AMFVectorDouble = 0x0F, //!< A double vector AMF value
|
|
||||||
AMFVectorObject = 0x10, //!< An object vector AMF value
|
|
||||||
AMFDictionary = 0x11 //!< A dictionary AMF value
|
|
||||||
};
|
|
||||||
|
|
||||||
//! An enum for the object value types
|
|
||||||
enum AMFObjectValueType : unsigned char {
|
|
||||||
AMFObjectAnonymous = 0x01,
|
|
||||||
AMFObjectTyped = 0x02,
|
|
||||||
AMFObjectDynamic = 0x03,
|
|
||||||
AMFObjectExternalizable = 0x04
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The base AMF value class
|
|
||||||
class AMFValue {
|
|
||||||
public:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
virtual AMFValueType GetValueType() = 0;
|
|
||||||
virtual ~AMFValue() {};
|
|
||||||
};
|
|
||||||
|
|
||||||
//! A typedef for a pointer to an AMF value
|
|
||||||
typedef AMFValue* NDGFxValue;
|
|
||||||
|
|
||||||
|
|
||||||
// The various AMF value types
|
|
||||||
|
|
||||||
//! The undefined value AMF type
|
|
||||||
class AMFUndefinedValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFUndefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The null value AMF type
|
|
||||||
class AMFNullValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFNull;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The false value AMF type
|
|
||||||
class AMFFalseValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFFalse;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The true value AMF type
|
|
||||||
class AMFTrueValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFTrue;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The integer value AMF type
|
|
||||||
class AMFIntegerValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
uint32_t value; //!< The value of the AMF type
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFInteger;
|
|
||||||
//! Sets the integer value
|
|
||||||
/*!
|
|
||||||
\param value The value to set
|
|
||||||
*/
|
|
||||||
void SetIntegerValue(uint32_t value);
|
|
||||||
|
|
||||||
//! Gets the integer value
|
|
||||||
/*!
|
|
||||||
\return The integer value
|
|
||||||
*/
|
|
||||||
uint32_t GetIntegerValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The double value AMF type
|
|
||||||
class AMFDoubleValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
double value; //!< The value of the AMF type
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFDouble;
|
|
||||||
//! Sets the double value
|
|
||||||
/*!
|
|
||||||
\param value The value to set to
|
|
||||||
*/
|
|
||||||
void SetDoubleValue(double value);
|
|
||||||
|
|
||||||
//! Gets the double value
|
|
||||||
/*!
|
|
||||||
\return The double value
|
|
||||||
*/
|
|
||||||
double GetDoubleValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The string value AMF type
|
|
||||||
class AMFStringValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
std::string value; //!< The value of the AMF type
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFString;
|
|
||||||
//! Sets the string value
|
|
||||||
/*!
|
|
||||||
\param value The string value to set to
|
|
||||||
*/
|
|
||||||
void SetStringValue(const std::string& value);
|
|
||||||
|
|
||||||
//! Gets the string value
|
|
||||||
/*!
|
|
||||||
\return The string value
|
|
||||||
*/
|
|
||||||
std::string GetStringValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The XML doc value AMF type
|
|
||||||
class AMFXMLDocValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
std::string xmlData; //!< The value of the AMF type
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFXMLDoc;
|
|
||||||
//! Sets the XML Doc value
|
|
||||||
/*!
|
|
||||||
\param value The value to set to
|
|
||||||
*/
|
|
||||||
void SetXMLDocValue(const std::string& value);
|
|
||||||
|
|
||||||
//! Gets the XML Doc value
|
|
||||||
/*!
|
|
||||||
\return The XML Doc value
|
|
||||||
*/
|
|
||||||
std::string GetXMLDocValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The date value AMF type
|
|
||||||
class AMFDateValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
uint64_t millisecondTimestamp; //!< The time in milliseconds since the ephoch
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFDate;
|
|
||||||
//! Sets the date time
|
|
||||||
/*!
|
|
||||||
\param value The value to set to
|
|
||||||
*/
|
|
||||||
void SetDateValue(uint64_t value);
|
|
||||||
|
|
||||||
//! Gets the date value
|
|
||||||
/*!
|
|
||||||
\return The date value in milliseconds since the epoch
|
|
||||||
*/
|
|
||||||
uint64_t GetDateValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The array value AMF type
|
|
||||||
// This object will manage it's own memory map and list. Do not delete its values.
|
|
||||||
class AMFArrayValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
_AMFArrayMap_ associative; //!< The array map (associative part)
|
|
||||||
_AMFArrayList_ dense; //!< The array list (dense part)
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() override { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFArray;
|
|
||||||
|
|
||||||
~AMFArrayValue() override;
|
|
||||||
//! Inserts an item into the array map for a specific key
|
|
||||||
/*!
|
|
||||||
\param key The key to set
|
|
||||||
\param value The value to add
|
|
||||||
*/
|
|
||||||
void InsertValue(const std::string& key, AMFValue* value);
|
|
||||||
|
|
||||||
//! Removes an item for a specific key
|
|
||||||
/*!
|
|
||||||
\param key The key to remove
|
|
||||||
*/
|
|
||||||
void RemoveValue(const std::string& key);
|
|
||||||
|
|
||||||
//! Finds an AMF value
|
|
||||||
/*!
|
|
||||||
\return The AMF value if found, nullptr otherwise
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
T* FindValue(const std::string& key) const {
|
|
||||||
_AMFArrayMap_::const_iterator it = this->associative.find(key);
|
|
||||||
if (it != this->associative.end() && T::ValueType == it->second->GetValueType()) {
|
|
||||||
return dynamic_cast<T*>(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Returns where the associative iterator begins
|
|
||||||
/*!
|
|
||||||
\return Where the array map iterator begins
|
|
||||||
*/
|
|
||||||
_AMFArrayMap_::iterator GetAssociativeIteratorValueBegin();
|
|
||||||
|
|
||||||
//! Returns where the associative iterator ends
|
|
||||||
/*!
|
|
||||||
\return Where the array map iterator ends
|
|
||||||
*/
|
|
||||||
_AMFArrayMap_::iterator GetAssociativeIteratorValueEnd();
|
|
||||||
|
|
||||||
//! Pushes back a value into the array list
|
|
||||||
/*!
|
|
||||||
\param value The value to push back
|
|
||||||
*/
|
|
||||||
void PushBackValue(AMFValue* value);
|
|
||||||
|
|
||||||
//! Pops back the last value in the array list
|
|
||||||
void PopBackValue();
|
|
||||||
|
|
||||||
//! Gets the count of the dense list
|
|
||||||
/*!
|
|
||||||
\return The dense list size
|
|
||||||
*/
|
|
||||||
uint32_t GetDenseValueSize();
|
|
||||||
|
|
||||||
//! Gets a specific value from the list for the specified index
|
|
||||||
/*!
|
|
||||||
\param index The index to get
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
T* GetValueAt(uint32_t index) {
|
|
||||||
if (index >= this->dense.size()) return nullptr;
|
|
||||||
AMFValue* foundValue = this->dense.at(index);
|
|
||||||
return T::ValueType == foundValue->GetValueType() ? dynamic_cast<T*>(foundValue) : nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Returns where the dense iterator begins
|
|
||||||
/*!
|
|
||||||
\return Where the iterator begins
|
|
||||||
*/
|
|
||||||
_AMFArrayList_::iterator GetDenseIteratorBegin();
|
|
||||||
|
|
||||||
//! Returns where the dense iterator ends
|
|
||||||
/*!
|
|
||||||
\return Where the iterator ends
|
|
||||||
*/
|
|
||||||
_AMFArrayList_::iterator GetDenseIteratorEnd();
|
|
||||||
|
|
||||||
//! Returns the associative map
|
|
||||||
/*!
|
|
||||||
\return The associative map
|
|
||||||
*/
|
|
||||||
_AMFArrayMap_ GetAssociativeMap() { return this->associative; };
|
|
||||||
|
|
||||||
//! Returns the dense array
|
|
||||||
/*!
|
|
||||||
\return The dense array
|
|
||||||
*/
|
|
||||||
_AMFArrayList_ GetDenseArray() { return this->dense; };
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The anonymous object value AMF type
|
|
||||||
class AMFObjectValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
_AMFObjectTraits_ traits; //!< The object traits
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() override { return ValueType; }
|
|
||||||
~AMFObjectValue() override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFObject;
|
|
||||||
//! Constructor
|
|
||||||
/*!
|
|
||||||
\param traits The traits to set
|
|
||||||
*/
|
|
||||||
AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits);
|
|
||||||
|
|
||||||
//! Gets the object value type
|
|
||||||
/*!
|
|
||||||
\return The object value type
|
|
||||||
*/
|
|
||||||
virtual AMFObjectValueType GetObjectValueType() { return AMFObjectAnonymous; }
|
|
||||||
|
|
||||||
//! Sets the value of a trait
|
|
||||||
/*!
|
|
||||||
\param trait The trait to set the value for
|
|
||||||
\param value The AMF value to set
|
|
||||||
*/
|
|
||||||
void SetTraitValue(const std::string& trait, AMFValue* value);
|
|
||||||
|
|
||||||
//! Gets a trait value
|
|
||||||
/*!
|
|
||||||
\param trait The trait to get the value for
|
|
||||||
\return The trait value
|
|
||||||
*/
|
|
||||||
AMFValue* GetTraitValue(const std::string& trait);
|
|
||||||
|
|
||||||
//! Gets the beginning of the object traits iterator
|
|
||||||
/*!
|
|
||||||
\return The AMF trait array iterator begin
|
|
||||||
*/
|
|
||||||
_AMFObjectTraits_::iterator GetTraitsIteratorBegin();
|
|
||||||
|
|
||||||
//! Gets the end of the object traits iterator
|
|
||||||
/*!
|
|
||||||
\return The AMF trait array iterator begin
|
|
||||||
*/
|
|
||||||
_AMFObjectTraits_::iterator GetTraitsIteratorEnd();
|
|
||||||
|
|
||||||
//! Gets the amount of traits
|
|
||||||
/*!
|
|
||||||
\return The amount of traits
|
|
||||||
*/
|
|
||||||
uint32_t GetTraitArrayCount();
|
|
||||||
};
|
|
||||||
@@ -1,259 +0,0 @@
|
|||||||
#include "AMFFormat_BitStream.h"
|
|
||||||
|
|
||||||
// Writes an AMFValue pointer to a RakNet::BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
|
|
||||||
if (value != nullptr) {
|
|
||||||
AMFValueType type = value->GetValueType();
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case AMFUndefined: {
|
|
||||||
AMFUndefinedValue* v = (AMFUndefinedValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFNull: {
|
|
||||||
AMFNullValue* v = (AMFNullValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFFalse: {
|
|
||||||
AMFFalseValue* v = (AMFFalseValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFTrue: {
|
|
||||||
AMFTrueValue* v = (AMFTrueValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFInteger: {
|
|
||||||
AMFIntegerValue* v = (AMFIntegerValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFDouble: {
|
|
||||||
AMFDoubleValue* v = (AMFDoubleValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFString: {
|
|
||||||
AMFStringValue* v = (AMFStringValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFXMLDoc: {
|
|
||||||
AMFXMLDocValue* v = (AMFXMLDocValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFDate: {
|
|
||||||
AMFDateValue* v = (AMFDateValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFArray: {
|
|
||||||
this->Write((AMFArrayValue*)value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AMFObject:
|
|
||||||
case AMFXML:
|
|
||||||
case AMFByteArray:
|
|
||||||
case AMFVectorInt:
|
|
||||||
case AMFVectorUInt:
|
|
||||||
case AMFVectorDouble:
|
|
||||||
case AMFVectorObject:
|
|
||||||
case AMFDictionary:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A private function to write an value to a RakNet::BitStream
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
|
|
||||||
unsigned char b4 = (unsigned char)v;
|
|
||||||
if (v < 0x00200000) {
|
|
||||||
b4 = b4 & 0x7F;
|
|
||||||
if (v > 0x7F) {
|
|
||||||
unsigned char b3;
|
|
||||||
v = v >> 7;
|
|
||||||
b3 = ((unsigned char)(v)) | 0x80;
|
|
||||||
if (v > 0x7F) {
|
|
||||||
unsigned char b2;
|
|
||||||
v = v >> 7;
|
|
||||||
b2 = ((unsigned char)(v)) | 0x80;
|
|
||||||
bs->Write(b2);
|
|
||||||
}
|
|
||||||
|
|
||||||
bs->Write(b3);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unsigned char b1;
|
|
||||||
unsigned char b2;
|
|
||||||
unsigned char b3;
|
|
||||||
|
|
||||||
v = v >> 8;
|
|
||||||
b3 = ((unsigned char)(v)) | 0x80;
|
|
||||||
v = v >> 7;
|
|
||||||
b2 = ((unsigned char)(v)) | 0x80;
|
|
||||||
v = v >> 7;
|
|
||||||
b1 = ((unsigned char)(v)) | 0x80;
|
|
||||||
|
|
||||||
bs->Write(b1);
|
|
||||||
bs->Write(b2);
|
|
||||||
bs->Write(b3);
|
|
||||||
}
|
|
||||||
|
|
||||||
bs->Write(b4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a flag number to a RakNet::BitStream
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
|
|
||||||
v = (v << 1) | 0x01;
|
|
||||||
WriteUInt29(bs, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an AMFString to a RakNet::BitStream
|
|
||||||
*
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
|
|
||||||
WriteFlagNumber(bs, (uint32_t)str.size());
|
|
||||||
bs->Write(str.c_str(), (uint32_t)str.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an U16 to a bitstream
|
|
||||||
*
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
|
|
||||||
bs->Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an U32 to a bitstream
|
|
||||||
*
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
|
|
||||||
bs->Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an U64 to a bitstream
|
|
||||||
*
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
|
|
||||||
bs->Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Writes an AMFUndefinedValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFUndefinedValue>(AMFUndefinedValue value) {
|
|
||||||
this->Write(AMFUndefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFNullValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFNullValue>(AMFNullValue value) {
|
|
||||||
this->Write(AMFNull);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFFalseValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFFalseValue>(AMFFalseValue value) {
|
|
||||||
this->Write(AMFFalse);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFTrueValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFTrueValue>(AMFTrueValue value) {
|
|
||||||
this->Write(AMFTrue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFIntegerValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFIntegerValue>(AMFIntegerValue value) {
|
|
||||||
this->Write(AMFInteger);
|
|
||||||
WriteUInt29(this, value.GetIntegerValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFDoubleValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value) {
|
|
||||||
this->Write(AMFDouble);
|
|
||||||
double d = value.GetDoubleValue();
|
|
||||||
WriteAMFU64(this, *((unsigned long long*) & d));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFStringValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFStringValue>(AMFStringValue value) {
|
|
||||||
this->Write(AMFString);
|
|
||||||
std::string v = value.GetStringValue();
|
|
||||||
WriteAMFString(this, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFXMLDocValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFXMLDocValue>(AMFXMLDocValue value) {
|
|
||||||
this->Write(AMFXMLDoc);
|
|
||||||
std::string v = value.GetXMLDocValue();
|
|
||||||
WriteAMFString(this, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFDateValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value) {
|
|
||||||
this->Write(AMFDate);
|
|
||||||
uint64_t date = value.GetDateValue();
|
|
||||||
WriteAMFU64(this, date);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFArrayValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value) {
|
|
||||||
this->Write(AMFArray);
|
|
||||||
uint32_t denseSize = value->GetDenseValueSize();
|
|
||||||
WriteFlagNumber(this, denseSize);
|
|
||||||
|
|
||||||
_AMFArrayMap_::iterator it = value->GetAssociativeIteratorValueBegin();
|
|
||||||
_AMFArrayMap_::iterator end = value->GetAssociativeIteratorValueEnd();
|
|
||||||
|
|
||||||
while (it != end) {
|
|
||||||
WriteAMFString(this, it->first);
|
|
||||||
this->Write(it->second);
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->Write(AMFNull);
|
|
||||||
|
|
||||||
if (denseSize > 0) {
|
|
||||||
_AMFArrayList_::iterator it2 = value->GetDenseIteratorBegin();
|
|
||||||
_AMFArrayList_::iterator end2 = value->GetDenseIteratorEnd();
|
|
||||||
|
|
||||||
while (it2 != end2) {
|
|
||||||
this->Write(*it2);
|
|
||||||
it2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Custom Classes
|
|
||||||
#include "AMFFormat.h"
|
|
||||||
|
|
||||||
// RakNet
|
|
||||||
#include <BitStream.h>
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file AMFFormat_BitStream.h
|
|
||||||
\brief A class that implements native writing of AMF values to RakNet::BitStream
|
|
||||||
*/
|
|
||||||
|
|
||||||
// We are using the RakNet namespace
|
|
||||||
namespace RakNet {
|
|
||||||
//! Writes an AMFValue pointer to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFValue*>(AMFValue* value);
|
|
||||||
|
|
||||||
//! Writes an AMFUndefinedValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFUndefinedValue>(AMFUndefinedValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFNullValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFNullValue>(AMFNullValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFFalseValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFFalseValue>(AMFFalseValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFTrueValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFTrueValue>(AMFTrueValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFIntegerValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFIntegerValue>(AMFIntegerValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFDoubleValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFStringValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFStringValue>(AMFStringValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFXMLDocValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFXMLDocValue>(AMFXMLDocValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFDateValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFArrayValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value);
|
|
||||||
} // namespace RakNet
|
|
||||||
367
dCommon/Amf3.h
Normal file
367
dCommon/Amf3.h
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
#ifndef __AMF3__H__
|
||||||
|
#define __AMF3__H__
|
||||||
|
|
||||||
|
#include "dCommonVars.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
#include "Game.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum class eAmf : uint8_t {
|
||||||
|
Undefined = 0x00, // An undefined AMF Value
|
||||||
|
Null = 0x01, // A null AMF value
|
||||||
|
False = 0x02, // A false AMF value
|
||||||
|
True = 0x03, // A true AMF value
|
||||||
|
Integer = 0x04, // An integer AMF value
|
||||||
|
Double = 0x05, // A double AMF value
|
||||||
|
String = 0x06, // A string AMF value
|
||||||
|
XMLDoc = 0x07, // Unused in the live client and cannot be serialized without modification. An XML Doc AMF value
|
||||||
|
Date = 0x08, // Unused in the live client and cannot be serialized without modification. A date AMF value
|
||||||
|
Array = 0x09, // An array AMF value
|
||||||
|
Object = 0x0A, // Unused in the live client and cannot be serialized without modification. An object AMF value
|
||||||
|
XML = 0x0B, // Unused in the live client and cannot be serialized without modification. An XML AMF value
|
||||||
|
ByteArray = 0x0C, // Unused in the live client and cannot be serialized without modification. A byte array AMF value
|
||||||
|
VectorInt = 0x0D, // Unused in the live client and cannot be serialized without modification. An integer vector AMF value
|
||||||
|
VectorUInt = 0x0E, // Unused in the live client and cannot be serialized without modification. An unsigned integer AMF value
|
||||||
|
VectorDouble = 0x0F, // Unused in the live client and cannot be serialized without modification. A double vector AMF value
|
||||||
|
VectorObject = 0x10, // Unused in the live client and cannot be serialized without modification. An object vector AMF value
|
||||||
|
Dictionary = 0x11 // Unused in the live client and cannot be serialized without modification. A dictionary AMF value
|
||||||
|
};
|
||||||
|
|
||||||
|
class AMFBaseValue {
|
||||||
|
public:
|
||||||
|
virtual eAmf GetValueType() { return eAmf::Undefined; };
|
||||||
|
AMFBaseValue() {};
|
||||||
|
virtual ~AMFBaseValue() {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
class AMFValue : public AMFBaseValue {
|
||||||
|
public:
|
||||||
|
AMFValue() {};
|
||||||
|
AMFValue(ValueType value) { SetValue(value); };
|
||||||
|
virtual ~AMFValue() override {};
|
||||||
|
|
||||||
|
eAmf GetValueType() override { return eAmf::Undefined; };
|
||||||
|
|
||||||
|
const ValueType& GetValue() { return data; };
|
||||||
|
void SetValue(ValueType value) { data = value; };
|
||||||
|
protected:
|
||||||
|
ValueType data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// As a string this is much easier to write and read from a BitStream.
|
||||||
|
template<>
|
||||||
|
class AMFValue<const char*> : public AMFBaseValue {
|
||||||
|
public:
|
||||||
|
AMFValue() {};
|
||||||
|
AMFValue(const char* value) { SetValue(std::string(value)); };
|
||||||
|
virtual ~AMFValue() override {};
|
||||||
|
|
||||||
|
eAmf GetValueType() override { return eAmf::String; };
|
||||||
|
|
||||||
|
const std::string& GetValue() { return data; };
|
||||||
|
void SetValue(std::string value) { data = value; };
|
||||||
|
protected:
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef AMFValue<std::nullptr_t> AMFNullValue;
|
||||||
|
typedef AMFValue<bool> AMFBoolValue;
|
||||||
|
typedef AMFValue<int32_t> AMFIntValue;
|
||||||
|
typedef AMFValue<std::string> AMFStringValue;
|
||||||
|
typedef AMFValue<double> AMFDoubleValue;
|
||||||
|
|
||||||
|
template<> inline eAmf AMFValue<std::nullptr_t>::GetValueType() { return eAmf::Null; };
|
||||||
|
template<> inline eAmf AMFValue<bool>::GetValueType() { return this->data ? eAmf::True : eAmf::False; };
|
||||||
|
template<> inline eAmf AMFValue<int32_t>::GetValueType() { return eAmf::Integer; };
|
||||||
|
template<> inline eAmf AMFValue<uint32_t>::GetValueType() { return eAmf::Integer; };
|
||||||
|
template<> inline eAmf AMFValue<std::string>::GetValueType() { return eAmf::String; };
|
||||||
|
template<> inline eAmf AMFValue<double>::GetValueType() { return eAmf::Double; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The AMFArrayValue object holds 2 types of lists:
|
||||||
|
* An associative list where a key maps to a value
|
||||||
|
* A Dense list where elements are stored back to back
|
||||||
|
*
|
||||||
|
* Objects that are Registered are owned by this object
|
||||||
|
* and are not to be deleted by a caller.
|
||||||
|
*/
|
||||||
|
class AMFArrayValue : public AMFBaseValue {
|
||||||
|
|
||||||
|
typedef std::unordered_map<std::string, AMFBaseValue*> AMFAssociative;
|
||||||
|
typedef std::vector<AMFBaseValue*> AMFDense;
|
||||||
|
|
||||||
|
public:
|
||||||
|
eAmf GetValueType() override { return eAmf::Array; };
|
||||||
|
|
||||||
|
~AMFArrayValue() override {
|
||||||
|
for (auto valueToDelete : GetDense()) {
|
||||||
|
if (valueToDelete) {
|
||||||
|
delete valueToDelete;
|
||||||
|
valueToDelete = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto valueToDelete : GetAssociative()) {
|
||||||
|
if (valueToDelete.second) {
|
||||||
|
delete valueToDelete.second;
|
||||||
|
valueToDelete.second = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Associative portion of the object
|
||||||
|
*/
|
||||||
|
inline AMFAssociative& GetAssociative() { return this->associative; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the dense portion of the object
|
||||||
|
*/
|
||||||
|
inline AMFDense& GetDense() { return this->dense; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an AMFValue into the associative portion with the given key.
|
||||||
|
* If a duplicate is attempted to be inserted, it is ignored and the
|
||||||
|
* first value with that key is kept in the map.
|
||||||
|
*
|
||||||
|
* These objects are not to be deleted by the caller as they are owned by
|
||||||
|
* the AMFArray object which manages its own memory.
|
||||||
|
*
|
||||||
|
* @param key The key to associate with the value
|
||||||
|
* @param value The value to insert
|
||||||
|
*
|
||||||
|
* @return The inserted element if the type matched,
|
||||||
|
* or nullptr if a key existed and was not the same type
|
||||||
|
*/
|
||||||
|
template<typename ValueType>
|
||||||
|
std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, ValueType value) {
|
||||||
|
auto element = associative.find(key);
|
||||||
|
AMFValue<ValueType>* val = nullptr;
|
||||||
|
bool found = true;
|
||||||
|
if (element == associative.end()) {
|
||||||
|
val = new AMFValue<ValueType>(value);
|
||||||
|
associative.insert(std::make_pair(key, val));
|
||||||
|
} else {
|
||||||
|
val = dynamic_cast<AMFValue<ValueType>*>(element->second);
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
return std::make_pair(val, found);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Associates an array with a string key
|
||||||
|
std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
|
||||||
|
auto element = associative.find(key);
|
||||||
|
AMFArrayValue* val = nullptr;
|
||||||
|
bool found = true;
|
||||||
|
if (element == associative.end()) {
|
||||||
|
val = new AMFArrayValue();
|
||||||
|
associative.insert(std::make_pair(key, val));
|
||||||
|
} else {
|
||||||
|
val = dynamic_cast<AMFArrayValue*>(element->second);
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
return std::make_pair(val, found);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Associates an array with an integer key
|
||||||
|
std::pair<AMFBaseValue*, bool> Insert(const uint32_t& index) {
|
||||||
|
AMFArrayValue* val = nullptr;
|
||||||
|
bool inserted = false;
|
||||||
|
if (index >= dense.size()) {
|
||||||
|
dense.resize(index + 1);
|
||||||
|
val = new AMFArrayValue();
|
||||||
|
dense.at(index) = val;
|
||||||
|
inserted = true;
|
||||||
|
}
|
||||||
|
return std::make_pair(dynamic_cast<AMFArrayValue*>(dense.at(index)), inserted);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inserts an AMFValue into the AMFArray key'd by index.
|
||||||
|
* Attempting to insert the same key to the same value twice overwrites
|
||||||
|
* the previous value with the new one.
|
||||||
|
*
|
||||||
|
* @param index The index to associate with the value
|
||||||
|
* @param value The value to insert
|
||||||
|
* @return The inserted element, or nullptr if the type did not match
|
||||||
|
* what was at the index.
|
||||||
|
*/
|
||||||
|
template<typename ValueType>
|
||||||
|
std::pair<AMFValue<ValueType>*, bool> Insert(const uint32_t& index, ValueType value) {
|
||||||
|
AMFValue<ValueType>* val = nullptr;
|
||||||
|
bool inserted = false;
|
||||||
|
if (index >= this->dense.size()) {
|
||||||
|
this->dense.resize(index + 1);
|
||||||
|
val = new AMFValue<ValueType>(value);
|
||||||
|
this->dense.at(index) = val;
|
||||||
|
inserted = true;
|
||||||
|
}
|
||||||
|
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(this->dense.at(index)), inserted);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an AMFValue into the associative portion with the given key.
|
||||||
|
* If a duplicate is attempted to be inserted, it replaces the original
|
||||||
|
*
|
||||||
|
* The inserted element is now owned by this object and is not to be deleted
|
||||||
|
*
|
||||||
|
* @param key The key to associate with the value
|
||||||
|
* @param value The value to insert
|
||||||
|
*/
|
||||||
|
void Insert(const std::string& key, AMFBaseValue* value) {
|
||||||
|
auto element = associative.find(key);
|
||||||
|
if (element != associative.end() && element->second) {
|
||||||
|
delete element->second;
|
||||||
|
element->second = value;
|
||||||
|
} else {
|
||||||
|
associative.insert(std::make_pair(key, value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an AMFValue into the associative portion with the given index.
|
||||||
|
* If a duplicate is attempted to be inserted, it replaces the original
|
||||||
|
*
|
||||||
|
* The inserted element is now owned by this object and is not to be deleted
|
||||||
|
*
|
||||||
|
* @param key The key to associate with the value
|
||||||
|
* @param value The value to insert
|
||||||
|
*/
|
||||||
|
void Insert(const uint32_t index, AMFBaseValue* value) {
|
||||||
|
if (index < dense.size()) {
|
||||||
|
AMFDense::iterator itr = dense.begin() + index;
|
||||||
|
if (*itr) delete dense.at(index);
|
||||||
|
} else {
|
||||||
|
dense.resize(index + 1);
|
||||||
|
}
|
||||||
|
dense.at(index) = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes an AMFValue into the back of the dense portion.
|
||||||
|
*
|
||||||
|
* These objects are not to be deleted by the caller as they are owned by
|
||||||
|
* the AMFArray object which manages its own memory.
|
||||||
|
*
|
||||||
|
* @param value The value to insert
|
||||||
|
*
|
||||||
|
* @return The inserted pointer, or nullptr should the key already be in use.
|
||||||
|
*/
|
||||||
|
template<typename ValueType>
|
||||||
|
inline AMFValue<ValueType>* Push(ValueType value) {
|
||||||
|
return Insert(this->dense.size(), value).first;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the key from the associative portion
|
||||||
|
*
|
||||||
|
* The pointer removed is now no longer managed by this container
|
||||||
|
*
|
||||||
|
* @param key The key to remove from the associative portion
|
||||||
|
*/
|
||||||
|
void Remove(const std::string& key, bool deleteValue = true) {
|
||||||
|
AMFAssociative::iterator it = this->associative.find(key);
|
||||||
|
if (it != this->associative.end()) {
|
||||||
|
if (deleteValue) delete it->second;
|
||||||
|
this->associative.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops the last element in the dense portion, deleting it in the process.
|
||||||
|
*/
|
||||||
|
void Remove(const uint32_t index) {
|
||||||
|
if (!this->dense.empty() && index < this->dense.size()) {
|
||||||
|
auto itr = this->dense.begin() + index;
|
||||||
|
if (*itr) delete (*itr);
|
||||||
|
this->dense.erase(itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pop() {
|
||||||
|
if (!this->dense.empty()) Remove(this->dense.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
AMFArrayValue* GetArray(const std::string& key) {
|
||||||
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
|
if (it != this->associative.end()) {
|
||||||
|
return dynamic_cast<AMFArrayValue*>(it->second);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
AMFArrayValue* GetArray(const uint32_t index) {
|
||||||
|
return index >= this->dense.size() ? nullptr : dynamic_cast<AMFArrayValue*>(this->dense.at(index));
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AMFArrayValue* InsertArray(const std::string& key) {
|
||||||
|
return static_cast<AMFArrayValue*>(Insert(key).first);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AMFArrayValue* InsertArray(const uint32_t index) {
|
||||||
|
return static_cast<AMFArrayValue*>(Insert(index).first);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AMFArrayValue* PushArray() {
|
||||||
|
return static_cast<AMFArrayValue*>(Insert(this->dense.size()).first);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an AMFValue by the key from the associative portion and converts it
|
||||||
|
* to the AmfValue template type. If the key did not exist, it is inserted.
|
||||||
|
*
|
||||||
|
* @tparam The target object type
|
||||||
|
* @param key The key to lookup
|
||||||
|
*
|
||||||
|
* @return The AMFValue
|
||||||
|
*/
|
||||||
|
template <typename AmfType>
|
||||||
|
AMFValue<AmfType>* Get(const std::string& key) const {
|
||||||
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
|
return it != this->associative.end() ?
|
||||||
|
dynamic_cast<AMFValue<AmfType>*>(it->second) :
|
||||||
|
nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get from the array but dont cast it
|
||||||
|
AMFBaseValue* Get(const std::string& key) const {
|
||||||
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
|
return it != this->associative.end() ? it->second : nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get an AMFValue object at a position in the dense portion.
|
||||||
|
* Gets an AMFValue by the index from the dense portion and converts it
|
||||||
|
* to the AmfValue template type. If the index did not exist, it is inserted.
|
||||||
|
*
|
||||||
|
* @tparam The target object type
|
||||||
|
* @param index The index to get
|
||||||
|
* @return The casted object, or nullptr.
|
||||||
|
*/
|
||||||
|
template <typename AmfType>
|
||||||
|
AMFValue<AmfType>* Get(uint32_t index) const {
|
||||||
|
return index < this->dense.size() ?
|
||||||
|
dynamic_cast<AMFValue<AmfType>*>(this->dense.at(index)) :
|
||||||
|
nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get from the dense but dont cast it
|
||||||
|
AMFBaseValue* Get(const uint32_t index) const {
|
||||||
|
return index < this->dense.size() ? this->dense.at(index) : nullptr;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* The associative portion. These values are key'd with strings to an AMFValue.
|
||||||
|
*/
|
||||||
|
AMFAssociative associative;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dense portion. These AMFValue's are stored one after
|
||||||
|
* another with the most recent addition being at the back.
|
||||||
|
*/
|
||||||
|
AMFDense dense;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__AMF3__H__
|
||||||
184
dCommon/AmfSerialize.cpp
Normal file
184
dCommon/AmfSerialize.cpp
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
#include "AmfSerialize.h"
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
|
||||||
|
// Writes an AMFValue pointer to a RakNet::BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value) {
|
||||||
|
eAmf type = value.GetValueType();
|
||||||
|
this->Write(type);
|
||||||
|
switch (type) {
|
||||||
|
case eAmf::Integer: {
|
||||||
|
this->Write<AMFIntValue&>(*static_cast<AMFIntValue*>(&value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::Double: {
|
||||||
|
this->Write<AMFDoubleValue&>(*static_cast<AMFDoubleValue*>(&value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::String: {
|
||||||
|
this->Write<AMFStringValue&>(*static_cast<AMFStringValue*>(&value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::Array: {
|
||||||
|
this->Write<AMFArrayValue&>(*static_cast<AMFArrayValue*>(&value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Game::logger->Log("AmfSerialize", "Encountered unwritable AMFType %i!", type);
|
||||||
|
}
|
||||||
|
case eAmf::Undefined:
|
||||||
|
case eAmf::Null:
|
||||||
|
case eAmf::False:
|
||||||
|
case eAmf::True:
|
||||||
|
case eAmf::Date:
|
||||||
|
case eAmf::Object:
|
||||||
|
case eAmf::XML:
|
||||||
|
case eAmf::XMLDoc:
|
||||||
|
case eAmf::ByteArray:
|
||||||
|
case eAmf::VectorInt:
|
||||||
|
case eAmf::VectorUInt:
|
||||||
|
case eAmf::VectorDouble:
|
||||||
|
case eAmf::VectorObject:
|
||||||
|
case eAmf::Dictionary:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A private function to write an value to a RakNet::BitStream
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
|
||||||
|
unsigned char b4 = (unsigned char)v;
|
||||||
|
if (v < 0x00200000) {
|
||||||
|
b4 = b4 & 0x7F;
|
||||||
|
if (v > 0x7F) {
|
||||||
|
unsigned char b3;
|
||||||
|
v = v >> 7;
|
||||||
|
b3 = ((unsigned char)(v)) | 0x80;
|
||||||
|
if (v > 0x7F) {
|
||||||
|
unsigned char b2;
|
||||||
|
v = v >> 7;
|
||||||
|
b2 = ((unsigned char)(v)) | 0x80;
|
||||||
|
bs->Write(b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bs->Write(b3);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned char b1;
|
||||||
|
unsigned char b2;
|
||||||
|
unsigned char b3;
|
||||||
|
|
||||||
|
v = v >> 8;
|
||||||
|
b3 = ((unsigned char)(v)) | 0x80;
|
||||||
|
v = v >> 7;
|
||||||
|
b2 = ((unsigned char)(v)) | 0x80;
|
||||||
|
v = v >> 7;
|
||||||
|
b1 = ((unsigned char)(v)) | 0x80;
|
||||||
|
|
||||||
|
bs->Write(b1);
|
||||||
|
bs->Write(b2);
|
||||||
|
bs->Write(b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
bs->Write(b4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a flag number to a RakNet::BitStream
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
|
||||||
|
v = (v << 1) | 0x01;
|
||||||
|
WriteUInt29(bs, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an AMFString to a RakNet::BitStream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
|
||||||
|
WriteFlagNumber(bs, (uint32_t)str.size());
|
||||||
|
bs->Write(str.c_str(), (uint32_t)str.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an U16 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
|
||||||
|
bs->Write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an U32 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
|
||||||
|
bs->Write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an U64 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
|
||||||
|
bs->Write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an AMFIntegerValue to BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFIntValue&>(AMFIntValue& value) {
|
||||||
|
WriteUInt29(this, value.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an AMFDoubleValue to BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFDoubleValue&>(AMFDoubleValue& value) {
|
||||||
|
double d = value.GetValue();
|
||||||
|
WriteAMFU64(this, *reinterpret_cast<uint64_t*>(&d));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an AMFStringValue to BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFStringValue&>(AMFStringValue& value) {
|
||||||
|
WriteAMFString(this, value.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an AMFArrayValue to BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFArrayValue&>(AMFArrayValue& value) {
|
||||||
|
uint32_t denseSize = value.GetDense().size();
|
||||||
|
WriteFlagNumber(this, denseSize);
|
||||||
|
|
||||||
|
auto it = value.GetAssociative().begin();
|
||||||
|
auto end = value.GetAssociative().end();
|
||||||
|
|
||||||
|
while (it != end) {
|
||||||
|
WriteAMFString(this, it->first);
|
||||||
|
this->Write<AMFBaseValue&>(*it->second);
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Write(eAmf::Null);
|
||||||
|
|
||||||
|
if (denseSize > 0) {
|
||||||
|
auto it2 = value.GetDense().begin();
|
||||||
|
auto end2 = value.GetDense().end();
|
||||||
|
|
||||||
|
while (it2 != end2) {
|
||||||
|
this->Write<AMFBaseValue&>(**it2);
|
||||||
|
it2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
dCommon/AmfSerialize.h
Normal file
50
dCommon/AmfSerialize.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Custom Classes
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
|
// RakNet
|
||||||
|
#include <BitStream.h>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file AmfSerialize.h
|
||||||
|
\brief A class that implements native writing of AMF values to RakNet::BitStream
|
||||||
|
*/
|
||||||
|
|
||||||
|
// We are using the RakNet namespace
|
||||||
|
namespace RakNet {
|
||||||
|
//! Writes an AMFValue pointer to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value);
|
||||||
|
|
||||||
|
//! Writes an AMFIntegerValue to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFIntValue&>(AMFIntValue& value);
|
||||||
|
|
||||||
|
//! Writes an AMFDoubleValue to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFDoubleValue&>(AMFDoubleValue& value);
|
||||||
|
|
||||||
|
//! Writes an AMFStringValue to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFStringValue&>(AMFStringValue& value);
|
||||||
|
|
||||||
|
//! Writes an AMFArrayValue to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFArrayValue&>(AMFArrayValue& value);
|
||||||
|
} // namespace RakNet
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
set(DCOMMON_SOURCES "AMFFormat.cpp"
|
set(DCOMMON_SOURCES
|
||||||
"AMFDeserialize.cpp"
|
"AMFDeserialize.cpp"
|
||||||
"AMFFormat_BitStream.cpp"
|
"AmfSerialize.cpp"
|
||||||
"BinaryIO.cpp"
|
"BinaryIO.cpp"
|
||||||
"dConfig.cpp"
|
"dConfig.cpp"
|
||||||
"Diagnostics.cpp"
|
"Diagnostics.cpp"
|
||||||
@@ -12,7 +12,7 @@ set(DCOMMON_SOURCES "AMFFormat.cpp"
|
|||||||
"NiPoint3.cpp"
|
"NiPoint3.cpp"
|
||||||
"NiQuaternion.cpp"
|
"NiQuaternion.cpp"
|
||||||
"SHA512.cpp"
|
"SHA512.cpp"
|
||||||
"Type.cpp"
|
"Demangler.cpp"
|
||||||
"ZCompression.cpp"
|
"ZCompression.cpp"
|
||||||
"BrickByBrickFix.cpp"
|
"BrickByBrickFix.cpp"
|
||||||
"BinaryPathFinder.cpp"
|
"BinaryPathFinder.cpp"
|
||||||
|
|||||||
29
dCommon/Demangler.cpp
Normal file
29
dCommon/Demangler.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "Demangler.h"
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cxxabi.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
std::string Demangler::Demangle(const char* name) {
|
||||||
|
// some arbitrary value to eliminate the compiler warning
|
||||||
|
// -4 is not a valid return value for __cxa_demangle so we'll use that.
|
||||||
|
int status = -4;
|
||||||
|
|
||||||
|
// __cxa_demangle requires that we free the returned char*
|
||||||
|
std::unique_ptr<char, void (*)(void*)> res{
|
||||||
|
abi::__cxa_demangle(name, NULL, NULL, &status),
|
||||||
|
std::free
|
||||||
|
};
|
||||||
|
|
||||||
|
return (status == 0) ? res.get() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // __GNUG__
|
||||||
|
|
||||||
|
// does nothing if not g++
|
||||||
|
std::string Demangler::Demangle(const char* name) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __GNUG__
|
||||||
9
dCommon/Demangler.h
Normal file
9
dCommon/Demangler.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Demangler {
|
||||||
|
// Given a char* containing a mangled name, return a std::string containing the demangled name.
|
||||||
|
// If the function fails for any reason, it returns an empty string.
|
||||||
|
std::string Demangle(const char* name);
|
||||||
|
}
|
||||||
@@ -107,7 +107,7 @@ static void ErrorCallback(void* data, const char* msg, int errnum) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Type.h"
|
#include "Demangler.h"
|
||||||
|
|
||||||
void GenerateDump() {
|
void GenerateDump() {
|
||||||
std::string cmd = "sudo gcore " + std::to_string(getpid());
|
std::string cmd = "sudo gcore " + std::to_string(getpid());
|
||||||
@@ -122,41 +122,43 @@ void CatchUnhandled(int sig) {
|
|||||||
if (Diagnostics::GetProduceMemoryDump()) {
|
if (Diagnostics::GetProduceMemoryDump()) {
|
||||||
GenerateDump();
|
GenerateDump();
|
||||||
}
|
}
|
||||||
|
constexpr uint8_t MaxStackTrace = 32;
|
||||||
void* array[10];
|
void* array[MaxStackTrace];
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
// get void*'s for all entries on the stack
|
// get void*'s for all entries on the stack
|
||||||
size = backtrace(array, 10);
|
size = backtrace(array, MaxStackTrace);
|
||||||
|
|
||||||
#if defined(__GNUG__) and defined(__dynamic)
|
# if defined(__GNUG__)
|
||||||
|
|
||||||
// Loop through the returned addresses, and get the symbols to be demangled
|
// Loop through the returned addresses, and get the symbols to be demangled
|
||||||
char** strings = backtrace_symbols(array, size);
|
char** strings = backtrace_symbols(array, size);
|
||||||
|
|
||||||
// Print the stack trace
|
// Print the stack trace
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]' and extract the function name
|
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]'
|
||||||
|
// and extract '_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress' from it to be demangled into a proper name
|
||||||
std::string functionName = strings[i];
|
std::string functionName = strings[i];
|
||||||
std::string::size_type start = functionName.find('(');
|
std::string::size_type start = functionName.find('(');
|
||||||
std::string::size_type end = functionName.find('+');
|
std::string::size_type end = functionName.find('+');
|
||||||
if (start != std::string::npos && end != std::string::npos) {
|
if (start != std::string::npos && end != std::string::npos) {
|
||||||
std::string demangled = functionName.substr(start + 1, end - start - 1);
|
std::string demangled = functionName.substr(start + 1, end - start - 1);
|
||||||
|
|
||||||
demangled = demangle(functionName.c_str());
|
demangled = Demangler::Demangle(demangled.c_str());
|
||||||
|
|
||||||
if (demangled.empty()) {
|
// If the demangled string is not empty, then we can replace the mangled string with the demangled one
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, demangled.c_str());
|
if (!demangled.empty()) {
|
||||||
} else {
|
demangled.push_back('(');
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
demangled += functionName.substr(end);
|
||||||
|
functionName = demangled;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
||||||
}
|
}
|
||||||
#else
|
# else // defined(__GNUG__)
|
||||||
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
||||||
#endif
|
# endif // defined(__GNUG__)
|
||||||
|
|
||||||
FILE* file = fopen(fileName.c_str(), "w+");
|
FILE* file = fopen(fileName.c_str(), "w+");
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
@@ -166,7 +168,7 @@ void CatchUnhandled(int sig) {
|
|||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else // __include_backtrace__
|
||||||
|
|
||||||
struct backtrace_state* state = backtrace_create_state(
|
struct backtrace_state* state = backtrace_create_state(
|
||||||
Diagnostics::GetProcessFileName().c_str(),
|
Diagnostics::GetProcessFileName().c_str(),
|
||||||
@@ -177,7 +179,7 @@ void CatchUnhandled(int sig) {
|
|||||||
struct bt_ctx ctx = { state, 0 };
|
struct bt_ctx ctx = { state, 0 };
|
||||||
Bt(state);
|
Bt(state);
|
||||||
|
|
||||||
#endif
|
#endif // __include_backtrace__
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
12
dCommon/DluAssert.h
Normal file
12
dCommon/DluAssert.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef __DLUASSERT__H__
|
||||||
|
#define __DLUASSERT__H__
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
# define DluAssert(expression) assert(expression)
|
||||||
|
#else
|
||||||
|
# define DluAssert(expression)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //!__DLUASSERT__H__
|
||||||
@@ -10,6 +10,8 @@ class dConfig;
|
|||||||
class RakPeerInterface;
|
class RakPeerInterface;
|
||||||
class AssetManager;
|
class AssetManager;
|
||||||
struct SystemAddress;
|
struct SystemAddress;
|
||||||
|
class EntityManager;
|
||||||
|
class dZoneManager;
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
extern dLogger* logger;
|
extern dLogger* logger;
|
||||||
@@ -22,4 +24,6 @@ namespace Game {
|
|||||||
extern AssetManager* assetManager;
|
extern AssetManager* assetManager;
|
||||||
extern SystemAddress chatSysAddr;
|
extern SystemAddress chatSysAddr;
|
||||||
extern bool shouldShutdown;
|
extern bool shouldShutdown;
|
||||||
|
extern EntityManager* entityManager;
|
||||||
|
extern dZoneManager* zoneManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,29 +111,6 @@ namespace GeneralUtils {
|
|||||||
*/
|
*/
|
||||||
bool CheckBit(int64_t value, uint32_t index);
|
bool CheckBit(int64_t value, uint32_t index);
|
||||||
|
|
||||||
// MARK: Random Number Generation
|
|
||||||
|
|
||||||
//! Generates a random number
|
|
||||||
/*!
|
|
||||||
\param min The minimum the generate from
|
|
||||||
\param max The maximum to generate to
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
|
||||||
// Make sure it is a numeric type
|
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
|
||||||
|
|
||||||
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
|
||||||
std::uniform_int_distribution<T> distribution(min, max);
|
|
||||||
return distribution(Game::randomEngine);
|
|
||||||
} else if (std::is_floating_point_v<T>) {
|
|
||||||
std::uniform_real_distribution<T> distribution(min, max);
|
|
||||||
return distribution(Game::randomEngine);
|
|
||||||
}
|
|
||||||
|
|
||||||
return T();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
std::u16string ReadWString(RakNet::BitStream* inStream);
|
std::u16string ReadWString(RakNet::BitStream* inStream);
|
||||||
@@ -149,6 +126,11 @@ namespace GeneralUtils {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T Parse(const char* value);
|
T Parse(const char* value);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool Parse(const char* value) {
|
||||||
|
return std::stoi(value);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int32_t Parse(const char* value) {
|
inline int32_t Parse(const char* value) {
|
||||||
return std::stoi(value);
|
return std::stoi(value);
|
||||||
@@ -223,4 +205,42 @@ namespace GeneralUtils {
|
|||||||
std::hash<T> h;
|
std::hash<T> h;
|
||||||
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Random Number Generation
|
||||||
|
|
||||||
|
//! Generates a random number
|
||||||
|
/*!
|
||||||
|
\param min The minimum the generate from
|
||||||
|
\param max The maximum to generate to
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
||||||
|
// Make sure it is a numeric type
|
||||||
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
|
|
||||||
|
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
||||||
|
std::uniform_int_distribution<T> distribution(min, max);
|
||||||
|
return distribution(Game::randomEngine);
|
||||||
|
} else if (std::is_floating_point_v<T>) {
|
||||||
|
std::uniform_real_distribution<T> distribution(min, max);
|
||||||
|
return distribution(Game::randomEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// on Windows we need to undef these or else they conflict with our numeric limits calls
|
||||||
|
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
|
||||||
|
#ifdef _WIN32
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T GenerateRandomNumber() {
|
||||||
|
// Make sure it is a numeric type
|
||||||
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
|
|
||||||
|
return GenerateRandomNumber<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,35 +61,33 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_S32: {
|
case LDF_TYPE_S32: {
|
||||||
try {
|
int32_t data;
|
||||||
int32_t data = static_cast<int32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<int32_t>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<int32_t>(key, data);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_FLOAT: {
|
case LDF_TYPE_FLOAT: {
|
||||||
try {
|
float data;
|
||||||
float data = strtof(ldfTypeAndValue.second.data(), &storage);
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<float>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<float>(key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_DOUBLE: {
|
case LDF_TYPE_DOUBLE: {
|
||||||
try {
|
double data;
|
||||||
double data = strtod(ldfTypeAndValue.second.data(), &storage);
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<double>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<double>(key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,9 +100,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
} else if (ldfTypeAndValue.second == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = 0;
|
data = 0;
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
data = static_cast<uint32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -122,9 +118,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
} else if (ldfTypeAndValue.second == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = false;
|
data = false;
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
data = static_cast<bool>(strtol(ldfTypeAndValue.second.data(), &storage, 10));
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -135,24 +129,22 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_U64: {
|
case LDF_TYPE_U64: {
|
||||||
try {
|
uint64_t data;
|
||||||
uint64_t data = static_cast<uint64_t>(strtoull(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<uint64_t>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<uint64_t>(key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_OBJID: {
|
case LDF_TYPE_OBJID: {
|
||||||
try {
|
LWOOBJID data;
|
||||||
LWOOBJID data = static_cast<LWOOBJID>(strtoll(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<LWOOBJID>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<LWOOBJID>(key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,10 +129,19 @@ NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Operator for addition of vectors
|
//! Operator for addition of vectors
|
||||||
NiPoint3 NiPoint3::operator+=(const NiPoint3& point) const {
|
NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
|
||||||
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
|
this->x += point.x;
|
||||||
|
this->y += point.y;
|
||||||
|
this->z += point.z;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NiPoint3& NiPoint3::operator*=(const float scalar) {
|
||||||
|
this->x *= scalar;
|
||||||
|
this->y *= scalar;
|
||||||
|
this->z *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//! Operator for subtraction of vectors
|
//! Operator for subtraction of vectors
|
||||||
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
|
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
|
||||||
|
|||||||
@@ -136,7 +136,9 @@ public:
|
|||||||
NiPoint3 operator+(const NiPoint3& point) const;
|
NiPoint3 operator+(const NiPoint3& point) const;
|
||||||
|
|
||||||
//! Operator for addition of vectors
|
//! Operator for addition of vectors
|
||||||
NiPoint3 operator+=(const NiPoint3& point) const;
|
NiPoint3& operator+=(const NiPoint3& point);
|
||||||
|
|
||||||
|
NiPoint3& operator*=(const float scalar);
|
||||||
|
|
||||||
//! Operator for subtraction of vectors
|
//! Operator for subtraction of vectors
|
||||||
NiPoint3 operator-(const NiPoint3& point) const;
|
NiPoint3 operator-(const NiPoint3& point) const;
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#include "Type.h"
|
|
||||||
#ifdef __GNUG__
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <memory>
|
|
||||||
#include <cxxabi.h>
|
|
||||||
|
|
||||||
std::string demangle(const char* name) {
|
|
||||||
|
|
||||||
int status = -4; // some arbitrary value to eliminate the compiler warning
|
|
||||||
|
|
||||||
// enable c++11 by passing the flag -std=c++11 to g++
|
|
||||||
std::unique_ptr<char, void(*)(void*)> res{
|
|
||||||
abi::__cxa_demangle(name, NULL, NULL, &status),
|
|
||||||
std::free
|
|
||||||
};
|
|
||||||
|
|
||||||
return (status == 0) ? res.get() : name;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// does nothing if not g++
|
|
||||||
std::string demangle(const char* name) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <typeinfo>
|
|
||||||
|
|
||||||
std::string demangle(const char* name);
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
std::string type(const T& t) {
|
|
||||||
|
|
||||||
return demangle(typeid(t).name());
|
|
||||||
}
|
|
||||||
@@ -42,7 +42,7 @@ struct AssetMemoryBuffer : std::streambuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
delete m_Base;
|
free(m_Base);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eClientMessageType.h"
|
#include "eClientMessageType.h"
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
|
|
||||||
#pragma warning (disable:4251) //Disables SQL warnings
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
|
|||||||
#define CBITSTREAM RakNet::BitStream bitStream;
|
#define CBITSTREAM RakNet::BitStream bitStream;
|
||||||
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
||||||
#define CMSGHEADER PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||||
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
|
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
|
||||||
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -101,13 +101,13 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
TRADE,
|
TRADE,
|
||||||
USER_CONTROL,
|
USER_CONTROL,
|
||||||
IGNORE_LIST,
|
IGNORE_LIST,
|
||||||
ROCKET_LAUNCH_LUP,
|
MULTI_ZONE_ENTRANCE,
|
||||||
BUFF_REAL, // the real buff component, should just be name BUFF
|
BUFF_REAL, // the real buff component, should just be name BUFF
|
||||||
INTERACTION_MANAGER,
|
INTERACTION_MANAGER,
|
||||||
DONATION_VENDOR,
|
DONATION_VENDOR,
|
||||||
COMBAT_MEDIATOR,
|
COMBAT_MEDIATOR,
|
||||||
COMMENDATION_VENDOR,
|
COMMENDATION_VENDOR,
|
||||||
UNKNOWN_103,
|
GATE_RUSH_CONTROL,
|
||||||
RAIL_ACTIVATOR,
|
RAIL_ACTIVATOR,
|
||||||
ROLLER,
|
ROLLER,
|
||||||
PLAYER_FORCED_MOVEMENT,
|
PLAYER_FORCED_MOVEMENT,
|
||||||
@@ -119,7 +119,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
UNKNOWN_112,
|
UNKNOWN_112,
|
||||||
PROPERTY_PLAQUE,
|
PROPERTY_PLAQUE,
|
||||||
BUILD_BORDER,
|
BUILD_BORDER,
|
||||||
UNKOWN_115,
|
UNKNOWN_115,
|
||||||
CULLING_PLANE,
|
CULLING_PLANE,
|
||||||
DESTROYABLE = 1000 // Actually 7
|
DESTROYABLE = 1000 // Actually 7
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,18 +13,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// Enable this to cache all entries in each table for fast access, comes with more memory cost
|
//! The CDClient Database namespace
|
||||||
//#define CDCLIENT_CACHE_ALL
|
|
||||||
|
|
||||||
// Enable this to skip some unused columns in some tables
|
|
||||||
#define UNUSED(v)
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file CDClientDatabase.hpp
|
|
||||||
\brief An interface between the CDClient.sqlite file and the server
|
|
||||||
*/
|
|
||||||
|
|
||||||
//! The CDClient Database namespace
|
|
||||||
namespace CDClientDatabase {
|
namespace CDClientDatabase {
|
||||||
|
|
||||||
//! Opens a connection with the CDClient
|
//! Opens a connection with the CDClient
|
||||||
|
|||||||
@@ -38,43 +38,53 @@
|
|||||||
#include "CDFeatureGatingTable.h"
|
#include "CDFeatureGatingTable.h"
|
||||||
#include "CDRailActivatorComponent.h"
|
#include "CDRailActivatorComponent.h"
|
||||||
|
|
||||||
|
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
||||||
|
// A vanilla CDClient takes about 46MB of memory + the regular world data.
|
||||||
|
// #define CDCLIENT_CACHE_ALL
|
||||||
|
|
||||||
|
#ifdef CDCLIENT_CACHE_ALL
|
||||||
|
#define CDCLIENT_DONT_CACHE_TABLE(x) x
|
||||||
|
#else
|
||||||
|
#define CDCLIENT_DONT_CACHE_TABLE(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
CDClientManager::CDClientManager() {
|
CDClientManager::CDClientManager() {
|
||||||
CDActivityRewardsTable::Instance();
|
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
|
||||||
UNUSED(CDAnimationsTable::Instance());
|
CDActivitiesTable::Instance().LoadValuesFromDatabase();
|
||||||
CDBehaviorParameterTable::Instance();
|
CDCLIENT_DONT_CACHE_TABLE(CDAnimationsTable::Instance().LoadValuesFromDatabase());
|
||||||
CDBehaviorTemplateTable::Instance();
|
CDBehaviorParameterTable::Instance().LoadValuesFromDatabase();
|
||||||
CDComponentsRegistryTable::Instance();
|
CDBehaviorTemplateTable::Instance().LoadValuesFromDatabase();
|
||||||
CDCurrencyTableTable::Instance();
|
CDBrickIDTableTable::Instance().LoadValuesFromDatabase();
|
||||||
CDDestructibleComponentTable::Instance();
|
CDCLIENT_DONT_CACHE_TABLE(CDComponentsRegistryTable::Instance().LoadValuesFromDatabase());
|
||||||
CDEmoteTableTable::Instance();
|
CDCurrencyTableTable::Instance().LoadValuesFromDatabase();
|
||||||
CDInventoryComponentTable::Instance();
|
CDDestructibleComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDItemComponentTable::Instance();
|
CDEmoteTableTable::Instance().LoadValuesFromDatabase();
|
||||||
CDItemSetsTable::Instance();
|
CDFeatureGatingTable::Instance().LoadValuesFromDatabase();
|
||||||
CDItemSetSkillsTable::Instance();
|
CDInventoryComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDLevelProgressionLookupTable::Instance();
|
CDCLIENT_DONT_CACHE_TABLE(CDItemComponentTable::Instance().LoadValuesFromDatabase());
|
||||||
CDLootMatrixTable::Instance();
|
CDItemSetSkillsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDLootTableTable::Instance();
|
CDItemSetsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDMissionNPCComponentTable::Instance();
|
CDLevelProgressionLookupTable::Instance().LoadValuesFromDatabase();
|
||||||
CDMissionTasksTable::Instance();
|
CDCLIENT_DONT_CACHE_TABLE(CDLootMatrixTable::Instance().LoadValuesFromDatabase());
|
||||||
CDMissionsTable::Instance();
|
CDCLIENT_DONT_CACHE_TABLE(CDLootTableTable::Instance().LoadValuesFromDatabase());
|
||||||
CDObjectSkillsTable::Instance();
|
CDMissionEmailTable::Instance().LoadValuesFromDatabase();
|
||||||
CDObjectsTable::Instance();
|
CDMissionNPCComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDPhysicsComponentTable::Instance();
|
CDMissionTasksTable::Instance().LoadValuesFromDatabase();
|
||||||
CDRebuildComponentTable::Instance();
|
CDMissionsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDScriptComponentTable::Instance();
|
CDMovementAIComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDSkillBehaviorTable::Instance();
|
CDObjectSkillsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDZoneTableTable::Instance();
|
CDCLIENT_DONT_CACHE_TABLE(CDObjectsTable::Instance().LoadValuesFromDatabase());
|
||||||
CDVendorComponentTable::Instance();
|
CDPhysicsComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDActivitiesTable::Instance();
|
CDPackageComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDPackageComponentTable::Instance();
|
CDProximityMonitorComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDProximityMonitorComponentTable::Instance();
|
CDPropertyEntranceComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDMovementAIComponentTable::Instance();
|
CDPropertyTemplateTable::Instance().LoadValuesFromDatabase();
|
||||||
CDBrickIDTableTable::Instance();
|
CDRailActivatorComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDRarityTableTable::Instance();
|
CDRarityTableTable::Instance().LoadValuesFromDatabase();
|
||||||
CDMissionEmailTable::Instance();
|
CDRebuildComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDRewardsTable::Instance();
|
CDRewardsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDPropertyEntranceComponentTable::Instance();
|
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDPropertyTemplateTable::Instance();
|
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
|
||||||
CDFeatureGatingTable::Instance();
|
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDRailActivatorComponentTable::Instance();
|
CDZoneTableTable::Instance().LoadValuesFromDatabase();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "Singleton.h"
|
#include "Singleton.h"
|
||||||
|
|
||||||
|
#define UNUSED_TABLE(v)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the CDClient tables so they are all loaded into memory.
|
* Initialize the CDClient tables so they are all loaded into memory.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
|
|
||||||
CDActivitiesTable::CDActivitiesTable(void) {
|
void CDActivitiesTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Activities");
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Activities");
|
||||||
@@ -55,8 +54,3 @@ std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActiviti
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDActivities> CDActivitiesTable::GetEntries(void) const {
|
|
||||||
return this->entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ private:
|
|||||||
std::vector<CDActivities> entries;
|
std::vector<CDActivities> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDActivitiesTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
|
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
|
||||||
|
|
||||||
std::vector<CDActivities> GetEntries(void) const;
|
const std::vector<CDActivities>& GetEntries() const { return this->entries; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDActivityRewardsTable.h"
|
#include "CDActivityRewardsTable.h"
|
||||||
|
|
||||||
CDActivityRewardsTable::CDActivityRewardsTable(void) {
|
void CDActivityRewardsTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -43,8 +43,3 @@ std::vector<CDActivityRewards> CDActivityRewardsTable::Query(std::function<bool(
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDActivityRewards> CDActivityRewardsTable::GetEntries(void) const {
|
|
||||||
return this->entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ private:
|
|||||||
std::vector<CDActivityRewards> entries;
|
std::vector<CDActivityRewards> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDActivityRewardsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
|
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
|
||||||
|
|
||||||
std::vector<CDActivityRewards> GetEntries(void) const;
|
std::vector<CDActivityRewards> GetEntries() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,56 +1,112 @@
|
|||||||
#include "CDAnimationsTable.h"
|
#include "CDAnimationsTable.h"
|
||||||
|
#include "GeneralUtils.h"
|
||||||
|
#include "Game.h"
|
||||||
|
|
||||||
CDAnimationsTable::CDAnimationsTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
void CDAnimationsTable::LoadValuesFromDatabase() {
|
||||||
unsigned int size = 0;
|
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Animations");
|
|
||||||
while (!tableSize.eof()) {
|
|
||||||
size = tableSize.getIntField(0, 0);
|
|
||||||
|
|
||||||
tableSize.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
tableSize.finalize();
|
|
||||||
|
|
||||||
// Reserve the size
|
|
||||||
this->entries.reserve(size);
|
|
||||||
|
|
||||||
// Now get the data
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDAnimations entry;
|
std::string animation_type = tableData.getStringField("animation_type", "");
|
||||||
entry.animationGroupID = tableData.getIntField("animationGroupID", -1);
|
DluAssert(!animation_type.empty());
|
||||||
entry.animation_type = tableData.getStringField("animation_type", "");
|
AnimationGroupID animationGroupID = tableData.getIntField("animationGroupID", -1);
|
||||||
entry.animation_name = tableData.getStringField("animation_name", "");
|
DluAssert(animationGroupID != -1);
|
||||||
entry.chance_to_play = tableData.getFloatField("chance_to_play", -1.0f);
|
|
||||||
entry.min_loops = tableData.getIntField("min_loops", -1);
|
|
||||||
entry.max_loops = tableData.getIntField("max_loops", -1);
|
|
||||||
entry.animation_length = tableData.getFloatField("animation_length", -1.0f);
|
|
||||||
entry.hideEquip = tableData.getIntField("hideEquip", -1) == 1 ? true : false;
|
|
||||||
entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", -1) == 1 ? true : false;
|
|
||||||
entry.restartable = tableData.getIntField("restartable", -1) == 1 ? true : false;
|
|
||||||
entry.face_animation_name = tableData.getStringField("face_animation_name", "");
|
|
||||||
entry.priority = tableData.getFloatField("priority", -1.0f);
|
|
||||||
entry.blendTime = tableData.getFloatField("blendTime", -1.0f);
|
|
||||||
|
|
||||||
this->entries.push_back(entry);
|
CDAnimation entry;
|
||||||
|
entry.animation_name = tableData.getStringField("animation_name", "");
|
||||||
|
entry.chance_to_play = tableData.getFloatField("chance_to_play", 1.0f);
|
||||||
|
UNUSED_COLUMN(entry.min_loops = tableData.getIntField("min_loops", 0);)
|
||||||
|
UNUSED_COLUMN(entry.max_loops = tableData.getIntField("max_loops", 0);)
|
||||||
|
entry.animation_length = tableData.getFloatField("animation_length", 0.0f);
|
||||||
|
UNUSED_COLUMN(entry.hideEquip = tableData.getIntField("hideEquip", 0) == 1;)
|
||||||
|
UNUSED_COLUMN(entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", 0) == 1;)
|
||||||
|
UNUSED_COLUMN(entry.restartable = tableData.getIntField("restartable", 0) == 1;)
|
||||||
|
UNUSED_COLUMN(entry.face_animation_name = tableData.getStringField("face_animation_name", "");)
|
||||||
|
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
|
||||||
|
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
|
||||||
|
|
||||||
|
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDAnimations> CDAnimationsTable::Query(std::function<bool(CDAnimations)> predicate) {
|
bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
|
||||||
|
auto tableData = queryToCache.execQuery();
|
||||||
|
// If we received a bad lookup, cache it anyways so we do not run the query again.
|
||||||
|
if (tableData.eof()) return false;
|
||||||
|
|
||||||
std::vector<CDAnimations> data = cpplinq::from(this->entries)
|
do {
|
||||||
>> cpplinq::where(predicate)
|
std::string animation_type = tableData.getStringField("animation_type", "");
|
||||||
>> cpplinq::to_vector();
|
DluAssert(!animation_type.empty());
|
||||||
|
AnimationGroupID animationGroupID = tableData.getIntField("animationGroupID", -1);
|
||||||
|
DluAssert(animationGroupID != -1);
|
||||||
|
|
||||||
return data;
|
CDAnimation entry;
|
||||||
|
entry.animation_name = tableData.getStringField("animation_name", "");
|
||||||
|
entry.chance_to_play = tableData.getFloatField("chance_to_play", 1.0f);
|
||||||
|
UNUSED_COLUMN(entry.min_loops = tableData.getIntField("min_loops", 0);)
|
||||||
|
UNUSED_COLUMN(entry.max_loops = tableData.getIntField("max_loops", 0);)
|
||||||
|
entry.animation_length = tableData.getFloatField("animation_length", 0.0f);
|
||||||
|
UNUSED_COLUMN(entry.hideEquip = tableData.getIntField("hideEquip", 0) == 1;)
|
||||||
|
UNUSED_COLUMN(entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", 0) == 1;)
|
||||||
|
UNUSED_COLUMN(entry.restartable = tableData.getIntField("restartable", 0) == 1;)
|
||||||
|
UNUSED_COLUMN(entry.face_animation_name = tableData.getStringField("face_animation_name", "");)
|
||||||
|
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
|
||||||
|
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
|
||||||
|
|
||||||
|
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
|
||||||
|
tableData.nextRow();
|
||||||
|
} while (!tableData.eof());
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDAnimations> CDAnimationsTable::GetEntries(void) const {
|
void CDAnimationsTable::CacheAnimations(const CDAnimationKey animationKey) {
|
||||||
return this->entries;
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ? and animation_type = ?");
|
||||||
|
query.bind(1, static_cast<int32_t>(animationKey.second));
|
||||||
|
query.bind(2, animationKey.first.c_str());
|
||||||
|
// If we received a bad lookup, cache it anyways so we do not run the query again.
|
||||||
|
if (!CacheData(query)) {
|
||||||
|
this->animations[animationKey];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) {
|
||||||
|
auto animationEntryCached = this->animations.find(CDAnimationKey("", animationGroupID));
|
||||||
|
if (animationEntryCached != this->animations.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ?");
|
||||||
|
query.bind(1, static_cast<int32_t>(animationGroupID));
|
||||||
|
|
||||||
|
// Cache the query so we don't run the query again.
|
||||||
|
CacheData(query);
|
||||||
|
this->animations[CDAnimationKey("", animationGroupID)];
|
||||||
|
}
|
||||||
|
|
||||||
|
CDAnimationLookupResult CDAnimationsTable::GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID) {
|
||||||
|
CDAnimationKey animationKey(animationType, animationGroupID);
|
||||||
|
auto animationEntryCached = this->animations.find(animationKey);
|
||||||
|
if (animationEntryCached == this->animations.end()) {
|
||||||
|
this->CacheAnimations(animationKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto animationEntry = this->animations.find(animationKey);
|
||||||
|
// If we have only one animation, return it regardless of the chance to play.
|
||||||
|
if (animationEntry->second.size() == 1) {
|
||||||
|
return CDAnimationLookupResult(animationEntry->second.front());
|
||||||
|
}
|
||||||
|
auto randomAnimation = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||||
|
|
||||||
|
for (auto& animationEntry : animationEntry->second) {
|
||||||
|
randomAnimation -= animationEntry.chance_to_play;
|
||||||
|
// This is how the client gets the random animation.
|
||||||
|
if (animationEntry.animation_name != previousAnimationName && randomAnimation <= 0.0f) return CDAnimationLookupResult(animationEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CDAnimationLookupResult();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,33 +1,67 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Custom Classes
|
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
struct CDAnimations {
|
struct CDAnimation {
|
||||||
unsigned int animationGroupID; //!< The animation group ID
|
// unsigned int animationGroupID;
|
||||||
std::string animation_type; //!< The animation type
|
// std::string animation_type;
|
||||||
|
// The above two are a pair to represent a primary key in the map.
|
||||||
std::string animation_name; //!< The animation name
|
std::string animation_name; //!< The animation name
|
||||||
float chance_to_play; //!< The chance to play the animation
|
float chance_to_play; //!< The chance to play the animation
|
||||||
unsigned int min_loops; //!< The minimum number of loops
|
UNUSED_COLUMN(unsigned int min_loops;) //!< The minimum number of loops
|
||||||
unsigned int max_loops; //!< The maximum number of loops
|
UNUSED_COLUMN(unsigned int max_loops;) //!< The maximum number of loops
|
||||||
float animation_length; //!< The animation length
|
float animation_length; //!< The animation length
|
||||||
bool hideEquip; //!< Whether or not to hide the equip
|
UNUSED_COLUMN(bool hideEquip;) //!< Whether or not to hide the equip
|
||||||
bool ignoreUpperBody; //!< Whether or not to ignore the upper body
|
UNUSED_COLUMN(bool ignoreUpperBody;) //!< Whether or not to ignore the upper body
|
||||||
bool restartable; //!< Whether or not the animation is restartable
|
UNUSED_COLUMN(bool restartable;) //!< Whether or not the animation is restartable
|
||||||
std::string face_animation_name; //!< The face animation name
|
UNUSED_COLUMN(std::string face_animation_name;) //!< The face animation name
|
||||||
float priority; //!< The priority
|
UNUSED_COLUMN(float priority;) //!< The priority
|
||||||
float blendTime; //!< The blend time
|
UNUSED_COLUMN(float blendTime;) //!< The blend time
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef LookupResult<CDAnimation> CDAnimationLookupResult;
|
||||||
|
|
||||||
class CDAnimationsTable : public CDTable<CDAnimationsTable> {
|
class CDAnimationsTable : public CDTable<CDAnimationsTable> {
|
||||||
private:
|
typedef int32_t AnimationGroupID;
|
||||||
std::vector<CDAnimations> entries;
|
typedef std::string AnimationID;
|
||||||
|
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
|
||||||
public:
|
public:
|
||||||
CDAnimationsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
/**
|
||||||
std::vector<CDAnimations> Query(std::function<bool(CDAnimations)> predicate);
|
* Given an animationType and the previousAnimationName played, return the next animationType to play.
|
||||||
|
* If there are more than 1 animationTypes that can be played, one is selected at random but also does not allow
|
||||||
|
* the previousAnimationName to be played twice.
|
||||||
|
*
|
||||||
|
* @param animationType The animationID to lookup
|
||||||
|
* @param previousAnimationName The previously played animation
|
||||||
|
* @param animationGroupID The animationGroupID to lookup
|
||||||
|
* @return CDAnimationLookupResult
|
||||||
|
*/
|
||||||
|
[[nodiscard]] CDAnimationLookupResult GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID);
|
||||||
|
|
||||||
std::vector<CDAnimations> GetEntries(void) const;
|
/**
|
||||||
|
* Cache a full AnimationGroup by its ID.
|
||||||
|
*/
|
||||||
|
void CacheAnimationGroup(AnimationGroupID animationGroupID);
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache all animations given a premade key
|
||||||
|
*/
|
||||||
|
void CacheAnimations(const CDAnimationKey animationKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the query responsible for caching the data.
|
||||||
|
* @param queryToCache
|
||||||
|
* @return true
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
bool CacheData(CppSQLite3Statement& queryToCache);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each animation is key'd by its animationName and its animationGroupID. Each
|
||||||
|
* animation has a possible list of animations. This is because there can be animations have a percent chance to play so one is selected at random.
|
||||||
|
*/
|
||||||
|
std::map<CDAnimationKey, std::list<CDAnimation>> animations;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
#include "CDBehaviorParameterTable.h"
|
#include "CDBehaviorParameterTable.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
|
uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
|
||||||
|
uint64_t key = behaviorID;
|
||||||
|
key <<= 31U;
|
||||||
|
key |= parameterID;
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDBehaviorParameterTable::LoadValuesFromDatabase() {
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
||||||
uint32_t uniqueParameterId = 0;
|
|
||||||
uint64_t hash = 0;
|
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDBehaviorParameter entry;
|
uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
|
||||||
entry.behaviorID = tableData.getIntField("behaviorID", -1);
|
|
||||||
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
|
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
|
||||||
auto parameter = m_ParametersList.find(candidateStringToAdd);
|
auto parameter = m_ParametersList.find(candidateStringToAdd);
|
||||||
|
uint32_t parameterId;
|
||||||
if (parameter != m_ParametersList.end()) {
|
if (parameter != m_ParametersList.end()) {
|
||||||
entry.parameterID = parameter;
|
parameterId = parameter->second;
|
||||||
} else {
|
} else {
|
||||||
entry.parameterID = m_ParametersList.insert(std::make_pair(candidateStringToAdd, uniqueParameterId)).first;
|
parameterId = m_ParametersList.insert(std::make_pair(candidateStringToAdd, m_ParametersList.size())).first->second;
|
||||||
uniqueParameterId++;
|
|
||||||
}
|
}
|
||||||
hash = entry.behaviorID;
|
uint64_t hash = GetKey(behaviorID, parameterId);
|
||||||
hash = (hash << 31U) | entry.parameterID->second;
|
float value = tableData.getFloatField("value", -1.0f);
|
||||||
entry.value = tableData.getFloatField("value", -1.0f);
|
|
||||||
|
|
||||||
m_Entries.insert(std::make_pair(hash, entry));
|
m_Entries.insert(std::make_pair(hash, value));
|
||||||
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
@@ -30,27 +34,22 @@ CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
|
|||||||
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
|
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
|
||||||
auto parameterID = this->m_ParametersList.find(name);
|
auto parameterID = this->m_ParametersList.find(name);
|
||||||
if (parameterID == this->m_ParametersList.end()) return defaultValue;
|
if (parameterID == this->m_ParametersList.end()) return defaultValue;
|
||||||
|
auto hash = GetKey(behaviorID, parameterID->second);
|
||||||
uint64_t hash = behaviorID;
|
|
||||||
|
|
||||||
hash = (hash << 31U) | parameterID->second;
|
|
||||||
|
|
||||||
// Search for specific parameter
|
// Search for specific parameter
|
||||||
const auto& it = m_Entries.find(hash);
|
auto it = m_Entries.find(hash);
|
||||||
return it != m_Entries.end() ? it->second.value : defaultValue;
|
return it != m_Entries.end() ? it->second : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
|
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
|
||||||
uint64_t hashBase = behaviorID;
|
uint64_t hashBase = behaviorID;
|
||||||
std::map<std::string, float> returnInfo;
|
std::map<std::string, float> returnInfo;
|
||||||
uint64_t hash;
|
for (auto& [parameterString, parameterId] : m_ParametersList) {
|
||||||
for (auto& parameterCandidate : m_ParametersList) {
|
uint64_t hash = GetKey(hashBase, parameterId);
|
||||||
hash = (hashBase << 31U) | parameterCandidate.second;
|
|
||||||
auto infoCandidate = m_Entries.find(hash);
|
auto infoCandidate = m_Entries.find(hash);
|
||||||
if (infoCandidate != m_Entries.end()) {
|
if (infoCandidate != m_Entries.end()) {
|
||||||
returnInfo.insert(std::make_pair(infoCandidate->second.parameterID->first, infoCandidate->second.value));
|
returnInfo.insert(std::make_pair(parameterString, infoCandidate->second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnInfo;
|
return returnInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,18 +5,15 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
struct CDBehaviorParameter {
|
|
||||||
unsigned int behaviorID; //!< The Behavior ID
|
|
||||||
std::unordered_map<std::string, uint32_t>::iterator parameterID; //!< The Parameter ID
|
|
||||||
float value; //!< The value of the behavior template
|
|
||||||
};
|
|
||||||
|
|
||||||
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> {
|
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint64_t, CDBehaviorParameter> m_Entries;
|
typedef uint64_t BehaviorParameterHash;
|
||||||
|
typedef float BehaviorParameterValue;
|
||||||
|
std::unordered_map<BehaviorParameterHash, BehaviorParameterValue> m_Entries;
|
||||||
std::unordered_map<std::string, uint32_t> m_ParametersList;
|
std::unordered_map<std::string, uint32_t> m_ParametersList;
|
||||||
public:
|
public:
|
||||||
CDBehaviorParameterTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
float GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0);
|
float GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0);
|
||||||
|
|
||||||
std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID);
|
std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDBehaviorTemplateTable.h"
|
#include "CDBehaviorTemplateTable.h"
|
||||||
|
|
||||||
CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) {
|
void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -48,7 +48,7 @@ std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::Query(std::function<boo
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::GetEntries(void) const {
|
const std::vector<CDBehaviorTemplate>& CDBehaviorTemplateTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,4 +64,3 @@ const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behav
|
|||||||
return entry->second;
|
return entry->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ private:
|
|||||||
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
|
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
|
||||||
std::unordered_set<std::string> m_EffectHandles;
|
std::unordered_set<std::string> m_EffectHandles;
|
||||||
public:
|
public:
|
||||||
CDBehaviorTemplateTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate);
|
std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate);
|
||||||
|
|
||||||
std::vector<CDBehaviorTemplate> GetEntries(void) const;
|
const std::vector<CDBehaviorTemplate>& GetEntries(void) const;
|
||||||
|
|
||||||
const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID);
|
const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDBrickIDTableTable.h"
|
#include "CDBrickIDTableTable.h"
|
||||||
|
|
||||||
CDBrickIDTableTable::CDBrickIDTableTable(void) {
|
void CDBrickIDTableTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -39,7 +39,7 @@ std::vector<CDBrickIDTable> CDBrickIDTableTable::Query(std::function<bool(CDBric
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDBrickIDTable> CDBrickIDTableTable::GetEntries(void) const {
|
const std::vector<CDBrickIDTable>& CDBrickIDTableTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ private:
|
|||||||
std::vector<CDBrickIDTable> entries;
|
std::vector<CDBrickIDTable> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDBrickIDTableTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
|
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
|
||||||
|
|
||||||
std::vector<CDBrickIDTable> GetEntries(void) const;
|
const std::vector<CDBrickIDTable>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,27 +1,37 @@
|
|||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
#define CDCLIENT_CACHE_ALL
|
void CDComponentsRegistryTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
|
|
||||||
|
|
||||||
#ifdef CDCLIENT_CACHE_ALL
|
|
||||||
// First, get the size of the table
|
|
||||||
unsigned int size = 0;
|
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ComponentsRegistry");
|
|
||||||
while (!tableSize.eof()) {
|
|
||||||
size = tableSize.getIntField(0, 0);
|
|
||||||
|
|
||||||
tableSize.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
tableSize.finalize();
|
|
||||||
|
|
||||||
// Reserve the size
|
|
||||||
//this->entries.reserve(size);
|
|
||||||
|
|
||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
CDComponentsRegistry entry;
|
||||||
|
entry.id = tableData.getIntField("id", -1);
|
||||||
|
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
|
||||||
|
entry.component_id = tableData.getIntField("component_id", -1);
|
||||||
|
|
||||||
|
this->mappedEntries.insert_or_assign(((uint64_t)entry.component_type) << 32 | ((uint64_t)entry.id), entry.component_id);
|
||||||
|
this->mappedEntries.insert_or_assign(entry.id, 0);
|
||||||
|
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
|
||||||
|
auto exists = mappedEntries.find(id);
|
||||||
|
if (exists != mappedEntries.end()) {
|
||||||
|
auto iter = mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
||||||
|
return iter == mappedEntries.end() ? defaultValue : iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now get the data. Get all components of this entity so we dont do a query for each component
|
||||||
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ComponentsRegistry WHERE id = ?;");
|
||||||
|
query.bind(1, static_cast<int32_t>(id));
|
||||||
|
|
||||||
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDComponentsRegistry entry;
|
CDComponentsRegistry entry;
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
@@ -33,61 +43,10 @@ CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
|
|||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
mappedEntries.insert_or_assign(id, 0);
|
||||||
#endif
|
|
||||||
}
|
auto iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
||||||
|
|
||||||
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
|
return iter == this->mappedEntries.end() ? defaultValue : iter->second;
|
||||||
const auto& iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
|
||||||
|
|
||||||
if (iter == this->mappedEntries.end()) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return iter->second;
|
|
||||||
|
|
||||||
#ifndef CDCLIENT_CACHE_ALL
|
|
||||||
// Now get the data
|
|
||||||
std::stringstream query;
|
|
||||||
|
|
||||||
query << "SELECT * FROM ComponentsRegistry WHERE id = " << std::to_string(id);
|
|
||||||
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
|
|
||||||
while (!tableData.eof()) {
|
|
||||||
CDComponentsRegistry entry;
|
|
||||||
entry.id = tableData.getIntField("id", -1);
|
|
||||||
entry.component_type = tableData.getIntField("component_type", -1);
|
|
||||||
entry.component_id = tableData.getIntField("component_id", -1);
|
|
||||||
|
|
||||||
//this->entries.push_back(entry);
|
|
||||||
|
|
||||||
//Darwin's stuff:
|
|
||||||
const auto& it = this->mappedEntries.find(entry.id);
|
|
||||||
if (it != mappedEntries.end()) {
|
|
||||||
const auto& iter = it->second.find(entry.component_type);
|
|
||||||
if (iter == it->second.end()) {
|
|
||||||
it->second.insert(std::make_pair(entry.component_type, entry.component_id));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::map<unsigned int, unsigned int> map;
|
|
||||||
map.insert(std::make_pair(entry.component_type, entry.component_id));
|
|
||||||
this->mappedEntries.insert(std::make_pair(entry.id, map));
|
|
||||||
}
|
|
||||||
|
|
||||||
tableData.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
tableData.finalize();
|
|
||||||
|
|
||||||
const auto& it2 = this->mappedEntries.find(id);
|
|
||||||
if (it2 != mappedEntries.end()) {
|
|
||||||
const auto& iter = it2->second.find(componentType);
|
|
||||||
if (iter != it2->second.end()) {
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultValue;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ struct CDComponentsRegistry {
|
|||||||
|
|
||||||
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
|
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
|
||||||
private:
|
private:
|
||||||
std::map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
|
std::unordered_map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDComponentsRegistryTable();
|
void LoadValuesFromDatabase();
|
||||||
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);
|
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "CDCurrencyTableTable.h"
|
#include "CDCurrencyTableTable.h"
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
CDCurrencyTableTable::CDCurrencyTableTable(void) {
|
void CDCurrencyTableTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -43,7 +43,7 @@ std::vector<CDCurrencyTable> CDCurrencyTableTable::Query(std::function<bool(CDCu
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDCurrencyTable> CDCurrencyTableTable::GetEntries(void) const {
|
const std::vector<CDCurrencyTable>& CDCurrencyTableTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ private:
|
|||||||
std::vector<CDCurrencyTable> entries;
|
std::vector<CDCurrencyTable> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDCurrencyTableTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
|
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
|
||||||
|
|
||||||
std::vector<CDCurrencyTable> GetEntries(void) const;
|
const std::vector<CDCurrencyTable>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "CDDestructibleComponentTable.h"
|
#include "CDDestructibleComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDDestructibleComponentTable::LoadValuesFromDatabase() {
|
||||||
CDDestructibleComponentTable::CDDestructibleComponentTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM DestructibleComponent");
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM DestructibleComponent");
|
||||||
@@ -52,7 +50,7 @@ std::vector<CDDestructibleComponent> CDDestructibleComponentTable::Query(std::fu
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDDestructibleComponent> CDDestructibleComponentTable::GetEntries(void) const {
|
const std::vector<CDDestructibleComponent>& CDDestructibleComponentTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ private:
|
|||||||
std::vector<CDDestructibleComponent> entries;
|
std::vector<CDDestructibleComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDDestructibleComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
|
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
|
||||||
|
|
||||||
std::vector<CDDestructibleComponent> GetEntries(void) const;
|
const std::vector<CDDestructibleComponent>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,40 +1,26 @@
|
|||||||
#include "CDEmoteTable.h"
|
#include "CDEmoteTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDEmoteTableTable::LoadValuesFromDatabase() {
|
||||||
CDEmoteTableTable::CDEmoteTableTable(void) {
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDEmoteTable* entry = new CDEmoteTable();
|
CDEmoteTable entry;
|
||||||
entry->ID = tableData.getIntField("id", -1);
|
entry.ID = tableData.getIntField("id", -1);
|
||||||
entry->animationName = tableData.getStringField("animationName", "");
|
entry.animationName = tableData.getStringField("animationName", "");
|
||||||
entry->iconFilename = tableData.getStringField("iconFilename", "");
|
entry.iconFilename = tableData.getStringField("iconFilename", "");
|
||||||
entry->channel = tableData.getIntField("channel", -1);
|
entry.channel = tableData.getIntField("channel", -1);
|
||||||
entry->locked = tableData.getIntField("locked", -1) != 0;
|
entry.locked = tableData.getIntField("locked", -1) != 0;
|
||||||
entry->localize = tableData.getIntField("localize", -1) != 0;
|
entry.localize = tableData.getIntField("localize", -1) != 0;
|
||||||
entry->locState = tableData.getIntField("locStatus", -1);
|
entry.locState = tableData.getIntField("locStatus", -1);
|
||||||
entry->gateVersion = tableData.getStringField("gate_version", "");
|
entry.gateVersion = tableData.getStringField("gate_version", "");
|
||||||
|
|
||||||
entries.insert(std::make_pair(entry->ID, entry));
|
entries.insert(std::make_pair(entry.ID, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
|
||||||
CDEmoteTableTable::~CDEmoteTableTable(void) {
|
|
||||||
for (auto e : entries) {
|
|
||||||
if (e.second) delete e.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
CDEmoteTable* CDEmoteTableTable::GetEmote(int id) {
|
CDEmoteTable* CDEmoteTableTable::GetEmote(int id) {
|
||||||
for (auto e : entries) {
|
auto itr = entries.find(id);
|
||||||
if (e.first == id) return e.second;
|
return itr != entries.end() ? &itr->second : nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,10 @@ struct CDEmoteTable {
|
|||||||
|
|
||||||
class CDEmoteTableTable : public CDTable<CDEmoteTableTable> {
|
class CDEmoteTableTable : public CDTable<CDEmoteTableTable> {
|
||||||
private:
|
private:
|
||||||
std::map<int, CDEmoteTable*> entries;
|
std::map<int, CDEmoteTable> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDEmoteTableTable();
|
void LoadValuesFromDatabase();
|
||||||
~CDEmoteTableTable();
|
|
||||||
// Returns an emote by ID
|
// Returns an emote by ID
|
||||||
CDEmoteTable* GetEmote(int id);
|
CDEmoteTable* GetEmote(int id);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDFeatureGatingTable.h"
|
#include "CDFeatureGatingTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDFeatureGatingTable::LoadValuesFromDatabase() {
|
||||||
CDFeatureGatingTable::CDFeatureGatingTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -53,7 +52,7 @@ bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDFeatureGating> CDFeatureGatingTable::GetEntries(void) const {
|
const std::vector<CDFeatureGating>& CDFeatureGatingTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ private:
|
|||||||
std::vector<CDFeatureGating> entries;
|
std::vector<CDFeatureGating> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDFeatureGatingTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate);
|
std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate);
|
||||||
|
|
||||||
bool FeatureUnlocked(const std::string& feature) const;
|
bool FeatureUnlocked(const std::string& feature) const;
|
||||||
|
|
||||||
std::vector<CDFeatureGating> GetEntries(void) const;
|
const std::vector<CDFeatureGating>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDInventoryComponentTable.h"
|
#include "CDInventoryComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDInventoryComponentTable::LoadValuesFromDatabase() {
|
||||||
CDInventoryComponentTable::CDInventoryComponentTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -42,7 +41,7 @@ std::vector<CDInventoryComponent> CDInventoryComponentTable::Query(std::function
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDInventoryComponent> CDInventoryComponentTable::GetEntries(void) const {
|
const std::vector<CDInventoryComponent>& CDInventoryComponentTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ private:
|
|||||||
std::vector<CDInventoryComponent> entries;
|
std::vector<CDInventoryComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDInventoryComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
|
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
|
||||||
|
|
||||||
std::vector<CDInventoryComponent> GetEntries(void) const;
|
const std::vector<CDInventoryComponent>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,11 +3,7 @@
|
|||||||
|
|
||||||
CDItemComponent CDItemComponentTable::Default = {};
|
CDItemComponent CDItemComponentTable::Default = {};
|
||||||
|
|
||||||
//! Constructor
|
void CDItemComponentTable::LoadValuesFromDatabase() {
|
||||||
CDItemComponentTable::CDItemComponentTable(void) {
|
|
||||||
Default = CDItemComponent();
|
|
||||||
|
|
||||||
#ifdef CDCLIENT_CACHE_ALL
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ItemComponent");
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ItemComponent");
|
||||||
@@ -55,13 +51,13 @@ CDItemComponentTable::CDItemComponentTable(void) {
|
|||||||
entry.currencyLOT = tableData.getIntField("currencyLOT", -1);
|
entry.currencyLOT = tableData.getIntField("currencyLOT", -1);
|
||||||
entry.altCurrencyCost = tableData.getIntField("altCurrencyCost", -1);
|
entry.altCurrencyCost = tableData.getIntField("altCurrencyCost", -1);
|
||||||
entry.subItems = tableData.getStringField("subItems", "");
|
entry.subItems = tableData.getStringField("subItems", "");
|
||||||
entry.audioEventUse = tableData.getStringField("audioEventUse", "");
|
UNUSED_COLUMN(entry.audioEventUse = tableData.getStringField("audioEventUse", ""));
|
||||||
entry.noEquipAnimation = tableData.getIntField("noEquipAnimation", -1) == 1 ? true : false;
|
entry.noEquipAnimation = tableData.getIntField("noEquipAnimation", -1) == 1 ? true : false;
|
||||||
entry.commendationLOT = tableData.getIntField("commendationLOT", -1);
|
entry.commendationLOT = tableData.getIntField("commendationLOT", -1);
|
||||||
entry.commendationCost = tableData.getIntField("commendationCost", -1);
|
entry.commendationCost = tableData.getIntField("commendationCost", -1);
|
||||||
entry.audioEquipMetaEventSet = tableData.getStringField("audioEquipMetaEventSet", "");
|
UNUSED_COLUMN(entry.audioEquipMetaEventSet = tableData.getStringField("audioEquipMetaEventSet", ""));
|
||||||
entry.currencyCosts = tableData.getStringField("currencyCosts", "");
|
entry.currencyCosts = tableData.getStringField("currencyCosts", "");
|
||||||
entry.ingredientInfo = tableData.getStringField("ingredientInfo", "");
|
UNUSED_COLUMN(entry.ingredientInfo = tableData.getStringField("ingredientInfo", ""));
|
||||||
entry.locStatus = tableData.getIntField("locStatus", -1);
|
entry.locStatus = tableData.getIntField("locStatus", -1);
|
||||||
entry.forgeType = tableData.getIntField("forgeType", -1);
|
entry.forgeType = tableData.getIntField("forgeType", -1);
|
||||||
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
|
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
|
||||||
@@ -71,7 +67,6 @@ CDItemComponentTable::CDItemComponentTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
|
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
|
||||||
@@ -80,12 +75,10 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CDCLIENT_CACHE_ALL
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ItemComponent WHERE id = ?;");
|
||||||
std::stringstream query;
|
query.bind(1, static_cast<int32_t>(skillID));
|
||||||
|
|
||||||
query << "SELECT * FROM ItemComponent WHERE id = " << std::to_string(skillID);
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
|
|
||||||
if (tableData.eof()) {
|
if (tableData.eof()) {
|
||||||
entries.insert(std::make_pair(skillID, Default));
|
entries.insert(std::make_pair(skillID, Default));
|
||||||
return Default;
|
return Default;
|
||||||
@@ -144,7 +137,6 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
|
|||||||
if (it2 != this->entries.end()) {
|
if (it2 != this->entries.end()) {
|
||||||
return it2->second;
|
return it2->second;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ private:
|
|||||||
std::map<unsigned int, CDItemComponent> entries;
|
std::map<unsigned int, CDItemComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDItemComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);
|
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);
|
||||||
|
|
||||||
// Gets an entry by ID
|
// Gets an entry by ID
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDItemSetSkillsTable.h"
|
#include "CDItemSetSkillsTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDItemSetSkillsTable::LoadValuesFromDatabase() {
|
||||||
CDItemSetSkillsTable::CDItemSetSkillsTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -41,7 +40,7 @@ std::vector<CDItemSetSkills> CDItemSetSkillsTable::Query(std::function<bool(CDIt
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetEntries(void) const {
|
const std::vector<CDItemSetSkills>& CDItemSetSkillsTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ private:
|
|||||||
std::vector<CDItemSetSkills> entries;
|
std::vector<CDItemSetSkills> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDItemSetSkillsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
|
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
|
||||||
|
|
||||||
std::vector<CDItemSetSkills> GetEntries(void) const;
|
const std::vector<CDItemSetSkills>& GetEntries() const;
|
||||||
|
|
||||||
std::vector<CDItemSetSkills> GetBySkillID(unsigned int SkillSetID);
|
std::vector<CDItemSetSkills> GetBySkillID(unsigned int SkillSetID);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDItemSetsTable.h"
|
#include "CDItemSetsTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDItemSetsTable::LoadValuesFromDatabase() {
|
||||||
CDItemSetsTable::CDItemSetsTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -53,7 +52,7 @@ std::vector<CDItemSets> CDItemSetsTable::Query(std::function<bool(CDItemSets)> p
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDItemSets> CDItemSetsTable::GetEntries(void) const {
|
const std::vector<CDItemSets>& CDItemSetsTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ private:
|
|||||||
std::vector<CDItemSets> entries;
|
std::vector<CDItemSets> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDItemSetsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
|
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
|
||||||
|
|
||||||
std::vector<CDItemSets> GetEntries(void) const;
|
const std::vector<CDItemSets>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDLevelProgressionLookupTable.h"
|
#include "CDLevelProgressionLookupTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
|
||||||
CDLevelProgressionLookupTable::CDLevelProgressionLookupTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -32,7 +31,6 @@ CDLevelProgressionLookupTable::CDLevelProgressionLookupTable(void) {
|
|||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a custom "where" clause
|
|
||||||
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) {
|
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) {
|
||||||
|
|
||||||
std::vector<CDLevelProgressionLookup> data = cpplinq::from(this->entries)
|
std::vector<CDLevelProgressionLookup> data = cpplinq::from(this->entries)
|
||||||
@@ -42,8 +40,7 @@ std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
const std::vector<CDLevelProgressionLookup>& CDLevelProgressionLookupTable::GetEntries() const {
|
||||||
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::GetEntries(void) const {
|
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ private:
|
|||||||
std::vector<CDLevelProgressionLookup> entries;
|
std::vector<CDLevelProgressionLookup> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDLevelProgressionLookupTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
|
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
const std::vector<CDLevelProgressionLookup>& GetEntries() const;
|
||||||
std::vector<CDLevelProgressionLookup> GetEntries(void) const;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,19 @@
|
|||||||
#include "CDLootMatrixTable.h"
|
#include "CDLootMatrixTable.h"
|
||||||
|
|
||||||
//! Constructor
|
CDLootMatrix CDLootMatrixTable::ReadRow(CppSQLite3Query& tableData) const {
|
||||||
CDLootMatrixTable::CDLootMatrixTable(void) {
|
CDLootMatrix entry{};
|
||||||
|
if (tableData.eof()) return entry;
|
||||||
|
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
||||||
|
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
|
||||||
|
entry.percent = tableData.getFloatField("percent", -1.0f);
|
||||||
|
entry.minToDrop = tableData.getIntField("minToDrop", -1);
|
||||||
|
entry.maxToDrop = tableData.getIntField("maxToDrop", -1);
|
||||||
|
entry.flagID = tableData.getIntField("flagID", -1);
|
||||||
|
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDLootMatrixTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -12,8 +24,6 @@ CDLootMatrixTable::CDLootMatrixTable(void) {
|
|||||||
tableSize.nextRow();
|
tableSize.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableSize.finalize();
|
|
||||||
|
|
||||||
// Reserve the size
|
// Reserve the size
|
||||||
this->entries.reserve(size);
|
this->entries.reserve(size);
|
||||||
|
|
||||||
@@ -21,33 +31,28 @@ CDLootMatrixTable::CDLootMatrixTable(void) {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDLootMatrix entry;
|
CDLootMatrix entry;
|
||||||
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
||||||
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
|
||||||
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
|
|
||||||
entry.percent = tableData.getFloatField("percent", -1.0f);
|
|
||||||
entry.minToDrop = tableData.getIntField("minToDrop", -1);
|
|
||||||
entry.maxToDrop = tableData.getIntField("maxToDrop", -1);
|
|
||||||
entry.id = tableData.getIntField("id", -1);
|
|
||||||
entry.flagID = tableData.getIntField("flagID", -1);
|
|
||||||
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
|
||||||
|
|
||||||
this->entries.push_back(entry);
|
this->entries[lootMatrixIndex].push_back(ReadRow(tableData));
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
|
||||||
|
auto itr = this->entries.find(matrixId);
|
||||||
|
if (itr != this->entries.end()) {
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootMatrix where LootMatrixIndex = ?;");
|
||||||
|
query.bind(1, static_cast<int32_t>(matrixId));
|
||||||
|
|
||||||
|
auto tableData = query.execQuery();
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
this->entries[matrixId].push_back(ReadRow(tableData));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
return this->entries[matrixId];
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CDLootMatrix> CDLootMatrixTable::Query(std::function<bool(CDLootMatrix)> predicate) {
|
|
||||||
|
|
||||||
std::vector<CDLootMatrix> data = cpplinq::from(this->entries)
|
|
||||||
>> cpplinq::where(predicate)
|
|
||||||
>> cpplinq::to_vector();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<CDLootMatrix>& CDLootMatrixTable::GetEntries(void) const {
|
|
||||||
return this->entries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,26 +4,26 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDLootMatrix {
|
struct CDLootMatrix {
|
||||||
unsigned int LootMatrixIndex; //!< The Loot Matrix Index
|
|
||||||
unsigned int LootTableIndex; //!< The Loot Table Index
|
unsigned int LootTableIndex; //!< The Loot Table Index
|
||||||
unsigned int RarityTableIndex; //!< The Rarity Table Index
|
unsigned int RarityTableIndex; //!< The Rarity Table Index
|
||||||
float percent; //!< The percent that this matrix is used?
|
float percent; //!< The percent that this matrix is used?
|
||||||
unsigned int minToDrop; //!< The minimum amount of loot from this matrix to drop
|
unsigned int minToDrop; //!< The minimum amount of loot from this matrix to drop
|
||||||
unsigned int maxToDrop; //!< The maximum amount of loot from this matrix to drop
|
unsigned int maxToDrop; //!< The maximum amount of loot from this matrix to drop
|
||||||
unsigned int id; //!< The ID of the Loot Matrix
|
|
||||||
unsigned int flagID; //!< ???
|
unsigned int flagID; //!< ???
|
||||||
UNUSED(std::string gate_version); //!< The Gate Version
|
UNUSED(std::string gate_version); //!< The Gate Version
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef uint32_t LootMatrixIndex;
|
||||||
|
typedef std::vector<CDLootMatrix> LootMatrixEntries;
|
||||||
|
|
||||||
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> {
|
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> {
|
||||||
private:
|
|
||||||
std::vector<CDLootMatrix> entries;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDLootMatrixTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
|
||||||
std::vector<CDLootMatrix> Query(std::function<bool(CDLootMatrix)> predicate);
|
|
||||||
|
|
||||||
const std::vector<CDLootMatrix>& GetEntries(void) const;
|
// Gets a matrix by ID or inserts a blank one if none existed.
|
||||||
|
const LootMatrixEntries& GetMatrix(uint32_t matrixId);
|
||||||
|
private:
|
||||||
|
CDLootMatrix ReadRow(CppSQLite3Query& tableData) const;
|
||||||
|
std::unordered_map<LootMatrixIndex, LootMatrixEntries> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,44 @@
|
|||||||
#include "CDLootTableTable.h"
|
#include "CDLootTableTable.h"
|
||||||
|
#include "CDClientManager.h"
|
||||||
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
#include "CDItemComponentTable.h"
|
||||||
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
//! Constructor
|
// Sort the tables by their rarity so the highest rarity items are first.
|
||||||
CDLootTableTable::CDLootTableTable(void) {
|
void SortTable(LootTableEntries& table) {
|
||||||
|
auto* componentsRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||||
|
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>();
|
||||||
|
// We modify the table in place so the outer loop keeps track of what is sorted
|
||||||
|
// and the inner loop finds the highest rarity item and swaps it with the current position
|
||||||
|
// of the outer loop.
|
||||||
|
for (auto oldItrOuter = table.begin(); oldItrOuter != table.end(); oldItrOuter++) {
|
||||||
|
auto lootToInsert = oldItrOuter;
|
||||||
|
// Its fine if this starts at 0, even if this doesnt match lootToInsert as the actual highest will
|
||||||
|
// either be found and overwrite these values, or the original is somehow zero and is still the highest rarity.
|
||||||
|
uint32_t highestLootRarity = 0;
|
||||||
|
for (auto oldItrInner = oldItrOuter; oldItrInner != table.end(); oldItrInner++) {
|
||||||
|
uint32_t itemComponentId = componentsRegistryTable->GetByIDAndType(oldItrInner->itemid, eReplicaComponentType::ITEM);
|
||||||
|
uint32_t rarity = itemComponentTable->GetItemComponentByID(itemComponentId).rarity;
|
||||||
|
if (rarity > highestLootRarity) {
|
||||||
|
highestLootRarity = rarity;
|
||||||
|
lootToInsert = oldItrInner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Game::logger->LogDebug("CDLootTableTable", "highest rarity %i item id %i", highestLootRarity, lootToInsert->itemid);
|
||||||
|
std::swap(*oldItrOuter, *lootToInsert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CDLootTable CDLootTableTable::ReadRow(CppSQLite3Query& tableData) const {
|
||||||
|
CDLootTable entry{};
|
||||||
|
if (tableData.eof()) return entry;
|
||||||
|
entry.itemid = tableData.getIntField("itemid", -1);
|
||||||
|
entry.MissionDrop = tableData.getIntField("MissionDrop", -1) == 1 ? true : false;
|
||||||
|
entry.sortPriority = tableData.getIntField("sortPriority", -1);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDLootTableTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -12,8 +49,6 @@ CDLootTableTable::CDLootTableTable(void) {
|
|||||||
tableSize.nextRow();
|
tableSize.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableSize.finalize();
|
|
||||||
|
|
||||||
// Reserve the size
|
// Reserve the size
|
||||||
this->entries.reserve(size);
|
this->entries.reserve(size);
|
||||||
|
|
||||||
@@ -21,32 +56,32 @@ CDLootTableTable::CDLootTableTable(void) {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDLootTable entry;
|
CDLootTable entry;
|
||||||
entry.id = tableData.getIntField("id", -1);
|
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
||||||
entry.itemid = tableData.getIntField("itemid", -1);
|
|
||||||
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
|
||||||
entry.id = tableData.getIntField("id", -1);
|
|
||||||
entry.MissionDrop = tableData.getIntField("MissionDrop", -1) == 1 ? true : false;
|
|
||||||
entry.sortPriority = tableData.getIntField("sortPriority", -1);
|
|
||||||
|
|
||||||
this->entries.push_back(entry);
|
this->entries[lootTableIndex].push_back(ReadRow(tableData));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
for (auto& [id, table] : this->entries) {
|
||||||
tableData.finalize();
|
SortTable(table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a custom "where" clause
|
const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
|
||||||
std::vector<CDLootTable> CDLootTableTable::Query(std::function<bool(CDLootTable)> predicate) {
|
auto itr = this->entries.find(tableId);
|
||||||
|
if (itr != this->entries.end()) {
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<CDLootTable> data = cpplinq::from(this->entries)
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootTable WHERE LootTableIndex = ?;");
|
||||||
>> cpplinq::where(predicate)
|
query.bind(1, static_cast<int32_t>(tableId));
|
||||||
>> cpplinq::to_vector();
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
return data;
|
while (!tableData.eof()) {
|
||||||
|
CDLootTable entry;
|
||||||
|
this->entries[tableId].push_back(ReadRow(tableData));
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
SortTable(this->entries[tableId]);
|
||||||
|
|
||||||
|
return this->entries[tableId];
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
|
||||||
const std::vector<CDLootTable>& CDLootTableTable::GetEntries(void) const {
|
|
||||||
return this->entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,21 @@
|
|||||||
struct CDLootTable {
|
struct CDLootTable {
|
||||||
unsigned int itemid; //!< The LOT of the item
|
unsigned int itemid; //!< The LOT of the item
|
||||||
unsigned int LootTableIndex; //!< The Loot Table Index
|
unsigned int LootTableIndex; //!< The Loot Table Index
|
||||||
unsigned int id; //!< The ID
|
|
||||||
bool MissionDrop; //!< Whether or not this loot table is a mission drop
|
bool MissionDrop; //!< Whether or not this loot table is a mission drop
|
||||||
unsigned int sortPriority; //!< The sorting priority
|
unsigned int sortPriority; //!< The sorting priority
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef uint32_t LootTableIndex;
|
||||||
|
typedef std::vector<CDLootTable> LootTableEntries;
|
||||||
|
|
||||||
class CDLootTableTable : public CDTable<CDLootTableTable> {
|
class CDLootTableTable : public CDTable<CDLootTableTable> {
|
||||||
private:
|
private:
|
||||||
std::vector<CDLootTable> entries;
|
CDLootTable ReadRow(CppSQLite3Query& tableData) const;
|
||||||
|
std::unordered_map<LootTableIndex, LootTableEntries> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDLootTableTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDLootTable> Query(std::function<bool(CDLootTable)> predicate);
|
const LootTableEntries& GetTable(uint32_t tableId);
|
||||||
|
|
||||||
const std::vector<CDLootTable>& GetEntries(void) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDMissionEmailTable.h"
|
#include "CDMissionEmailTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDMissionEmailTable::LoadValuesFromDatabase() {
|
||||||
CDMissionEmailTable::CDMissionEmailTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -48,7 +47,7 @@ std::vector<CDMissionEmail> CDMissionEmailTable::Query(std::function<bool(CDMiss
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
std::vector<CDMissionEmail> CDMissionEmailTable::GetEntries(void) const {
|
const std::vector<CDMissionEmail>& CDMissionEmailTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ private:
|
|||||||
std::vector<CDMissionEmail> entries;
|
std::vector<CDMissionEmail> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDMissionEmailTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
|
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
|
||||||
|
|
||||||
std::vector<CDMissionEmail> GetEntries(void) const;
|
const std::vector<CDMissionEmail>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDMissionNPCComponentTable.h"
|
#include "CDMissionNPCComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
|
||||||
CDMissionNPCComponentTable::CDMissionNPCComponentTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -45,7 +44,7 @@ std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::Query(std::functi
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::GetEntries(void) const {
|
const std::vector<CDMissionNPCComponent>& CDMissionNPCComponentTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ private:
|
|||||||
std::vector<CDMissionNPCComponent> entries;
|
std::vector<CDMissionNPCComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDMissionNPCComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
|
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
std::vector<CDMissionNPCComponent> GetEntries(void) const;
|
const std::vector<CDMissionNPCComponent>& GetEntries() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDMissionTasksTable.h"
|
#include "CDMissionTasksTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDMissionTasksTable::LoadValuesFromDatabase() {
|
||||||
CDMissionTasksTable::CDMissionTasksTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -56,16 +55,14 @@ std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missio
|
|||||||
|
|
||||||
for (auto& entry : this->entries) {
|
for (auto& entry : this->entries) {
|
||||||
if (entry.id == missionID) {
|
if (entry.id == missionID) {
|
||||||
CDMissionTasks* task = const_cast<CDMissionTasks*>(&entry);
|
tasks.push_back(&entry);
|
||||||
|
|
||||||
tasks.push_back(task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries(void) const {
|
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ private:
|
|||||||
std::vector<CDMissionTasks> entries;
|
std::vector<CDMissionTasks> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDMissionTasksTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
|
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
|
||||||
|
|
||||||
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID);
|
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID);
|
||||||
|
|
||||||
const std::vector<CDMissionTasks>& GetEntries(void) const;
|
const std::vector<CDMissionTasks>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
CDMissions CDMissionsTable::Default = {};
|
CDMissions CDMissionsTable::Default = {};
|
||||||
|
|
||||||
//! Constructor
|
void CDMissionsTable::LoadValuesFromDatabase() {
|
||||||
CDMissionsTable::CDMissionsTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ private:
|
|||||||
std::vector<CDMissions> entries;
|
std::vector<CDMissions> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDMissionsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
|
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
const std::vector<CDMissions>& GetEntries(void) const;
|
const std::vector<CDMissions>& GetEntries() const;
|
||||||
|
|
||||||
const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
|
const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDMovementAIComponentTable.h"
|
#include "CDMovementAIComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDMovementAIComponentTable::LoadValuesFromDatabase() {
|
||||||
CDMovementAIComponentTable::CDMovementAIComponentTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -37,7 +36,6 @@ CDMovementAIComponentTable::CDMovementAIComponentTable(void) {
|
|||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a custom "where" clause
|
|
||||||
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
|
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
|
||||||
|
|
||||||
std::vector<CDMovementAIComponent> data = cpplinq::from(this->entries)
|
std::vector<CDMovementAIComponent> data = cpplinq::from(this->entries)
|
||||||
@@ -47,8 +45,7 @@ std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::functi
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
const std::vector<CDMovementAIComponent>& CDMovementAIComponentTable::GetEntries(void) const {
|
||||||
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::GetEntries(void) const {
|
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ private:
|
|||||||
std::vector<CDMovementAIComponent> entries;
|
std::vector<CDMovementAIComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDMovementAIComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
|
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
std::vector<CDMovementAIComponent> GetEntries(void) const;
|
const std::vector<CDMovementAIComponent>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDObjectSkillsTable.h"
|
#include "CDObjectSkillsTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDObjectSkillsTable::LoadValuesFromDatabase() {
|
||||||
CDObjectSkillsTable::CDObjectSkillsTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -33,7 +32,6 @@ CDObjectSkillsTable::CDObjectSkillsTable(void) {
|
|||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a custom "where" clause
|
|
||||||
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
|
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
|
||||||
|
|
||||||
std::vector<CDObjectSkills> data = cpplinq::from(this->entries)
|
std::vector<CDObjectSkills> data = cpplinq::from(this->entries)
|
||||||
@@ -43,7 +41,6 @@ std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObje
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
const std::vector<CDObjectSkills>& CDObjectSkillsTable::GetEntries() const {
|
||||||
std::vector<CDObjectSkills> CDObjectSkillsTable::GetEntries(void) const {
|
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ private:
|
|||||||
std::vector<CDObjectSkills> entries;
|
std::vector<CDObjectSkills> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDObjectSkillsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
|
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
std::vector<CDObjectSkills> GetEntries(void) const;
|
const std::vector<CDObjectSkills>& GetEntries() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "CDObjectsTable.h"
|
#include "CDObjectsTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDObjectsTable::LoadValuesFromDatabase() {
|
||||||
CDObjectsTable::CDObjectsTable(void) {
|
|
||||||
#ifdef CDCLIENT_CACHE_ALL
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Objects");
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Objects");
|
||||||
@@ -20,25 +18,24 @@ CDObjectsTable::CDObjectsTable(void) {
|
|||||||
CDObjects entry;
|
CDObjects entry;
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.name = tableData.getStringField("name", "");
|
entry.name = tableData.getStringField("name", "");
|
||||||
entry.placeable = tableData.getIntField("placeable", -1);
|
UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);)
|
||||||
entry.type = tableData.getStringField("type", "");
|
entry.type = tableData.getStringField("type", "");
|
||||||
entry.description = tableData.getStringField("description", "");
|
UNUSED_COLUMN(entry.description = tableData.getStringField("description", "");)
|
||||||
entry.localize = tableData.getIntField("localize", -1);
|
UNUSED_COLUMN(entry.localize = tableData.getIntField("localize", -1);)
|
||||||
entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1);
|
UNUSED_COLUMN(entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1);)
|
||||||
entry.displayName = tableData.getStringField("displayName", "");
|
UNUSED_COLUMN(entry.displayName = tableData.getStringField("displayName", "");)
|
||||||
entry.interactionDistance = tableData.getFloatField("interactionDistance", -1.0f);
|
entry.interactionDistance = tableData.getFloatField("interactionDistance", -1.0f);
|
||||||
entry.nametag = tableData.getIntField("nametag", -1);
|
UNUSED_COLUMN(entry.nametag = tableData.getIntField("nametag", -1);)
|
||||||
entry._internalNotes = tableData.getStringField("_internalNotes", "");
|
UNUSED_COLUMN(entry._internalNotes = tableData.getStringField("_internalNotes", "");)
|
||||||
entry.locStatus = tableData.getIntField("locStatus", -1);
|
UNUSED_COLUMN(entry.locStatus = tableData.getIntField("locStatus", -1);)
|
||||||
entry.gate_version = tableData.getStringField("gate_version", "");
|
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
|
||||||
entry.HQ_valid = tableData.getIntField("HQ_valid", -1);
|
UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
|
||||||
|
|
||||||
this->entries.insert(std::make_pair(entry.id, entry));
|
this->entries.insert(std::make_pair(entry.id, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
#endif
|
|
||||||
|
|
||||||
m_default.id = 0;
|
m_default.id = 0;
|
||||||
}
|
}
|
||||||
@@ -49,12 +46,10 @@ const CDObjects& CDObjectsTable::GetByID(unsigned int LOT) {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CDCLIENT_CACHE_ALL
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Objects WHERE id = ?;");
|
||||||
std::stringstream query;
|
query.bind(1, static_cast<int32_t>(LOT));
|
||||||
|
|
||||||
query << "SELECT * FROM Objects WHERE id = " << std::to_string(LOT);
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
|
|
||||||
if (tableData.eof()) {
|
if (tableData.eof()) {
|
||||||
this->entries.insert(std::make_pair(LOT, m_default));
|
this->entries.insert(std::make_pair(LOT, m_default));
|
||||||
return m_default;
|
return m_default;
|
||||||
@@ -88,7 +83,6 @@ const CDObjects& CDObjectsTable::GetByID(unsigned int LOT) {
|
|||||||
if (it2 != entries.end()) {
|
if (it2 != entries.end()) {
|
||||||
return it2->second;
|
return it2->second;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return m_default;
|
return m_default;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ private:
|
|||||||
CDObjects m_default;
|
CDObjects m_default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDObjectsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Gets an entry by ID
|
// Gets an entry by ID
|
||||||
const CDObjects& GetByID(unsigned int LOT);
|
const CDObjects& GetByID(unsigned int LOT);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDPackageComponentTable.h"
|
#include "CDPackageComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDPackageComponentTable::LoadValuesFromDatabase() {
|
||||||
CDPackageComponentTable::CDPackageComponentTable(void) {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -43,7 +42,7 @@ std::vector<CDPackageComponent> CDPackageComponentTable::Query(std::function<boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
std::vector<CDPackageComponent> CDPackageComponentTable::GetEntries(void) const {
|
const std::vector<CDPackageComponent>& CDPackageComponentTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ private:
|
|||||||
std::vector<CDPackageComponent> entries;
|
std::vector<CDPackageComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDPackageComponentTable(void);
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
|
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
|
||||||
|
|
||||||
std::vector<CDPackageComponent> GetEntries(void) const;
|
const std::vector<CDPackageComponent>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,46 +1,35 @@
|
|||||||
#include "CDPhysicsComponentTable.h"
|
#include "CDPhysicsComponentTable.h"
|
||||||
|
|
||||||
CDPhysicsComponentTable::CDPhysicsComponentTable(void) {
|
void CDPhysicsComponentTable::LoadValuesFromDatabase() {
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDPhysicsComponent* entry = new CDPhysicsComponent();
|
CDPhysicsComponent entry;
|
||||||
entry->id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry->bStatic = tableData.getIntField("static", -1) != 0;
|
entry.bStatic = tableData.getIntField("static", -1) != 0;
|
||||||
entry->physicsAsset = tableData.getStringField("physics_asset", "");
|
entry.physicsAsset = tableData.getStringField("physics_asset", "");
|
||||||
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
|
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
|
||||||
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
|
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
|
||||||
entry->speed = tableData.getFloatField("speed", -1);
|
entry.speed = tableData.getFloatField("speed", -1);
|
||||||
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
|
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
|
||||||
entry->playerHeight = tableData.getFloatField("playerHeight");
|
entry.playerHeight = tableData.getFloatField("playerHeight");
|
||||||
entry->playerRadius = tableData.getFloatField("playerRadius");
|
entry.playerRadius = tableData.getFloatField("playerRadius");
|
||||||
entry->pcShapeType = tableData.getIntField("pcShapeType");
|
entry.pcShapeType = tableData.getIntField("pcShapeType");
|
||||||
entry->collisionGroup = tableData.getIntField("collisionGroup");
|
entry.collisionGroup = tableData.getIntField("collisionGroup");
|
||||||
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
|
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
|
||||||
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
|
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
|
||||||
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
|
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
|
||||||
UNUSED(entry->friction = tableData.getFloatField("friction"));
|
UNUSED(entry->friction = tableData.getFloatField("friction"));
|
||||||
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
|
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
|
||||||
|
|
||||||
m_entries.insert(std::make_pair(entry->id, entry));
|
m_entries.insert(std::make_pair(entry.id, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
CDPhysicsComponentTable::~CDPhysicsComponentTable() {
|
|
||||||
for (auto e : m_entries) {
|
|
||||||
if (e.second) delete e.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_entries.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) {
|
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) {
|
||||||
for (auto e : m_entries) {
|
auto itr = m_entries.find(componentID);
|
||||||
if (e.first == componentID) return e.second;
|
return itr != m_entries.end() ? &itr->second : nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,12 +23,11 @@ struct CDPhysicsComponent {
|
|||||||
|
|
||||||
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> {
|
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> {
|
||||||
public:
|
public:
|
||||||
CDPhysicsComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
~CDPhysicsComponentTable();
|
|
||||||
|
|
||||||
static const std::string GetTableName() { return "PhysicsComponent"; };
|
static const std::string GetTableName() { return "PhysicsComponent"; };
|
||||||
CDPhysicsComponent* GetByID(unsigned int componentID);
|
CDPhysicsComponent* GetByID(unsigned int componentID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<unsigned int, CDPhysicsComponent*> m_entries;
|
std::map<unsigned int, CDPhysicsComponent> m_entries;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "CDPropertyEntranceComponentTable.h"
|
#include "CDPropertyEntranceComponentTable.h"
|
||||||
|
|
||||||
CDPropertyEntranceComponentTable::CDPropertyEntranceComponentTable() {
|
void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ struct CDPropertyEntranceComponent {
|
|||||||
|
|
||||||
class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable> {
|
class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable> {
|
||||||
public:
|
public:
|
||||||
CDPropertyEntranceComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
CDPropertyEntranceComponent GetByID(uint32_t id);
|
CDPropertyEntranceComponent GetByID(uint32_t id);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
[[nodiscard]] std::vector<CDPropertyEntranceComponent> GetEntries() const { return entries; }
|
[[nodiscard]] const std::vector<CDPropertyEntranceComponent>& GetEntries() const { return entries; }
|
||||||
private:
|
private:
|
||||||
std::vector<CDPropertyEntranceComponent> entries{};
|
std::vector<CDPropertyEntranceComponent> entries{};
|
||||||
CDPropertyEntranceComponent defaultEntry{};
|
CDPropertyEntranceComponent defaultEntry{};
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user