mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-21 22:24:21 +00:00
Compare commits
6 Commits
raw-parsin
...
auth-packe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0dc4fab531 | ||
|
|
500a72dc11 | ||
|
|
b36b440eba | ||
|
|
d1e65f16f7 | ||
|
|
e854d6f56a | ||
|
|
824d563fd2 |
29
.github/copilot-instructions.md
vendored
29
.github/copilot-instructions.md
vendored
@@ -1,29 +0,0 @@
|
|||||||
# GitHub Copilot Instructions
|
|
||||||
|
|
||||||
* c++20 standard, please use the latest features except NO modules.
|
|
||||||
* use `.contains` for searching in associative containers
|
|
||||||
* use const as much as possible. If it can be const, it should be made const
|
|
||||||
* DO NOT USE const_cast EVER.
|
|
||||||
* use `cstdint` bitwidth types ALWAYS for integral types.
|
|
||||||
* NEVER use std::wstring. If wide strings are necessary, use std::u16string with conversion utilties in GeneralUtils.h.
|
|
||||||
* Functions are ALWAYS PascalCase.
|
|
||||||
* local variables are camelCase
|
|
||||||
* NEVER use snake case
|
|
||||||
* indentation is TABS, not SPACES.
|
|
||||||
* TABS are 4 spaces by default
|
|
||||||
* Use trailing braces ALWAYS
|
|
||||||
* global variables are prefixed with `g_`
|
|
||||||
* if global variables or functions are needed, they should be located in an anonymous namespace
|
|
||||||
* Use `GeneralUtils::TryParse` for ANY parsing of strings to integrals.
|
|
||||||
* Use brace initialization when possible.
|
|
||||||
* ALWAYS default initialize variables.
|
|
||||||
* Pointers should be avoided unless necessary. Use references when the pointer has been checked and should not be null
|
|
||||||
* headers should be as compact as possible. Do NOT include extra data that isnt needed.
|
|
||||||
* Remember to include logs (LOG macro uses printf style logging) while putting verbose logs under LOG_DEBUG.
|
|
||||||
* NEVER USE `RakNet::BitStream::ReadBit`
|
|
||||||
* NEVER assume pointers are good, always check if they are null. Once a pointer is checked and is known to be non-null, further accesses no longer need checking
|
|
||||||
* Be wary of TOCTOU. Prevent all possible issues relating to TOCTOU.
|
|
||||||
* new memory allocations should never be used unless absolutely necessary.
|
|
||||||
* new for reconstruction of objects is allowed
|
|
||||||
* Prefer following the format of the file over correct formatting. Consistency over correctness.
|
|
||||||
* When using auto, ALWAYS put a * for pointers.
|
|
||||||
33
.github/workflows/build-and-push-docker.yml
vendored
33
.github/workflows/build-and-push-docker.yml
vendored
@@ -1,14 +1,14 @@
|
|||||||
name: Docker
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- "main"
|
||||||
tags:
|
tags:
|
||||||
- "v*.*.*"
|
- "v*.*.*"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- "main"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: ghcr.io
|
REGISTRY: ghcr.io
|
||||||
@@ -20,21 +20,15 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
attestations: write
|
|
||||||
id-token: write
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
|
||||||
|
|
||||||
- name: Log in to the Container registry
|
- name: Log in to the Container registry
|
||||||
if: github.event_name != 'pull_request'
|
uses: docker/login-action@v3
|
||||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@@ -42,32 +36,21 @@ jobs:
|
|||||||
|
|
||||||
- name: Extract metadata (tags, labels) for Docker
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
# generate Docker tags based on the following events/attributes
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=pr
|
type=ref,event=pr
|
||||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||||
type=raw,value=canary,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
type=semver,pattern={{major}}
|
type=semver,pattern={{major}}
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
id: push
|
uses: docker/build-push-action@v5
|
||||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
|
|
||||||
- name: Sign Docker image
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
|
|
||||||
with:
|
|
||||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
||||||
subject-digest: ${{ steps.push.outputs.digest }}
|
|
||||||
push-to-registry: true
|
|
||||||
|
|||||||
84
.github/workflows/build-and-test.yml
vendored
84
.github/workflows/build-and-test.yml
vendored
@@ -3,8 +3,6 @@ name: CI
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
tags:
|
|
||||||
- "v*.*.*"
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
|
|
||||||
@@ -12,51 +10,38 @@ jobs:
|
|||||||
build-and-test:
|
build-and-test:
|
||||||
name: Build & Test (${{ matrix.os }})
|
name: Build & Test (${{ matrix.os }})
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
continue-on-error: ${{ github.event_name == 'pull_request' }}
|
continue-on-error: true
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
os: [ windows-2022, ubuntu-22.04, macos-13 ]
|
||||||
- os: windows-2025
|
|
||||||
artifact: windows
|
|
||||||
debug_preset: windows-msvc-relwithdebinfo
|
|
||||||
- os: ubuntu-24.04
|
|
||||||
artifact: linux
|
|
||||||
debug_preset: linux-gnu-relwithdebinfo
|
|
||||||
- os: macos-15-intel
|
|
||||||
artifact: macos
|
|
||||||
debug_preset: macos-relwithdebinfo
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Add msbuild to PATH (Windows only)
|
- name: Add msbuild to PATH (Windows only)
|
||||||
if: ${{ matrix.os == 'windows-2025' }}
|
if: ${{ matrix.os == 'windows-2022' }}
|
||||||
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3
|
uses: microsoft/setup-msbuild@767f00a3f09872d96a0cb9fcd5e6a4ff33311330
|
||||||
with:
|
with:
|
||||||
vs-version: '[18,19)'
|
vs-version: '[17,18)'
|
||||||
msbuild-architecture: x64
|
msbuild-architecture: x64
|
||||||
- name: Get CMake
|
- name: Install libssl and switch to XCode 15.2 (Mac Only)
|
||||||
uses: lukka/get-cmake@591817e96fcad43505fb4eae36172462abb3a42e # v4.3.3
|
if: ${{ matrix.os == 'macos-13' }}
|
||||||
with:
|
|
||||||
cmakeVersion: "latest"
|
|
||||||
- name: cmake
|
|
||||||
uses: lukka/run-cmake@5d55ea7949e25f69f0ecb516d8d572297e03a956 # v10.9
|
|
||||||
with:
|
|
||||||
workflowPreset: "${{ matrix.debug_preset }}"
|
|
||||||
|
|
||||||
- name: Extract Linux debug symbols
|
|
||||||
if: matrix.os == 'ubuntu-24.04'
|
|
||||||
run: |
|
run: |
|
||||||
find build -type f -name '*Server' | while read bin; do
|
brew install openssl@3
|
||||||
objcopy --only-keep-debug "$bin" "${bin}.debug"
|
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
|
||||||
objcopy --strip-debug --add-gnu-debuglink="${bin}.debug" "$bin"
|
- name: Get CMake 3.x
|
||||||
done
|
uses: lukka/get-cmake@28983e0d3955dba2bb0a6810caae0c6cf268ec0c
|
||||||
|
|
||||||
- name: artifacts
|
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
||||||
with:
|
with:
|
||||||
name: build-${{matrix.artifact}}
|
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
|
||||||
|
- name: cmake
|
||||||
|
uses: lukka/run-cmake@67c73a83a46f86c4e0b96b741ac37ff495478c38
|
||||||
|
with:
|
||||||
|
workflowPreset: "ci-${{matrix.os}}"
|
||||||
|
- name: artifacts
|
||||||
|
uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47
|
||||||
|
with:
|
||||||
|
name: build-${{matrix.os}}
|
||||||
path: |
|
path: |
|
||||||
build/*/*Server*
|
build/*/*Server*
|
||||||
build/*/*.ini
|
build/*/*.ini
|
||||||
@@ -67,30 +52,5 @@ jobs:
|
|||||||
build/*/navmeshes/
|
build/*/navmeshes/
|
||||||
build/*/migrations/
|
build/*/migrations/
|
||||||
build/*/*.dcf
|
build/*/*.dcf
|
||||||
|
!build/*/*.pdb
|
||||||
!build/*/d*/
|
!build/*/d*/
|
||||||
!build/*/*.dSYM/
|
|
||||||
!build/**/*.debug
|
|
||||||
|
|
||||||
- name: debug symbols (Windows)
|
|
||||||
if: matrix.os == 'windows-2025'
|
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
||||||
with:
|
|
||||||
name: debug-${{matrix.artifact}}
|
|
||||||
path: |
|
|
||||||
build/*/*.pdb
|
|
||||||
build/*/d*/
|
|
||||||
retention-days: 30
|
|
||||||
- name: debug symbols (Linux)
|
|
||||||
if: matrix.os == 'ubuntu-24.04'
|
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
||||||
with:
|
|
||||||
name: debug-${{matrix.artifact}}
|
|
||||||
path: build/**/*.debug
|
|
||||||
retention-days: 30
|
|
||||||
- name: debug symbols (macOS)
|
|
||||||
if: matrix.os == 'macos-15-intel'
|
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
||||||
with:
|
|
||||||
name: debug-${{matrix.artifact}}
|
|
||||||
path: build/**/*.dSYM/
|
|
||||||
retention-days: 30
|
|
||||||
|
|||||||
93
.github/workflows/canary.yml
vendored
93
.github/workflows/canary.yml
vendored
@@ -1,93 +0,0 @@
|
|||||||
name: Canary
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_run:
|
|
||||||
workflows: ["CI"]
|
|
||||||
branches: [main]
|
|
||||||
types: [completed]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
canary-release:
|
|
||||||
name: Publish Canary Release
|
|
||||||
if: github.event.workflow_run.conclusion == 'success'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: ${{ github.event.workflow_run.head_sha }}
|
|
||||||
|
|
||||||
- name: Get last release tag
|
|
||||||
id: last_tag
|
|
||||||
run: |
|
|
||||||
tag=$(git describe --tags --abbrev=0 --match "v*.*.*" 2>/dev/null || echo "none")
|
|
||||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Generate changelog since last release tag
|
|
||||||
uses: orhun/git-cliff-action@f50e11560dce63f7c33227798f90b924471a88b5 # v4.8.0
|
|
||||||
id: cliff
|
|
||||||
with:
|
|
||||||
config: cliff.toml
|
|
||||||
args: --unreleased --strip header
|
|
||||||
env:
|
|
||||||
OUTPUT: CHANGES.md
|
|
||||||
GITHUB_REPO: ${{ github.repository }}
|
|
||||||
|
|
||||||
- name: Prepend header to changelog
|
|
||||||
run: |
|
|
||||||
last="${{ steps.last_tag.outputs.tag }}"
|
|
||||||
sha="${{ github.event.workflow_run.head_sha }}"
|
|
||||||
short="${sha:0:7}"
|
|
||||||
if [ "$last" != "none" ]; then
|
|
||||||
header="Changes since **$last** ([full diff](https://github.com/${{ github.repository }}/compare/${last}...${sha}))\n\n"
|
|
||||||
else
|
|
||||||
header="Changes up to \`${short}\`\n\n"
|
|
||||||
fi
|
|
||||||
printf "%b" "$header" | cat - CHANGES.md > CHANGES.tmp && mv CHANGES.tmp CHANGES.md
|
|
||||||
|
|
||||||
- name: Download artifacts from CI run
|
|
||||||
uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
|
|
||||||
with:
|
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
|
||||||
path: artifacts/
|
|
||||||
|
|
||||||
- name: Package artifacts
|
|
||||||
run: |
|
|
||||||
declare -A platform_map=(
|
|
||||||
["build-windows"]="darkflame-universe-windows"
|
|
||||||
["build-linux"]="darkflame-universe-linux"
|
|
||||||
["build-macos"]="darkflame-universe-macos"
|
|
||||||
)
|
|
||||||
cd artifacts
|
|
||||||
for dir in build-*/; do
|
|
||||||
name="${dir%/}"
|
|
||||||
out="${platform_map[$name]:-$name}"
|
|
||||||
zip -r "../${out}.zip" "$dir"
|
|
||||||
done
|
|
||||||
cd ..
|
|
||||||
ls -lh *.zip
|
|
||||||
|
|
||||||
- name: Delete existing canary release
|
|
||||||
run: gh release delete canary --yes --cleanup-tag 2>/dev/null || true
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Create canary pre-release
|
|
||||||
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
|
|
||||||
with:
|
|
||||||
tag: canary
|
|
||||||
name: "Canary ${{ steps.last_tag.outputs.tag }}+${{ github.event.workflow_run.head_sha }}"
|
|
||||||
bodyFile: CHANGES.md
|
|
||||||
artifacts: "*.zip"
|
|
||||||
artifactContentType: application/zip
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
prerelease: true
|
|
||||||
draft: false
|
|
||||||
allowUpdates: true
|
|
||||||
removeArtifacts: true
|
|
||||||
commit: ${{ github.event.workflow_run.head_sha }}
|
|
||||||
38
.github/workflows/pr-title-check.yml
vendored
38
.github/workflows/pr-title-check.yml
vendored
@@ -1,38 +0,0 @@
|
|||||||
name: PR Title Check
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, edited, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
statuses: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-title:
|
|
||||||
name: Conventional Commit Title
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check PR title follows Conventional Commits
|
|
||||||
uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
types: |
|
|
||||||
feat
|
|
||||||
fix
|
|
||||||
perf
|
|
||||||
refactor
|
|
||||||
docs
|
|
||||||
chore
|
|
||||||
test
|
|
||||||
ci
|
|
||||||
revert
|
|
||||||
requireScope: false
|
|
||||||
subjectPattern: ^.+$
|
|
||||||
subjectPatternError: |
|
|
||||||
The PR title "{title}" must have a description after the type/scope prefix.
|
|
||||||
Example: "feat: add new login flow" or "fix(auth): handle null token"
|
|
||||||
wip: true
|
|
||||||
validateSingleCommit: false
|
|
||||||
70
.github/workflows/release.yml
vendored
70
.github/workflows/release.yml
vendored
@@ -1,70 +0,0 @@
|
|||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_run:
|
|
||||||
workflows: ["CI"]
|
|
||||||
types: [completed]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Create Release
|
|
||||||
# Only run when CI completed successfully on a tag push (not a PR branch named like a version)
|
|
||||||
if: |
|
|
||||||
github.event.workflow_run.conclusion == 'success' &&
|
|
||||||
github.event.workflow_run.event == 'push' &&
|
|
||||||
startsWith(github.event.workflow_run.head_branch, 'v')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: ${{ github.event.workflow_run.head_sha }}
|
|
||||||
|
|
||||||
- name: Generate changelog
|
|
||||||
uses: orhun/git-cliff-action@f50e11560dce63f7c33227798f90b924471a88b5 # v4.8.0
|
|
||||||
id: cliff
|
|
||||||
with:
|
|
||||||
config: cliff.toml
|
|
||||||
args: --latest --strip header
|
|
||||||
env:
|
|
||||||
OUTPUT: CHANGES.md
|
|
||||||
GITHUB_REPO: ${{ github.repository }}
|
|
||||||
|
|
||||||
- name: Download artifacts from CI run
|
|
||||||
uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
|
|
||||||
with:
|
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
|
||||||
path: artifacts/
|
|
||||||
|
|
||||||
- name: Package artifacts
|
|
||||||
run: |
|
|
||||||
declare -A platform_map=(
|
|
||||||
["build-windows"]="darkflame-universe-windows"
|
|
||||||
["build-linux"]="darkflame-universe-linux"
|
|
||||||
["build-macos"]="darkflame-universe-macos"
|
|
||||||
)
|
|
||||||
cd artifacts
|
|
||||||
for dir in build-*/; do
|
|
||||||
name="${dir%/}"
|
|
||||||
out="${platform_map[$name]:-$name}"
|
|
||||||
zip -r "../${out}.zip" "$dir"
|
|
||||||
done
|
|
||||||
cd ..
|
|
||||||
ls -lh *.zip
|
|
||||||
|
|
||||||
- name: Create GitHub Release
|
|
||||||
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
|
|
||||||
with:
|
|
||||||
tag: ${{ github.event.workflow_run.head_branch }}
|
|
||||||
name: ${{ github.event.workflow_run.head_branch }}
|
|
||||||
bodyFile: CHANGES.md
|
|
||||||
artifacts: "*.zip"
|
|
||||||
artifactContentType: application/zip
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
prerelease: false
|
|
||||||
draft: false
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -126,5 +126,3 @@ docker-compose.override.yml
|
|||||||
# CMake scripts
|
# CMake scripts
|
||||||
!cmake/*
|
!cmake/*
|
||||||
!cmake/toolchains/*
|
!cmake/toolchains/*
|
||||||
.mcp.json
|
|
||||||
.claude/
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ set(CMAKE_C_STANDARD 99)
|
|||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
||||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
||||||
@@ -68,11 +67,7 @@ set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|||||||
# Disabled no-register
|
# Disabled no-register
|
||||||
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
if(APPLE)
|
add_link_options("-Wl,-rpath,$ORIGIN/")
|
||||||
add_link_options("-Wl,-rpath,@loader_path/")
|
|
||||||
else()
|
|
||||||
add_link_options("-Wl,-rpath,$ORIGIN/")
|
|
||||||
endif()
|
|
||||||
add_compile_options("-fPIC")
|
add_compile_options("-fPIC")
|
||||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0)
|
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0)
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
"inherits": "default",
|
"inherits": "default",
|
||||||
"displayName": "[Multi] Windows (MSVC)",
|
"displayName": "[Multi] Windows (MSVC)",
|
||||||
"description": "Set architecture to 64-bit (b/c RakNet)",
|
"description": "Set architecture to 64-bit (b/c RakNet)",
|
||||||
"generator": "Visual Studio 18 2026",
|
"generator": "Visual Studio 17 2022",
|
||||||
"binaryDir": "${sourceDir}/build/msvc",
|
"binaryDir": "${sourceDir}/build/msvc",
|
||||||
"architecture": {
|
"architecture": {
|
||||||
"value": "x64"
|
"value": "x64"
|
||||||
@@ -162,13 +162,6 @@
|
|||||||
"rhs": "Darwin"
|
"rhs": "Darwin"
|
||||||
},
|
},
|
||||||
"binaryDir": "${sourceDir}/build/macos"
|
"binaryDir": "${sourceDir}/build/macos"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "macos-relwithdebinfo",
|
|
||||||
"inherits": ["macos", "relwithdebinfo-config"],
|
|
||||||
"displayName": "[RelWithDebInfo] MacOS",
|
|
||||||
"description": "Create a RelWithDebInfo build for MacOS",
|
|
||||||
"binaryDir": "${sourceDir}/build/macos-relwithdebinfo"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"buildPresets": [
|
"buildPresets": [
|
||||||
@@ -262,7 +255,7 @@
|
|||||||
{
|
{
|
||||||
"name": "macos-relwithdebinfo",
|
"name": "macos-relwithdebinfo",
|
||||||
"inherits": "default",
|
"inherits": "default",
|
||||||
"configurePreset": "macos-relwithdebinfo",
|
"configurePreset": "macos",
|
||||||
"displayName": "[RelWithDebInfo] MacOS",
|
"displayName": "[RelWithDebInfo] MacOS",
|
||||||
"description": "This preset is used to build in release mode with debug info on MacOS",
|
"description": "This preset is used to build in release mode with debug info on MacOS",
|
||||||
"configuration": "RelWithDebInfo"
|
"configuration": "RelWithDebInfo"
|
||||||
@@ -381,7 +374,7 @@
|
|||||||
{
|
{
|
||||||
"name": "macos-relwithdebinfo",
|
"name": "macos-relwithdebinfo",
|
||||||
"inherits": "default",
|
"inherits": "default",
|
||||||
"configurePreset": "macos-relwithdebinfo",
|
"configurePreset": "macos",
|
||||||
"displayName": "[RelWithDebInfo] MacOS",
|
"displayName": "[RelWithDebInfo] MacOS",
|
||||||
"description": "Runs all tests on a MacOS configuration",
|
"description": "Runs all tests on a MacOS configuration",
|
||||||
"configuration": "RelWithDebInfo"
|
"configuration": "RelWithDebInfo"
|
||||||
@@ -610,7 +603,7 @@
|
|||||||
"steps": [
|
"steps": [
|
||||||
{
|
{
|
||||||
"type": "configure",
|
"type": "configure",
|
||||||
"name": "macos-relwithdebinfo"
|
"name": "macos"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "build",
|
"type": "build",
|
||||||
@@ -623,7 +616,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ci-macos-15-intel",
|
"name": "ci-macos-13",
|
||||||
"displayName": "[Release] MacOS",
|
"displayName": "[Release] MacOS",
|
||||||
"description": "CI workflow preset for MacOS",
|
"description": "CI workflow preset for MacOS",
|
||||||
"steps": [
|
"steps": [
|
||||||
|
|||||||
@@ -16,9 +16,7 @@ RUN --mount=type=cache,target=/app/build,id=build-cache \
|
|||||||
cd /app/build && \
|
cd /app/build && \
|
||||||
cmake .. && \
|
cmake .. && \
|
||||||
make -j$(nproc --ignore 1) && \
|
make -j$(nproc --ignore 1) && \
|
||||||
cp -r /app/build/* /tmp/persisted-build/ && \
|
cp -r /app/build/* /tmp/persisted-build/
|
||||||
mkdir -p /tmp/persisted-build/mariadbcpp && \
|
|
||||||
cp /app/build/thirdparty/mariadb-connector-cpp/src/mariadb_connector_cpp-build/libmariadbcpp.so /tmp/persisted-build/mariadbcpp/
|
|
||||||
|
|
||||||
FROM debian:12 as runtime
|
FROM debian:12 as runtime
|
||||||
|
|
||||||
|
|||||||
35
cliff.toml
35
cliff.toml
@@ -1,35 +0,0 @@
|
|||||||
[changelog]
|
|
||||||
header = ""
|
|
||||||
body = """
|
|
||||||
{% for group, commits in commits | group_by(attribute="group") %}
|
|
||||||
### {{ group | upper_first }}
|
|
||||||
{% for commit in commits %}
|
|
||||||
- {% if commit.scope %}**{{ commit.scope }}**: {% endif %}{{ commit.message }} ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}/commit/{{ commit.id }}))\
|
|
||||||
{% if commit.github.username %} by [@{{ commit.github.username }}](https://github.com/{{ commit.github.username }}){% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
"""
|
|
||||||
footer = ""
|
|
||||||
trim = true
|
|
||||||
|
|
||||||
[git]
|
|
||||||
conventional_commits = true
|
|
||||||
filter_unconventional = true
|
|
||||||
split_commits = false
|
|
||||||
commit_parsers = [
|
|
||||||
{ message = "^feat", group = "Features" },
|
|
||||||
{ message = "^fix", group = "Bug Fixes" },
|
|
||||||
{ message = "^perf", group = "Performance" },
|
|
||||||
{ message = "^refactor", group = "Refactoring" },
|
|
||||||
{ message = "^docs", group = "Documentation" },
|
|
||||||
{ message = "^chore", group = "Chores" },
|
|
||||||
{ message = "^test", group = "Testing" },
|
|
||||||
{ message = "^ci", group = "CI/CD" },
|
|
||||||
{ message = "^revert", group = "Reverts" },
|
|
||||||
]
|
|
||||||
filter_commits = false
|
|
||||||
tag_pattern = "v[0-9].*"
|
|
||||||
skip_tags = "canary"
|
|
||||||
ignore_tags = ""
|
|
||||||
topo_order = false
|
|
||||||
sort_commits = "oldest"
|
|
||||||
@@ -7,7 +7,6 @@ FetchContent_Declare(
|
|||||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||||
GIT_TAG release-1.12.1
|
GIT_TAG release-1.12.1
|
||||||
GIT_PROGRESS TRUE
|
GIT_PROGRESS TRUE
|
||||||
GIT_SHALLOW 1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||||
|
|||||||
@@ -10,15 +10,14 @@ if(WIN32 AND NOT MARIADB_BUILD_SOURCE)
|
|||||||
file(MAKE_DIRECTORY "${MARIADB_MSI_DIR}")
|
file(MAKE_DIRECTORY "${MARIADB_MSI_DIR}")
|
||||||
file(MAKE_DIRECTORY "${MARIADB_CONNECTOR_DIR}")
|
file(MAKE_DIRECTORY "${MARIADB_CONNECTOR_DIR}")
|
||||||
|
|
||||||
# These values track the published Windows MSI packages used by the prebuilt path.
|
# These values need to be updated whenever a new minor release replaces an old one
|
||||||
# Keep the Connector/C++ package version aligned with the checked out submodule tag when possible.
|
# Go to https://mariadb.com/downloads/connectors/ to find the up-to-date URL parts
|
||||||
# Go to https://mariadb.com/downloads/connectors/ to find the up-to-date URL parts.
|
set(MARIADB_CONNECTOR_C_VERSION "3.2.7")
|
||||||
set(MARIADB_CONNECTOR_C_VERSION "3.4.8")
|
set(MARIADB_CONNECTOR_C_BUCKET "2319651")
|
||||||
set(MARIADB_CONNECTOR_C_BUCKET "4516894")
|
set(MARIADB_CONNECTOR_C_MD5 "f8636d733f1d093af9d4f22f3239f885")
|
||||||
set(MARIADB_CONNECTOR_C_MD5 "50f6fc0c77b8d3bacbeac0126e179861")
|
set(MARIADB_CONNECTOR_CPP_VERSION "1.0.2")
|
||||||
set(MARIADB_CONNECTOR_CPP_VERSION "1.1.7")
|
set(MARIADB_CONNECTOR_CPP_BUCKET "2531525")
|
||||||
set(MARIADB_CONNECTOR_CPP_BUCKET "4464908")
|
set(MARIADB_CONNECTOR_CPP_MD5 "3034bbd6ca00a0125345f9fd1a178401")
|
||||||
set(MARIADB_CONNECTOR_CPP_MD5 "08644a7ff084b5933325cadb904796e5")
|
|
||||||
|
|
||||||
set(MARIADB_CONNECTOR_C_MSI "mariadb-connector-c-${MARIADB_CONNECTOR_C_VERSION}-win64.msi")
|
set(MARIADB_CONNECTOR_C_MSI "mariadb-connector-c-${MARIADB_CONNECTOR_C_VERSION}-win64.msi")
|
||||||
set(MARIADB_CONNECTOR_CPP_MSI "mariadb-connector-cpp-${MARIADB_CONNECTOR_CPP_VERSION}-win64.msi")
|
set(MARIADB_CONNECTOR_CPP_MSI "mariadb-connector-cpp-${MARIADB_CONNECTOR_CPP_VERSION}-win64.msi")
|
||||||
@@ -80,39 +79,23 @@ else() # Build from source
|
|||||||
-DWITH_EXTERNAL_ZLIB=ON
|
-DWITH_EXTERNAL_ZLIB=ON
|
||||||
-DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}
|
-DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}
|
||||||
-DCMAKE_C_FLAGS=-w # disable zlib warnings
|
-DCMAKE_C_FLAGS=-w # disable zlib warnings
|
||||||
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0\ -Wno-inconsistent-missing-override\ -include\ cstdint)
|
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||||
else()
|
else()
|
||||||
set(MARIADB_EXTRA_CMAKE_ARGS
|
set(MARIADB_EXTRA_CMAKE_ARGS
|
||||||
-DCMAKE_C_FLAGS=-w # disable zlib warnings
|
-DCMAKE_C_FLAGS=-w # disable zlib warnings
|
||||||
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0\ -include\ cstdint)
|
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(MARIADBCPP_BUILD_DIR "${PROJECT_BINARY_DIR}/thirdparty/mariadb-connector-cpp/src/mariadb_connector_cpp-build")
|
|
||||||
set(MARIADBCPP_INSTALL_DIR ${PROJECT_BINARY_DIR}/prefix)
|
set(MARIADBCPP_INSTALL_DIR ${PROJECT_BINARY_DIR}/prefix)
|
||||||
|
set(MARIADBCPP_LIBRARY_DIR ${PROJECT_BINARY_DIR}/mariadbcpp)
|
||||||
|
set(MARIADBCPP_PLUGIN_DIR ${MARIADBCPP_LIBRARY_DIR}/plugin)
|
||||||
set(MARIADBCPP_SOURCE_DIR ${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp)
|
set(MARIADBCPP_SOURCE_DIR ${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp)
|
||||||
set(MARIADB_INCLUDE_DIR "${MARIADBCPP_SOURCE_DIR}/include")
|
set(MARIADB_INCLUDE_DIR "${MARIADBCPP_SOURCE_DIR}/include")
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
set(MARIADBCPP_LIBRARY_DIR ${PROJECT_BINARY_DIR}/mariadbcpp)
|
|
||||||
set(MARIADBCPP_PLUGIN_DIR ${MARIADBCPP_LIBRARY_DIR}/plugin)
|
|
||||||
set(MARIADB_INSTALL_COMMAND)
|
|
||||||
else()
|
|
||||||
set(MARIADBCPP_LIBRARY_DIR ${MARIADBCPP_BUILD_DIR})
|
|
||||||
set(MARIADBCPP_PLUGIN_DIR ${MARIADBCPP_BUILD_DIR}/libmariadb)
|
|
||||||
set(MARIADB_INSTALL_COMMAND INSTALL_COMMAND ${CMAKE_COMMAND} -E true)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
|
|
||||||
set(MARIADB_POLICY_VERSION_ARG -DCMAKE_POLICY_VERSION_MINIMUM=3.5)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ExternalProject_Add(mariadb_connector_cpp
|
ExternalProject_Add(mariadb_connector_cpp
|
||||||
PREFIX "${PROJECT_BINARY_DIR}/thirdparty/mariadb-connector-cpp"
|
PREFIX "${PROJECT_BINARY_DIR}/thirdparty/mariadb-connector-cpp"
|
||||||
SOURCE_DIR ${MARIADBCPP_SOURCE_DIR}
|
SOURCE_DIR ${MARIADBCPP_SOURCE_DIR}
|
||||||
BINARY_DIR ${MARIADBCPP_BUILD_DIR}
|
|
||||||
INSTALL_DIR ${MARIADBCPP_INSTALL_DIR}
|
INSTALL_DIR ${MARIADBCPP_INSTALL_DIR}
|
||||||
CMAKE_ARGS -Wno-dev
|
CMAKE_ARGS -Wno-dev
|
||||||
${MARIADB_POLICY_VERSION_ARG}
|
|
||||||
-DWITH_UNIT_TESTS=OFF
|
-DWITH_UNIT_TESTS=OFF
|
||||||
-DMARIADB_LINK_DYNAMIC=OFF
|
-DMARIADB_LINK_DYNAMIC=OFF
|
||||||
-DCMAKE_BUILD_RPATH_USE_ORIGIN=${CMAKE_BUILD_RPATH_USE_ORIGIN}
|
-DCMAKE_BUILD_RPATH_USE_ORIGIN=${CMAKE_BUILD_RPATH_USE_ORIGIN}
|
||||||
@@ -120,7 +103,6 @@ else() # Build from source
|
|||||||
-DINSTALL_LIBDIR=${MARIADBCPP_LIBRARY_DIR}
|
-DINSTALL_LIBDIR=${MARIADBCPP_LIBRARY_DIR}
|
||||||
-DINSTALL_PLUGINDIR=${MARIADBCPP_PLUGIN_DIR}
|
-DINSTALL_PLUGINDIR=${MARIADBCPP_PLUGIN_DIR}
|
||||||
${MARIADB_EXTRA_CMAKE_ARGS}
|
${MARIADB_EXTRA_CMAKE_ARGS}
|
||||||
${MARIADB_INSTALL_COMMAND}
|
|
||||||
BUILD_ALWAYS true
|
BUILD_ALWAYS true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
//Auth includes:
|
//Auth includes:
|
||||||
#include "AuthPackets.h"
|
#include "AuthPackets.h"
|
||||||
|
#include "CommonPackets.h"
|
||||||
#include "ServiceType.h"
|
#include "ServiceType.h"
|
||||||
#include "MessageType/Server.h"
|
#include "MessageType/Server.h"
|
||||||
#include "MessageType/Auth.h"
|
#include "MessageType/Auth.h"
|
||||||
@@ -52,7 +53,6 @@ int main(int argc, char** argv) {
|
|||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Server::SetupLogger("AuthServer");
|
Server::SetupLogger("AuthServer");
|
||||||
if (!Game::logger) return EXIT_FAILURE;
|
if (!Game::logger) return EXIT_FAILURE;
|
||||||
Game::config->LogSettings();
|
|
||||||
|
|
||||||
LOG("Starting Auth server...");
|
LOG("Starting Auth server...");
|
||||||
LOG("Version: %s", PROJECT_VERSION);
|
LOG("Version: %s", PROJECT_VERSION);
|
||||||
@@ -165,17 +165,12 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
if (packet->length < 4) return;
|
CINSTREAM;
|
||||||
|
LUBitStream luBitStream;
|
||||||
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
if (!luBitStream.ReadHeader(inStream) && luBitStream.rakNetID != ID_USER_PACKET_ENUM) return;
|
||||||
if (static_cast<ServiceType>(packet->data[1]) == ServiceType::COMMON) {
|
else if (luBitStream.serviceType == ServiceType::COMMON) {
|
||||||
if (static_cast<MessageType::Server>(packet->data[3]) == MessageType::Server::VERSION_CONFIRM) {
|
CommonPackets::Handle(inStream, packet->systemAddress);
|
||||||
AuthPackets::HandleHandshake(Game::server, packet);
|
} else if (luBitStream.serviceType == ServiceType::AUTH) {
|
||||||
}
|
AuthPackets::Handle(inStream, packet->systemAddress);
|
||||||
} else if (static_cast<ServiceType>(packet->data[1]) == ServiceType::AUTH) {
|
|
||||||
if (static_cast<MessageType::Auth>(packet->data[3]) == MessageType::Auth::LOGIN_REQUEST) {
|
|
||||||
AuthPackets::HandleLoginRequest(Game::server, packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "MessageType/Chat.h"
|
#include "MessageType/Chat.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dConfig.h"
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
|
|
||||||
@@ -35,7 +34,7 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
|
|||||||
if (!receiver.ignoredPlayers.empty()) {
|
if (!receiver.ignoredPlayers.empty()) {
|
||||||
LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
|
LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
|
||||||
} else {
|
} else {
|
||||||
auto ignoreList = Database::Get()->GetIgnoreList(playerId);
|
auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId));
|
||||||
if (ignoreList.empty()) {
|
if (ignoreList.empty()) {
|
||||||
LOG_DEBUG("Player %llu has no ignores", playerId);
|
LOG_DEBUG("Player %llu has no ignores", playerId);
|
||||||
return;
|
return;
|
||||||
@@ -44,6 +43,7 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
|
|||||||
for (auto& ignoredPlayer : ignoreList) {
|
for (auto& ignoredPlayer : ignoreList) {
|
||||||
receiver.ignoredPlayers.emplace_back(ignoredPlayer.name, ignoredPlayer.id);
|
receiver.ignoredPlayers.emplace_back(ignoredPlayer.name, ignoredPlayer.id);
|
||||||
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
|
||||||
|
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::PERSISTENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +73,8 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t MAX_IGNORES = Game::config->GetValue("max_ignores", 32);
|
constexpr int32_t MAX_IGNORES = 32;
|
||||||
if (receiver.ignoredPlayers.size() >= MAX_IGNORES) {
|
if (receiver.ignoredPlayers.size() > MAX_IGNORES) {
|
||||||
LOG_DEBUG("Player %llu has too many ignores", playerId);
|
LOG_DEBUG("Player %llu has too many ignores", playerId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -114,8 +114,9 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ignoredPlayerId != LWOOBJID_EMPTY) {
|
if (ignoredPlayerId != LWOOBJID_EMPTY) {
|
||||||
Database::Get()->AddIgnore(playerId, ignoredPlayerId);
|
Database::Get()->AddIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(ignoredPlayerId));
|
||||||
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
|
||||||
|
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT);
|
||||||
|
|
||||||
receiver.ignoredPlayers.emplace_back(toIgnoreStr, ignoredPlayerId);
|
receiver.ignoredPlayers.emplace_back(toIgnoreStr, ignoredPlayerId);
|
||||||
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
|
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
|
||||||
@@ -156,7 +157,7 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::Get()->RemoveIgnore(playerId, toRemove->playerId);
|
Database::Get()->RemoveIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(toRemove->playerId));
|
||||||
receiver.ignoredPlayers.erase(toRemove, receiver.ignoredPlayers.end());
|
receiver.ignoredPlayers.erase(toRemove, receiver.ignoredPlayers.end());
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
FriendData fd;
|
FriendData fd;
|
||||||
fd.isFTP = false; // not a thing in DLU
|
fd.isFTP = false; // not a thing in DLU
|
||||||
fd.friendID = friendData.friendID;
|
fd.friendID = friendData.friendID;
|
||||||
|
GeneralUtils::SetBit(fd.friendID, eObjectBits::PERSISTENT);
|
||||||
GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER);
|
||||||
|
|
||||||
fd.isBestFriend = friendData.isBestFriend; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
fd.isBestFriend = friendData.isBestFriend; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||||
@@ -160,7 +161,9 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
|
|
||||||
// Set the bits
|
// Set the bits
|
||||||
GeneralUtils::SetBit(queryPlayerID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(queryPlayerID, eObjectBits::CHARACTER);
|
||||||
|
GeneralUtils::SetBit(queryPlayerID, eObjectBits::PERSISTENT);
|
||||||
GeneralUtils::SetBit(queryFriendID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(queryFriendID, eObjectBits::CHARACTER);
|
||||||
|
GeneralUtils::SetBit(queryFriendID, eObjectBits::PERSISTENT);
|
||||||
|
|
||||||
// Since this player can either be the friend of someone else or be friends with someone else
|
// Since this player can either be the friend of someone else or be friends with someone else
|
||||||
// their column in the database determines what bit gets set. When the value hits 3, they
|
// their column in the database determines what bit gets set. When the value hits 3, they
|
||||||
@@ -315,6 +318,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert friendID to LWOOBJID
|
// Convert friendID to LWOOBJID
|
||||||
|
GeneralUtils::SetBit(friendID, eObjectBits::PERSISTENT);
|
||||||
GeneralUtils::SetBit(friendID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(friendID, eObjectBits::CHARACTER);
|
||||||
|
|
||||||
Database::Get()->RemoveFriend(playerID, friendID);
|
Database::Get()->RemoveFriend(playerID, friendID);
|
||||||
@@ -435,11 +439,6 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
inStream.IgnoreBytes(4);
|
inStream.IgnoreBytes(4);
|
||||||
inStream.Read(channel);
|
inStream.Read(channel);
|
||||||
inStream.Read(size);
|
inStream.Read(size);
|
||||||
if (size > MAX_MESSAGE_LENGTH) {
|
|
||||||
LOG("Received a probably spoofed chat message, ignoring msg");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
inStream.IgnoreBytes(77);
|
inStream.IgnoreBytes(77);
|
||||||
|
|
||||||
LUWString message(size);
|
LUWString message(size);
|
||||||
@@ -484,11 +483,6 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
if (channel != eChatChannel::PRIVATE_CHAT) LOG("WARNING: Received Private chat with the wrong channel!");
|
if (channel != eChatChannel::PRIVATE_CHAT) LOG("WARNING: Received Private chat with the wrong channel!");
|
||||||
|
|
||||||
inStream.Read(size);
|
inStream.Read(size);
|
||||||
if (size > MAX_MESSAGE_LENGTH) {
|
|
||||||
LOG("Received a probably spoofed chat message, ignoring msg");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
inStream.IgnoreBytes(77);
|
inStream.IgnoreBytes(77);
|
||||||
|
|
||||||
inStream.Read(LUReceiverName);
|
inStream.Read(LUReceiverName);
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ int main(int argc, char** argv) {
|
|||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Server::SetupLogger("ChatServer");
|
Server::SetupLogger("ChatServer");
|
||||||
if (!Game::logger) return EXIT_FAILURE;
|
if (!Game::logger) return EXIT_FAILURE;
|
||||||
Game::config->LogSettings();
|
|
||||||
|
|
||||||
//Read our config:
|
//Read our config:
|
||||||
|
|
||||||
@@ -202,11 +201,8 @@ int main(int argc, char** argv) {
|
|||||||
//Delete our objects here:
|
//Delete our objects here:
|
||||||
Database::Destroy("ChatServer");
|
Database::Destroy("ChatServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
Game::server = nullptr;
|
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
Game::logger = nullptr;
|
|
||||||
delete Game::config;
|
delete Game::config;
|
||||||
Game::config = nullptr;
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,15 @@ void PlayerContainer::RemovePlayer(const LWOOBJID playerID) {
|
|||||||
auto* team = TeamContainer::GetTeam(playerID);
|
auto* team = TeamContainer::GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
TeamContainer::RemoveMember(team, playerID, false, false, true);
|
const auto memberName = GeneralUtils::UTF8ToUTF16(player.playerName);
|
||||||
|
|
||||||
|
for (const auto memberId : team->memberIDs) {
|
||||||
|
const auto& otherMember = GetPlayerData(memberId);
|
||||||
|
|
||||||
|
if (!otherMember) continue;
|
||||||
|
|
||||||
|
TeamContainer::SendTeamSetOffWorldFlag(otherMember, playerID, { 0, 0, 0 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatWeb::SendWSPlayerUpdate(player, eActivityType::PlayerLoggedOut);
|
ChatWeb::SendWSPlayerUpdate(player, eActivityType::PlayerLoggedOut);
|
||||||
@@ -168,7 +176,6 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Make this a pointer again or do something to make it so you cant edit the LWOOBJID_EMPTY entry? it should be ignored in all cases anyways though...
|
|
||||||
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
|
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
|
||||||
return m_Players.contains(playerID) ? m_Players[playerID] : m_Players[LWOOBJID_EMPTY];
|
return m_Players.contains(playerID) ? m_Players[playerID] : m_Players[LWOOBJID_EMPTY];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ TeamData* TeamContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newTeam->lootFlag = 0;
|
newTeam->lootFlag = 1;
|
||||||
|
|
||||||
TeamStatusUpdate(newTeam);
|
TeamStatusUpdate(newTeam);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "Amf3.h"
|
#include "Amf3.h"
|
||||||
#include "StringifiedEnum.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
|
||||||
@@ -54,7 +53,7 @@ std::unique_ptr<AMFBaseValue> AMFDeserialize::Read(RakNet::BitStream& inStream)
|
|||||||
case eAmf::VectorObject:
|
case eAmf::VectorObject:
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case eAmf::Dictionary:
|
case eAmf::Dictionary:
|
||||||
throw std::invalid_argument(StringifiedEnum::ToString(marker).data());
|
throw marker;
|
||||||
default:
|
default:
|
||||||
throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast<int32_t>(marker)));
|
throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast<int32_t>(marker)));
|
||||||
}
|
}
|
||||||
@@ -89,11 +88,6 @@ const std::string AMFDeserialize::ReadString(RakNet::BitStream& inStream) {
|
|||||||
// Right shift by 1 bit to get index if reference or size of next string if value
|
// Right shift by 1 bit to get index if reference or size of next string if value
|
||||||
length = length >> 1;
|
length = length >> 1;
|
||||||
if (isReference) {
|
if (isReference) {
|
||||||
constexpr int32_t maxStringSize = 1024 * 1024;
|
|
||||||
if (length > maxStringSize) {
|
|
||||||
LOG("1MB string attempted to be allocated in AMF deserialize, possible spoof, aborting deserialize.");
|
|
||||||
throw std::invalid_argument("1MB string attempted to be allocated in AMF deserialize, possible spoof, aborting deserialize.");
|
|
||||||
}
|
|
||||||
std::string value(length, 0);
|
std::string value(length, 0);
|
||||||
inStream.Read(&value[0], length);
|
inStream.Read(&value[0], length);
|
||||||
// Empty strings are never sent by reference
|
// Empty strings are never sent by reference
|
||||||
@@ -123,12 +117,6 @@ std::unique_ptr<AMFArrayValue> AMFDeserialize::ReadAmfArray(RakNet::BitStream& i
|
|||||||
if (key.size() == 0) break;
|
if (key.size() == 0) break;
|
||||||
arrayValue->Insert(key, Read(inStream));
|
arrayValue->Insert(key, Read(inStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int32_t maxArraySize = 10'000;
|
|
||||||
if (sizeOfDenseArray > maxArraySize) {
|
|
||||||
LOG("Someone sent 10,000 dense array entries, probably a bad packet.");
|
|
||||||
throw std::invalid_argument("Someone sent 10,000 dense array entries, probably a bad packet.");
|
|
||||||
}
|
|
||||||
// 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->Insert(i, Read(inStream));
|
arrayValue->Insert(i, Read(inStream));
|
||||||
|
|||||||
@@ -369,39 +369,11 @@ public:
|
|||||||
|
|
||||||
template<typename AmfType = AMFArrayValue>
|
template<typename AmfType = AMFArrayValue>
|
||||||
AmfType& PushDebug(const std::string_view name) {
|
AmfType& PushDebug(const std::string_view name) {
|
||||||
size_t i = 0;
|
|
||||||
for (; i < m_Dense.size(); i++) {
|
|
||||||
const auto& cast = dynamic_cast<AMFArrayValue*>(m_Dense[i].get());
|
|
||||||
if (!cast) continue;
|
|
||||||
|
|
||||||
const auto& nameValue = cast->Get<std::string>("name");
|
|
||||||
if (!nameValue || nameValue->GetValue() != name) continue;
|
|
||||||
|
|
||||||
// found a duplicate, return this instead
|
|
||||||
auto valueCast = dynamic_cast<AmfType*>(cast->Get("value"));
|
|
||||||
if (valueCast) return *valueCast;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* value = PushArray();
|
auto* value = PushArray();
|
||||||
value->Insert<std::string>("name", name.data());
|
value->Insert("name", name.data());
|
||||||
return value->Insert<AmfType>("value", std::make_unique<AmfType>());
|
return value->Insert<AmfType>("value", std::make_unique<AmfType>());
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFArrayValue& PushDebug(const NiPoint3& point) {
|
|
||||||
PushDebug<AMFDoubleValue>("X") = point.x;
|
|
||||||
PushDebug<AMFDoubleValue>("Y") = point.y;
|
|
||||||
PushDebug<AMFDoubleValue>("Z") = point.z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
AMFArrayValue& PushDebug(const NiQuaternion& rot) {
|
|
||||||
PushDebug<AMFDoubleValue>("W") = rot.w;
|
|
||||||
PushDebug<AMFDoubleValue>("X") = rot.x;
|
|
||||||
PushDebug<AMFDoubleValue>("Y") = rot.y;
|
|
||||||
PushDebug<AMFDoubleValue>("Z") = rot.z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The associative portion. These values are key'd with strings to an AMFValue.
|
* The associative portion. These values are key'd with strings to an AMFValue.
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
|
|
||||||
if (actualUncompressedSize != -1) {
|
if (actualUncompressedSize != -1) {
|
||||||
uint32_t previousSize = completeUncompressedModel.size();
|
uint32_t previousSize = completeUncompressedModel.size();
|
||||||
completeUncompressedModel.append(reinterpret_cast<char*>(uncompressedChunk.get()), actualUncompressedSize);
|
completeUncompressedModel.append(reinterpret_cast<char*>(uncompressedChunk.get()));
|
||||||
|
completeUncompressedModel.resize(previousSize + actualUncompressedSize);
|
||||||
} else {
|
} else {
|
||||||
LOG("Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, model.id, err);
|
LOG("Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, model.id, err);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -49,24 +49,24 @@ if (UNIX)
|
|||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
# TODO Keep an eye on the zlib repository for an update to disable testing. Don't forget to update CMakePresets
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
zlib
|
zlib
|
||||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.3.2.zip
|
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
||||||
URL_HASH MD5=adbba6eef8960c3412818b2e241f46dc
|
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
|
||||||
GIT_PROGRESS TRUE
|
GIT_PROGRESS TRUE
|
||||||
GIT_SHALLOW 1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Disable warning about no project version.
|
# Disable warning about no project version.
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
|
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
|
||||||
# Disable warning about the minimum version of cmake used for bcrypt being deprecated in the future
|
# Disable warning about the minimum version of cmake used for bcrypt being deprecated in the future
|
||||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
|
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
|
||||||
# Disable zlib tests
|
|
||||||
set(ZLIB_BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
|
||||||
|
|
||||||
FetchContent_MakeAvailable(zlib)
|
FetchContent_MakeAvailable(zlib)
|
||||||
|
|
||||||
set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
|
set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
|
||||||
|
set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}")
|
||||||
|
add_library(ZLIB::ZLIB ALIAS zlib)
|
||||||
else ()
|
else ()
|
||||||
message(
|
message(
|
||||||
FATAL_ERROR
|
FATAL_ERROR
|
||||||
|
|||||||
@@ -308,9 +308,8 @@ std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::stri
|
|||||||
for (const auto& t : std::filesystem::directory_iterator(folder)) {
|
for (const auto& t : std::filesystem::directory_iterator(folder)) {
|
||||||
if (t.is_directory() || t.is_symlink()) continue;
|
if (t.is_directory() || t.is_symlink()) continue;
|
||||||
auto filename = t.path().filename().string();
|
auto filename = t.path().filename().string();
|
||||||
// Ensure the file has a name in the format of xxxxxxxx_anything_goes_here.sql
|
const auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
|
||||||
const auto migrationNumber = TryParse<uint32_t>(GeneralUtils::SplitString(filename, '_').at(0));
|
filenames.emplace(index, std::move(filename));
|
||||||
if (migrationNumber.has_value()) filenames.emplace(migrationNumber.value(), std::move(filename));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now sort the map by the oldest migration.
|
// Now sort the map by the oldest migration.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// C++
|
// C++
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
#include "dPlatforms.h"
|
#include "dPlatforms.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "DluAssert.h"
|
|
||||||
|
|
||||||
#include <glm/ext/vector_float3.hpp>
|
#include <glm/ext/vector_float3.hpp>
|
||||||
|
|
||||||
@@ -205,12 +204,6 @@ namespace GeneralUtils {
|
|||||||
return isParsed ? static_cast<T>(result) : std::optional<T>{};
|
return isParsed ? static_cast<T>(result) : std::optional<T>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
// A version of TryParse that will return `errorVal` if `str` failed to parse.
|
|
||||||
template <Numeric T>
|
|
||||||
[[nodiscard]] T TryParse(std::string_view str, const T errorVal) {
|
|
||||||
return TryParse<T>(str).value_or(errorVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires(!Numeric<T>)
|
requires(!Numeric<T>)
|
||||||
[[nodiscard]] std::optional<T> TryParse(std::string_view str);
|
[[nodiscard]] std::optional<T> TryParse(std::string_view str);
|
||||||
@@ -243,12 +236,6 @@ namespace GeneralUtils {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A version of TryParse that will return `errorVal` if `str` failed to parse.
|
|
||||||
template <std::floating_point T>
|
|
||||||
[[nodiscard]] T TryParse(std::string_view str, const T errorVal) {
|
|
||||||
return TryParse<T>(str).value_or(errorVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -270,11 +257,6 @@ namespace GeneralUtils {
|
|||||||
return z ? std::make_optional<T>(x.value(), y.value(), z.value()) : std::nullopt;
|
return z ? std::make_optional<T>(x.value(), y.value(), z.value()) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alternative overload of TryParse with a default value
|
|
||||||
[[nodiscard]] inline NiPoint3 TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ, const NiPoint3 errorVal) {
|
|
||||||
return TryParse<NiPoint3>(strX, strY, strZ).value_or(errorVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TryParse overload for handling NiPoint3 by passing a span of three strings
|
* The TryParse overload for handling NiPoint3 by passing a span of three strings
|
||||||
* @param str The string vector representing the X, Y, and Z coordinates
|
* @param str The string vector representing the X, Y, and Z coordinates
|
||||||
@@ -285,11 +267,6 @@ namespace GeneralUtils {
|
|||||||
return (str.size() == 3) ? TryParse<T>(str[0], str[1], str[2]) : std::nullopt;
|
return (str.size() == 3) ? TryParse<T>(str[0], str[1], str[2]) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alternative overload of TryParse with a default value
|
|
||||||
[[nodiscard]] inline NiPoint3 TryParse(const std::span<const std::string> str, const NiPoint3 errorVal) {
|
|
||||||
return TryParse<NiPoint3>(str).value_or(errorVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::u16string to_u16string(const T value) {
|
std::u16string to_u16string(const T value) {
|
||||||
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
||||||
@@ -328,7 +305,7 @@ namespace GeneralUtils {
|
|||||||
template<typename Container>
|
template<typename Container>
|
||||||
inline Container::value_type GetRandomElement(const Container& container) {
|
inline Container::value_type GetRandomElement(const Container& container) {
|
||||||
DluAssert(!container.empty());
|
DluAssert(!container.empty());
|
||||||
return container[GenerateRandomNumber<typename Container::size_type>(0, container.size() - 1)];
|
return container[GenerateRandomNumber<typename Container::value_type>(0, container.size() - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,151 +10,163 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
using LDFKey = std::string_view;
|
||||||
|
using LDFTypeAndValue = std::string_view;
|
||||||
|
|
||||||
|
using LDFType = std::string_view;
|
||||||
|
using LDFValue = std::string_view;
|
||||||
|
|
||||||
//! Returns a pointer to a LDFData value based on string format
|
//! Returns a pointer to a LDFData value based on string format
|
||||||
std::unique_ptr<LDFBaseData> LDFBaseData::DataFromString(const std::string_view& format) {
|
LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
||||||
std::unique_ptr<LDFBaseData> toReturn;
|
|
||||||
// A valid LDF must be at least 3 characters long (=0:) is the shortest valid LDF (empty UTF-16 key with no initial value)
|
// A valid LDF must be at least 3 characters long (=0:) is the shortest valid LDF (empty UTF-16 key with no initial value)
|
||||||
if (!format.empty() && format.length() > 2) {
|
if (format.empty() || format.length() <= 2) return nullptr;
|
||||||
auto equalsPosition = format.find('=');
|
auto equalsPosition = format.find('=');
|
||||||
// You can have an empty key, just make sure the type and value might exist
|
// You can have an empty key, just make sure the type and value might exist
|
||||||
if (equalsPosition != std::string::npos && equalsPosition != (format.size() - 1)) {
|
if (equalsPosition == std::string::npos || equalsPosition == (format.size() - 1)) return nullptr;
|
||||||
|
|
||||||
const std::string_view keyValue = format.substr(0, equalsPosition);
|
std::pair<LDFKey, LDFTypeAndValue> keyValue;
|
||||||
const std::string_view typeAndValue = format.substr(equalsPosition + 1, format.size());
|
keyValue.first = format.substr(0, equalsPosition);
|
||||||
|
keyValue.second = format.substr(equalsPosition + 1, format.size());
|
||||||
|
|
||||||
const auto key = GeneralUtils::ASCIIToUTF16(keyValue);
|
std::u16string key = GeneralUtils::ASCIIToUTF16(keyValue.first);
|
||||||
|
|
||||||
const auto colonPosition = typeAndValue.find(':');
|
auto colonPosition = keyValue.second.find(':');
|
||||||
|
|
||||||
// If : is the first thing after an =, then this is an invalid LDF since
|
// If : is the first thing after an =, then this is an invalid LDF since
|
||||||
// we dont have a type to use.
|
// we dont have a type to use.
|
||||||
if (colonPosition != std::string::npos && colonPosition != 0) {
|
if (colonPosition == std::string::npos || colonPosition == 0) return nullptr;
|
||||||
const std::string_view ldfType = typeAndValue.substr(0, colonPosition);
|
|
||||||
const std::string_view ldfValue = typeAndValue.substr(colonPosition + 1, typeAndValue.size());
|
|
||||||
|
|
||||||
// Only allow empty values for string values.
|
std::pair<LDFType, LDFValue> ldfTypeAndValue;
|
||||||
if (!ldfValue.empty() || (ldfType == "0" /* UTF-16 */ || ldfType == "13" /* UTF-8 */)) {
|
ldfTypeAndValue.first = keyValue.second.substr(0, colonPosition);
|
||||||
const eLDFType type = GeneralUtils::TryParse<eLDFType>(ldfType, LDF_TYPE_UNKNOWN);
|
ldfTypeAndValue.second = keyValue.second.substr(colonPosition + 1, keyValue.second.size());
|
||||||
switch (type) {
|
|
||||||
case LDF_TYPE_UTF_16: {
|
|
||||||
std::u16string data = GeneralUtils::UTF8ToUTF16(ldfValue);
|
|
||||||
toReturn.reset(new LDFData<std::u16string>(key, data));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LDF_TYPE_S32: {
|
// Only allow empty values for string values.
|
||||||
const auto data = GeneralUtils::TryParse<int32_t>(ldfValue);
|
if (ldfTypeAndValue.second.size() == 0 && !(ldfTypeAndValue.first == "0" || ldfTypeAndValue.first == "13")) return nullptr;
|
||||||
if (data) {
|
|
||||||
toReturn.reset(new LDFData<int32_t>(key, data.value()));
|
|
||||||
} else {
|
|
||||||
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfValue.data(), format.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
eLDFType type;
|
||||||
}
|
char* storage;
|
||||||
|
try {
|
||||||
case LDF_TYPE_FLOAT: {
|
type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10));
|
||||||
const auto data = GeneralUtils::TryParse<float>(ldfValue);
|
} catch (std::exception) {
|
||||||
if (data) {
|
LOG("Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
|
||||||
toReturn.reset(new LDFData<float>(key, data.value()));
|
return nullptr;
|
||||||
} else {
|
|
||||||
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfValue.data(), format.data());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LDF_TYPE_DOUBLE: {
|
|
||||||
const auto data = GeneralUtils::TryParse<double>(ldfValue);
|
|
||||||
if (data) {
|
|
||||||
toReturn.reset(new LDFData<double>(key, data.value()));
|
|
||||||
} else {
|
|
||||||
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfValue.data(), format.data());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LDF_TYPE_U32:
|
|
||||||
{
|
|
||||||
uint32_t data;
|
|
||||||
bool parsed = true;
|
|
||||||
// Have to do this really weird parsing to allow for copy ellision
|
|
||||||
if (ldfValue == "true") {
|
|
||||||
data = 1;
|
|
||||||
} else if (ldfValue == "false") {
|
|
||||||
data = 0;
|
|
||||||
} else {
|
|
||||||
const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfValue);
|
|
||||||
if (!dataOptional) {
|
|
||||||
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfValue.data(), format.data());
|
|
||||||
parsed = false;
|
|
||||||
} else {
|
|
||||||
data = dataOptional.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parsed) toReturn.reset(new LDFData<uint32_t>(key, data));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LDF_TYPE_BOOLEAN: {
|
|
||||||
bool data;
|
|
||||||
bool parsed = true;
|
|
||||||
// Have to do this really weird parsing to allow for copy ellision
|
|
||||||
if (ldfValue == "true") {
|
|
||||||
data = true;
|
|
||||||
} else if (ldfValue == "false") {
|
|
||||||
data = false;
|
|
||||||
} else {
|
|
||||||
const auto dataOptional = GeneralUtils::TryParse<bool>(ldfValue);
|
|
||||||
if (!dataOptional) {
|
|
||||||
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfValue.data(), format.data());
|
|
||||||
parsed = false;
|
|
||||||
} else {
|
|
||||||
data = dataOptional.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parsed) toReturn.reset(new LDFData<bool>(key, data));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LDF_TYPE_U64: {
|
|
||||||
const auto data = GeneralUtils::TryParse<uint64_t>(ldfValue);
|
|
||||||
if (data) {
|
|
||||||
toReturn.reset(new LDFData<uint64_t>(key, data.value()));
|
|
||||||
} else {
|
|
||||||
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfValue.data(), format.data());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LDF_TYPE_OBJID: {
|
|
||||||
const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfValue);
|
|
||||||
if (data) {
|
|
||||||
toReturn.reset(new LDFData<LWOOBJID>(key, data.value()));
|
|
||||||
} else {
|
|
||||||
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfValue.data(), format.data());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LDF_TYPE_UTF_8: {
|
|
||||||
toReturn.reset(new LDFData<std::string>(key, ldfValue.data()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LDF_TYPE_UNKNOWN:
|
|
||||||
[[fallthrough]];
|
|
||||||
default: {
|
|
||||||
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfValue.data(), format.data());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
LDFBaseData* returnValue = nullptr;
|
||||||
|
switch (type) {
|
||||||
|
case LDF_TYPE_UTF_16: {
|
||||||
|
std::u16string data = GeneralUtils::UTF8ToUTF16(ldfTypeAndValue.second);
|
||||||
|
returnValue = new LDFData<std::u16string>(key, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_S32: {
|
||||||
|
const auto data = GeneralUtils::TryParse<int32_t>(ldfTypeAndValue.second);
|
||||||
|
if (!data) {
|
||||||
|
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
returnValue = new LDFData<int32_t>(key, data.value());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_FLOAT: {
|
||||||
|
const auto data = GeneralUtils::TryParse<float>(ldfTypeAndValue.second);
|
||||||
|
if (!data) {
|
||||||
|
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
returnValue = new LDFData<float>(key, data.value());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_DOUBLE: {
|
||||||
|
const auto data = GeneralUtils::TryParse<double>(ldfTypeAndValue.second);
|
||||||
|
if (!data) {
|
||||||
|
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
returnValue = new LDFData<double>(key, data.value());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_U32:
|
||||||
|
{
|
||||||
|
uint32_t data;
|
||||||
|
|
||||||
|
if (ldfTypeAndValue.second == "true") {
|
||||||
|
data = 1;
|
||||||
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
|
data = 0;
|
||||||
|
} else {
|
||||||
|
const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfTypeAndValue.second);
|
||||||
|
if (!dataOptional) {
|
||||||
|
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
data = dataOptional.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue = new LDFData<uint32_t>(key, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_BOOLEAN: {
|
||||||
|
bool data;
|
||||||
|
|
||||||
|
if (ldfTypeAndValue.second == "true") {
|
||||||
|
data = true;
|
||||||
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
|
data = false;
|
||||||
|
} else {
|
||||||
|
const auto dataOptional = GeneralUtils::TryParse<bool>(ldfTypeAndValue.second);
|
||||||
|
if (!dataOptional) {
|
||||||
|
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
data = dataOptional.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue = new LDFData<bool>(key, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_U64: {
|
||||||
|
const auto data = GeneralUtils::TryParse<uint64_t>(ldfTypeAndValue.second);
|
||||||
|
if (!data) {
|
||||||
|
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
returnValue = new LDFData<uint64_t>(key, data.value());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_OBJID: {
|
||||||
|
const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfTypeAndValue.second);
|
||||||
|
if (!data) {
|
||||||
|
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
returnValue = new LDFData<LWOOBJID>(key, data.value());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_UTF_8: {
|
||||||
|
std::string data = ldfTypeAndValue.second.data();
|
||||||
|
returnValue = new LDFData<std::string>(key, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LDF_TYPE_UNKNOWN: {
|
||||||
|
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
LOG("Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
#ifndef LDFFORMAT_H
|
#ifndef __LDFFORMAT__H__
|
||||||
#define LDFFORMAT_H
|
#define __LDFFORMAT__H__
|
||||||
|
|
||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
// C++
|
// C++
|
||||||
#include <map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -47,17 +46,17 @@ public:
|
|||||||
|
|
||||||
virtual std::string GetValueAsString() const = 0;
|
virtual std::string GetValueAsString() const = 0;
|
||||||
|
|
||||||
virtual std::unique_ptr<LDFBaseData> Copy() const = 0;
|
virtual LDFBaseData* Copy() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an input string, return the data as a LDF key.
|
* Given an input string, return the data as a LDF key.
|
||||||
*/
|
*/
|
||||||
static std::unique_ptr<LDFBaseData> DataFromString(const std::string_view& format);
|
static LDFBaseData* DataFromString(const std::string_view& format);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class LDFData : public LDFBaseData {
|
class LDFData: public LDFBaseData {
|
||||||
private:
|
private:
|
||||||
std::u16string key;
|
std::u16string key;
|
||||||
T value;
|
T value;
|
||||||
@@ -165,8 +164,8 @@ public:
|
|||||||
return this->GetValueString();
|
return this->GetValueString();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<LDFBaseData> Copy() const override {
|
LDFBaseData* Copy() const override {
|
||||||
return std::make_unique<LDFData<T>>(key, value);
|
return new LDFData<T>(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static const T Default = {};
|
inline static const T Default = {};
|
||||||
@@ -227,89 +226,4 @@ template<> inline std::string LDFData<LWOOBJID>::GetValueString() const { return
|
|||||||
|
|
||||||
template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; }
|
template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; }
|
||||||
|
|
||||||
struct LwoNameValue {
|
#endif //!__LDFFORMAT__H__
|
||||||
using LDFPtr = std::unique_ptr<LDFBaseData>;
|
|
||||||
using ValueType = std::map<std::u16string, LDFPtr>;
|
|
||||||
|
|
||||||
LwoNameValue& operator=(const LwoNameValue& other) {
|
|
||||||
this->values = other.Copy();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void Insert(const std::u16string& key, const T& value) {
|
|
||||||
this->values.insert_or_assign(key, std::unique_ptr(std::make_unique<LDFData<T>>(key, value)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Insert(const std::u16string& key, const char* value) {
|
|
||||||
this->Insert<std::string>(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Insert(const std::u16string& key, const char16_t* value) {
|
|
||||||
this->Insert<std::u16string>(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void Insert(const std::string& key, const T& value) {
|
|
||||||
this->Insert<T>(GeneralUtils::UTF8ToUTF16(key), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Insert(const std::string& key, const char* value) {
|
|
||||||
this->Insert<std::string>(GeneralUtils::UTF8ToUTF16(key), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Insert(const std::string& key, const char16_t* value) {
|
|
||||||
this->Insert<std::u16string>(GeneralUtils::UTF8ToUTF16(key), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const LDFPtr& ParseInsert(const std::string& data) {
|
|
||||||
LDFPtr toInsert(LDFBaseData::DataFromString(data));
|
|
||||||
return toInsert ?
|
|
||||||
this->values.insert_or_assign(toInsert->GetKey(), std::move(toInsert)).first->second :
|
|
||||||
this->values.insert_or_assign(u"FAILED_TO_PARSE_" + GeneralUtils::UTF8ToUTF16(data), std::make_unique<LDFData<std::string>>("", "")).first->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LDFPtr& ParseInsert(const std::u16string& data) {
|
|
||||||
return this->ParseInsert(GeneralUtils::UTF16ToWTF8(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueType::const_iterator begin() const {
|
|
||||||
return this->values.cbegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueType::const_iterator end() const {
|
|
||||||
return this->values.cend();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Erase(const std::u16string& key) {
|
|
||||||
this->values.erase(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Erase(const std::string& key) {
|
|
||||||
this->Erase(GeneralUtils::ASCIIToUTF16(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueType::iterator find(const ValueType::key_type& key) {
|
|
||||||
return this->values.find(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueType::const_iterator find(const ValueType::key_type& key) const {
|
|
||||||
return this->values.find(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
LwoNameValue() = default;
|
|
||||||
|
|
||||||
LwoNameValue(const LwoNameValue& other) {
|
|
||||||
this->values = other.Copy();
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueType values;
|
|
||||||
private:
|
|
||||||
ValueType Copy() const {
|
|
||||||
ValueType copy;
|
|
||||||
for (const auto& [key, value] : this->values) copy.insert_or_assign(key, value->Copy());
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!LDFFORMAT_H
|
|
||||||
|
|||||||
@@ -96,17 +96,3 @@ bool Logger::GetLogToConsole() const {
|
|||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuncEntry::FuncEntry(const char* funcName, const char* fileName, const uint32_t line) {
|
|
||||||
m_FuncName = funcName;
|
|
||||||
if (!m_FuncName) m_FuncName = "Unknown";
|
|
||||||
m_Line = line;
|
|
||||||
m_FileName = fileName;
|
|
||||||
LOG("--> %s::%s:%i", m_FileName, m_FuncName, m_Line);
|
|
||||||
}
|
|
||||||
|
|
||||||
FuncEntry::~FuncEntry() {
|
|
||||||
if (!m_FuncName || !m_FileName) return;
|
|
||||||
|
|
||||||
LOG("<-- %s::%s:%i", m_FileName, m_FuncName, m_Line);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -32,19 +32,6 @@ constexpr const char* GetFileNameFromAbsolutePath(const char* path) {
|
|||||||
#define LOG(message, ...) do { auto str_ = FILENAME_AND_LINE; Game::logger->Log(str_, message, ##__VA_ARGS__); } while(0)
|
#define LOG(message, ...) do { auto str_ = FILENAME_AND_LINE; Game::logger->Log(str_, message, ##__VA_ARGS__); } while(0)
|
||||||
#define LOG_DEBUG(message, ...) do { auto str_ = FILENAME_AND_LINE; Game::logger->LogDebug(str_, message, ##__VA_ARGS__); } while(0)
|
#define LOG_DEBUG(message, ...) do { auto str_ = FILENAME_AND_LINE; Game::logger->LogDebug(str_, message, ##__VA_ARGS__); } while(0)
|
||||||
|
|
||||||
// Place this right at the start of a function. Will log a message when called and then once you leave the function.
|
|
||||||
#define LOG_ENTRY auto str_ = GetFileNameFromAbsolutePath(__FILE__); FuncEntry funcEntry_(__FUNCTION__, str_, __LINE__)
|
|
||||||
|
|
||||||
class FuncEntry {
|
|
||||||
public:
|
|
||||||
FuncEntry(const char* funcName, const char* fileName, const uint32_t line);
|
|
||||||
~FuncEntry();
|
|
||||||
private:
|
|
||||||
const char* m_FuncName = nullptr;
|
|
||||||
const char* m_FileName = nullptr;
|
|
||||||
uint32_t m_Line = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Writer class for writing data to files.
|
// Writer class for writing data to files.
|
||||||
class Writer {
|
class Writer {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -5,43 +5,13 @@
|
|||||||
#include "TinyXmlUtils.h"
|
#include "TinyXmlUtils.h"
|
||||||
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <functional>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
// The base LXFML xml file to use when creating new models.
|
|
||||||
std::string g_base = R"(<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
|
||||||
<LXFML versionMajor="5" versionMinor="0">
|
|
||||||
<Meta>
|
|
||||||
<Application name="LEGO Universe" versionMajor="0" versionMinor="0"/>
|
|
||||||
<Brand name="LEGOUniverse"/>
|
|
||||||
<BrickSet version="457"/>
|
|
||||||
</Meta>
|
|
||||||
<Bricks>
|
|
||||||
</Bricks>
|
|
||||||
<RigidSystems>
|
|
||||||
</RigidSystems>
|
|
||||||
<GroupSystems>
|
|
||||||
<GroupSystem>
|
|
||||||
</GroupSystem>
|
|
||||||
</GroupSystems>
|
|
||||||
</LXFML>)";
|
|
||||||
}
|
|
||||||
|
|
||||||
Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoint3& curPosition) {
|
Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoint3& curPosition) {
|
||||||
Result toReturn;
|
Result toReturn;
|
||||||
|
|
||||||
// Handle empty or invalid input
|
|
||||||
if (data.empty()) {
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLDocument doc;
|
tinyxml2::XMLDocument doc;
|
||||||
// Use length-based parsing to avoid expensive string copy
|
const auto err = doc.Parse(data.data());
|
||||||
const auto err = doc.Parse(data.data(), data.size());
|
|
||||||
if (err != tinyxml2::XML_SUCCESS) {
|
if (err != tinyxml2::XML_SUCCESS) {
|
||||||
|
LOG("Failed to parse xml %s.", StringifiedEnum::ToString(err).data());
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +20,7 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
|||||||
|
|
||||||
auto lxfml = reader["LXFML"];
|
auto lxfml = reader["LXFML"];
|
||||||
if (!lxfml) {
|
if (!lxfml) {
|
||||||
|
LOG("Failed to find LXFML element.");
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,19 +49,16 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
|||||||
// Calculate the lowest and highest points on the entire model
|
// Calculate the lowest and highest points on the entire model
|
||||||
for (const auto& transformation : transformations | std::views::values) {
|
for (const auto& transformation : transformations | std::views::values) {
|
||||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||||
if (split.size() < 12) continue;
|
if (split.size() < 12) {
|
||||||
|
LOG("Not enough in the split?");
|
||||||
auto xOpt = GeneralUtils::TryParse<float>(split[9]);
|
continue;
|
||||||
auto yOpt = GeneralUtils::TryParse<float>(split[10]);
|
}
|
||||||
auto zOpt = GeneralUtils::TryParse<float>(split[11]);
|
|
||||||
|
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
||||||
if (!xOpt.has_value() || !yOpt.has_value() || !zOpt.has_value()) continue;
|
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
||||||
|
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
||||||
auto x = xOpt.value();
|
if (x < lowest.x) lowest.x = x;
|
||||||
auto y = yOpt.value();
|
if (y < lowest.y) lowest.y = y;
|
||||||
auto z = zOpt.value();
|
|
||||||
if (x < lowest.x) lowest.x = x;
|
|
||||||
if (y < lowest.y) lowest.y = y;
|
|
||||||
if (z < lowest.z) lowest.z = z;
|
if (z < lowest.z) lowest.z = z;
|
||||||
|
|
||||||
if (highest.x < x) highest.x = x;
|
if (highest.x < x) highest.x = x;
|
||||||
@@ -119,19 +87,13 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
|||||||
for (auto& transformation : transformations | std::views::values) {
|
for (auto& transformation : transformations | std::views::values) {
|
||||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||||
if (split.size() < 12) {
|
if (split.size() < 12) {
|
||||||
|
LOG("Not enough in the split?");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto xOpt = GeneralUtils::TryParse<float>(split[9]);
|
auto x = GeneralUtils::TryParse<float>(split[9]).value() - newRootPos.x + curPosition.x;
|
||||||
auto yOpt = GeneralUtils::TryParse<float>(split[10]);
|
auto y = GeneralUtils::TryParse<float>(split[10]).value() - newRootPos.y + curPosition.y;
|
||||||
auto zOpt = GeneralUtils::TryParse<float>(split[11]);
|
auto z = GeneralUtils::TryParse<float>(split[11]).value() - newRootPos.z + curPosition.z;
|
||||||
|
|
||||||
if (!xOpt.has_value() || !yOpt.has_value() || !zOpt.has_value()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto x = xOpt.value() - newRootPos.x + curPosition.x;
|
|
||||||
auto y = yOpt.value() - newRootPos.y + curPosition.y;
|
|
||||||
auto z = zOpt.value() - newRootPos.z + curPosition.z;
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
for (int i = 0; i < 9; i++) {
|
for (int i = 0; i < 9; i++) {
|
||||||
stream << split[i];
|
stream << split[i];
|
||||||
@@ -166,345 +128,3 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
|||||||
toReturn.center = newRootPos;
|
toReturn.center = newRootPos;
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deep-clone an XMLElement (attributes, text, and child elements) into a target document
|
|
||||||
// with maximum depth protection to prevent infinite loops
|
|
||||||
static tinyxml2::XMLElement* CloneElementDeep(const tinyxml2::XMLElement* src, tinyxml2::XMLDocument& dstDoc, int maxDepth = 100) {
|
|
||||||
if (!src || maxDepth <= 0) return nullptr;
|
|
||||||
auto* dst = dstDoc.NewElement(src->Name());
|
|
||||||
|
|
||||||
// copy attributes
|
|
||||||
for (const tinyxml2::XMLAttribute* attr = src->FirstAttribute(); attr; attr = attr->Next()) {
|
|
||||||
dst->SetAttribute(attr->Name(), attr->Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy children (elements and text)
|
|
||||||
for (const tinyxml2::XMLNode* child = src->FirstChild(); child; child = child->NextSibling()) {
|
|
||||||
if (const tinyxml2::XMLElement* childElem = child->ToElement()) {
|
|
||||||
// Recursively clone child elements with decremented depth
|
|
||||||
auto* clonedChild = CloneElementDeep(childElem, dstDoc, maxDepth - 1);
|
|
||||||
if (clonedChild) dst->InsertEndChild(clonedChild);
|
|
||||||
} else if (const tinyxml2::XMLText* txt = child->ToText()) {
|
|
||||||
auto* n = dstDoc.NewText(txt->Value());
|
|
||||||
dst->InsertEndChild(n);
|
|
||||||
} else if (const tinyxml2::XMLComment* c = child->ToComment()) {
|
|
||||||
auto* n = dstDoc.NewComment(c->Value());
|
|
||||||
dst->InsertEndChild(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Lxfml::Result> Lxfml::Split(const std::string_view data, const NiPoint3& curPosition) {
|
|
||||||
std::vector<Result> results;
|
|
||||||
|
|
||||||
// Handle empty or invalid input
|
|
||||||
if (data.empty()) {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent processing extremely large inputs that could cause hangs
|
|
||||||
if (data.size() > 10000000) { // 10MB limit
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLDocument doc;
|
|
||||||
// Use length-based parsing to avoid expensive string copy
|
|
||||||
const auto err = doc.Parse(data.data(), data.size());
|
|
||||||
if (err != tinyxml2::XML_SUCCESS) {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* lxfml = doc.FirstChildElement("LXFML");
|
|
||||||
if (!lxfml) {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build maps: partRef -> Part element, partRef -> Brick element, boneRef -> partRef, brickRef -> Brick element
|
|
||||||
std::unordered_map<std::string, tinyxml2::XMLElement*> partRefToPart;
|
|
||||||
std::unordered_map<std::string, tinyxml2::XMLElement*> partRefToBrick;
|
|
||||||
std::unordered_map<std::string, std::string> boneRefToPartRef;
|
|
||||||
std::unordered_map<std::string, tinyxml2::XMLElement*> brickByRef;
|
|
||||||
|
|
||||||
auto* bricksParent = lxfml->FirstChildElement("Bricks");
|
|
||||||
if (bricksParent) {
|
|
||||||
for (auto* brick = bricksParent->FirstChildElement("Brick"); brick; brick = brick->NextSiblingElement("Brick")) {
|
|
||||||
const char* brickRef = brick->Attribute("refID");
|
|
||||||
if (brickRef) brickByRef.emplace(std::string(brickRef), brick);
|
|
||||||
for (auto* part = brick->FirstChildElement("Part"); part; part = part->NextSiblingElement("Part")) {
|
|
||||||
const char* partRef = part->Attribute("refID");
|
|
||||||
if (partRef) {
|
|
||||||
partRefToPart.emplace(std::string(partRef), part);
|
|
||||||
partRefToBrick.emplace(std::string(partRef), brick);
|
|
||||||
}
|
|
||||||
auto* bone = part->FirstChildElement("Bone");
|
|
||||||
if (bone) {
|
|
||||||
const char* boneRef = bone->Attribute("refID");
|
|
||||||
if (boneRef) boneRefToPartRef.emplace(std::string(boneRef), partRef ? std::string(partRef) : std::string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect RigidSystem elements
|
|
||||||
std::vector<tinyxml2::XMLElement*> rigidSystems;
|
|
||||||
auto* rigidSystemsParent = lxfml->FirstChildElement("RigidSystems");
|
|
||||||
if (rigidSystemsParent) {
|
|
||||||
for (auto* rs = rigidSystemsParent->FirstChildElement("RigidSystem"); rs; rs = rs->NextSiblingElement("RigidSystem")) {
|
|
||||||
rigidSystems.push_back(rs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect top-level groups (immediate children of GroupSystem)
|
|
||||||
std::vector<tinyxml2::XMLElement*> groupRoots;
|
|
||||||
auto* groupSystemsParent = lxfml->FirstChildElement("GroupSystems");
|
|
||||||
if (groupSystemsParent) {
|
|
||||||
for (auto* gs = groupSystemsParent->FirstChildElement("GroupSystem"); gs; gs = gs->NextSiblingElement("GroupSystem")) {
|
|
||||||
for (auto* group = gs->FirstChildElement("Group"); group; group = group->NextSiblingElement("Group")) {
|
|
||||||
groupRoots.push_back(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track used bricks and rigidsystems
|
|
||||||
std::unordered_set<std::string> usedBrickRefs;
|
|
||||||
std::unordered_set<tinyxml2::XMLElement*> usedRigidSystems;
|
|
||||||
|
|
||||||
// Track used groups to avoid processing them twice
|
|
||||||
std::unordered_set<tinyxml2::XMLElement*> usedGroups;
|
|
||||||
|
|
||||||
// Helper to create output document from sets of brick refs and rigidsystem pointers
|
|
||||||
auto makeOutput = [&](const std::unordered_set<std::string>& bricksToInclude, const std::vector<tinyxml2::XMLElement*>& rigidSystemsToInclude, const std::vector<tinyxml2::XMLElement*>& groupsToInclude = {}) {
|
|
||||||
tinyxml2::XMLDocument outDoc;
|
|
||||||
outDoc.Parse(g_base.c_str());
|
|
||||||
auto* outRoot = outDoc.FirstChildElement("LXFML");
|
|
||||||
auto* outBricks = outRoot->FirstChildElement("Bricks");
|
|
||||||
auto* outRigidSystems = outRoot->FirstChildElement("RigidSystems");
|
|
||||||
auto* outGroupSystems = outRoot->FirstChildElement("GroupSystems");
|
|
||||||
|
|
||||||
// clone and insert bricks
|
|
||||||
for (const auto& bref : bricksToInclude) {
|
|
||||||
auto it = brickByRef.find(bref);
|
|
||||||
if (it == brickByRef.end()) continue;
|
|
||||||
tinyxml2::XMLElement* cloned = CloneElementDeep(it->second, outDoc);
|
|
||||||
if (cloned) outBricks->InsertEndChild(cloned);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clone and insert rigidsystems
|
|
||||||
for (auto* rsPtr : rigidSystemsToInclude) {
|
|
||||||
tinyxml2::XMLElement* cloned = CloneElementDeep(rsPtr, outDoc);
|
|
||||||
if (cloned) outRigidSystems->InsertEndChild(cloned);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clone and insert group(s) if requested
|
|
||||||
if (outGroupSystems && !groupsToInclude.empty()) {
|
|
||||||
// clear default children
|
|
||||||
while (outGroupSystems->FirstChild()) outGroupSystems->DeleteChild(outGroupSystems->FirstChild());
|
|
||||||
// create a GroupSystem element and append requested groups
|
|
||||||
auto* newGS = outDoc.NewElement("GroupSystem");
|
|
||||||
for (auto* gptr : groupsToInclude) {
|
|
||||||
tinyxml2::XMLElement* clonedG = CloneElementDeep(gptr, outDoc);
|
|
||||||
if (clonedG) newGS->InsertEndChild(clonedG);
|
|
||||||
}
|
|
||||||
outGroupSystems->InsertEndChild(newGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print to string
|
|
||||||
tinyxml2::XMLPrinter printer;
|
|
||||||
outDoc.Print(&printer);
|
|
||||||
// Normalize position and compute center using existing helper
|
|
||||||
std::string xmlString = printer.CStr();
|
|
||||||
if (xmlString.size() > 5000000) { // 5MB limit for normalization
|
|
||||||
Result emptyResult;
|
|
||||||
emptyResult.lxfml = xmlString;
|
|
||||||
return emptyResult;
|
|
||||||
}
|
|
||||||
auto normalized = NormalizePosition(xmlString, curPosition);
|
|
||||||
return normalized;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 1) Process groups (each top-level Group becomes one output; nested groups are included)
|
|
||||||
for (auto* groupRoot : groupRoots) {
|
|
||||||
// Skip if this group was already processed as part of another group
|
|
||||||
if (usedGroups.find(groupRoot) != usedGroups.end()) continue;
|
|
||||||
|
|
||||||
// Helper to collect all partRefs in a group's subtree
|
|
||||||
std::function<void(const tinyxml2::XMLElement*, std::unordered_set<std::string>&)> collectParts = [&](const tinyxml2::XMLElement* g, std::unordered_set<std::string>& partRefs) {
|
|
||||||
if (!g) return;
|
|
||||||
const char* partAttr = g->Attribute("partRefs");
|
|
||||||
if (partAttr) {
|
|
||||||
for (auto& tok : GeneralUtils::SplitString(partAttr, ',')) partRefs.insert(tok);
|
|
||||||
}
|
|
||||||
for (auto* child = g->FirstChildElement("Group"); child; child = child->NextSiblingElement("Group")) collectParts(child, partRefs);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Collect all groups that need to be merged into this output
|
|
||||||
std::vector<tinyxml2::XMLElement*> groupsToInclude{ groupRoot };
|
|
||||||
usedGroups.insert(groupRoot);
|
|
||||||
|
|
||||||
// Build initial sets of bricks and boneRefs from the starting group
|
|
||||||
std::unordered_set<std::string> partRefs;
|
|
||||||
collectParts(groupRoot, partRefs);
|
|
||||||
|
|
||||||
std::unordered_set<std::string> bricksIncluded;
|
|
||||||
std::unordered_set<std::string> boneRefsIncluded;
|
|
||||||
for (const auto& pref : partRefs) {
|
|
||||||
auto pit = partRefToBrick.find(pref);
|
|
||||||
if (pit != partRefToBrick.end()) {
|
|
||||||
const char* bref = pit->second->Attribute("refID");
|
|
||||||
if (bref) bricksIncluded.insert(std::string(bref));
|
|
||||||
}
|
|
||||||
auto partIt = partRefToPart.find(pref);
|
|
||||||
if (partIt != partRefToPart.end()) {
|
|
||||||
auto* bone = partIt->second->FirstChildElement("Bone");
|
|
||||||
if (bone) {
|
|
||||||
const char* bref = bone->Attribute("refID");
|
|
||||||
if (bref) boneRefsIncluded.insert(std::string(bref));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iteratively include any RigidSystems that reference any boneRefsIncluded
|
|
||||||
// and check if those rigid systems' bricks span other groups
|
|
||||||
bool changed = true;
|
|
||||||
std::vector<tinyxml2::XMLElement*> rigidSystemsToInclude;
|
|
||||||
int maxIterations = 1000; // Safety limit to prevent infinite loops
|
|
||||||
int iteration = 0;
|
|
||||||
while (changed && iteration < maxIterations) {
|
|
||||||
changed = false;
|
|
||||||
iteration++;
|
|
||||||
|
|
||||||
// First, expand rigid systems based on current boneRefsIncluded
|
|
||||||
for (auto* rs : rigidSystems) {
|
|
||||||
if (usedRigidSystems.find(rs) != usedRigidSystems.end()) continue;
|
|
||||||
// parse boneRefs of this rigid system (from its <Rigid> children)
|
|
||||||
bool intersects = false;
|
|
||||||
std::vector<std::string> rsBoneRefs;
|
|
||||||
for (auto* rigid = rs->FirstChildElement("Rigid"); rigid; rigid = rigid->NextSiblingElement("Rigid")) {
|
|
||||||
const char* battr = rigid->Attribute("boneRefs");
|
|
||||||
if (!battr) continue;
|
|
||||||
for (auto& tok : GeneralUtils::SplitString(battr, ',')) {
|
|
||||||
rsBoneRefs.push_back(tok);
|
|
||||||
if (boneRefsIncluded.find(tok) != boneRefsIncluded.end()) intersects = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!intersects) continue;
|
|
||||||
// include this rigid system and all boneRefs it references
|
|
||||||
usedRigidSystems.insert(rs);
|
|
||||||
rigidSystemsToInclude.push_back(rs);
|
|
||||||
for (const auto& br : rsBoneRefs) {
|
|
||||||
boneRefsIncluded.insert(br);
|
|
||||||
auto bpIt = boneRefToPartRef.find(br);
|
|
||||||
if (bpIt != boneRefToPartRef.end()) {
|
|
||||||
auto partRef = bpIt->second;
|
|
||||||
auto pbIt = partRefToBrick.find(partRef);
|
|
||||||
if (pbIt != partRefToBrick.end()) {
|
|
||||||
const char* bref = pbIt->second->Attribute("refID");
|
|
||||||
if (bref && bricksIncluded.insert(std::string(bref)).second) changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second, check if the newly included bricks span any other groups
|
|
||||||
// If so, merge those groups into the current output
|
|
||||||
for (auto* otherGroup : groupRoots) {
|
|
||||||
if (usedGroups.find(otherGroup) != usedGroups.end()) continue;
|
|
||||||
|
|
||||||
// Collect partRefs from this other group
|
|
||||||
std::unordered_set<std::string> otherPartRefs;
|
|
||||||
collectParts(otherGroup, otherPartRefs);
|
|
||||||
|
|
||||||
// Check if any of these partRefs correspond to bricks we've already included
|
|
||||||
bool spansOtherGroup = false;
|
|
||||||
for (const auto& pref : otherPartRefs) {
|
|
||||||
auto pit = partRefToBrick.find(pref);
|
|
||||||
if (pit != partRefToBrick.end()) {
|
|
||||||
const char* bref = pit->second->Attribute("refID");
|
|
||||||
if (bref && bricksIncluded.find(std::string(bref)) != bricksIncluded.end()) {
|
|
||||||
spansOtherGroup = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spansOtherGroup) {
|
|
||||||
// Merge this group into the current output
|
|
||||||
usedGroups.insert(otherGroup);
|
|
||||||
groupsToInclude.push_back(otherGroup);
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
// Add all partRefs, boneRefs, and bricks from this group
|
|
||||||
for (const auto& pref : otherPartRefs) {
|
|
||||||
auto pit = partRefToBrick.find(pref);
|
|
||||||
if (pit != partRefToBrick.end()) {
|
|
||||||
const char* bref = pit->second->Attribute("refID");
|
|
||||||
if (bref) bricksIncluded.insert(std::string(bref));
|
|
||||||
}
|
|
||||||
auto partIt = partRefToPart.find(pref);
|
|
||||||
if (partIt != partRefToPart.end()) {
|
|
||||||
auto* bone = partIt->second->FirstChildElement("Bone");
|
|
||||||
if (bone) {
|
|
||||||
const char* bref = bone->Attribute("refID");
|
|
||||||
if (bref) boneRefsIncluded.insert(std::string(bref));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iteration >= maxIterations) {
|
|
||||||
// Iteration limit reached, stop processing to prevent infinite loops
|
|
||||||
// The file is likely malformed, so just skip further processing
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
// include bricks from bricksIncluded into used set
|
|
||||||
for (const auto& b : bricksIncluded) usedBrickRefs.insert(b);
|
|
||||||
|
|
||||||
// make output doc and push result (include all merged groups' XML)
|
|
||||||
auto normalized = makeOutput(bricksIncluded, rigidSystemsToInclude, groupsToInclude);
|
|
||||||
results.push_back(normalized);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) Process remaining RigidSystems (each becomes its own file)
|
|
||||||
for (auto* rs : rigidSystems) {
|
|
||||||
if (usedRigidSystems.find(rs) != usedRigidSystems.end()) continue;
|
|
||||||
std::unordered_set<std::string> bricksIncluded;
|
|
||||||
// collect boneRefs referenced by this rigid system
|
|
||||||
for (auto* rigid = rs->FirstChildElement("Rigid"); rigid; rigid = rigid->NextSiblingElement("Rigid")) {
|
|
||||||
const char* battr = rigid->Attribute("boneRefs");
|
|
||||||
if (!battr) continue;
|
|
||||||
for (auto& tok : GeneralUtils::SplitString(battr, ',')) {
|
|
||||||
auto bpIt = boneRefToPartRef.find(tok);
|
|
||||||
if (bpIt != boneRefToPartRef.end()) {
|
|
||||||
auto partRef = bpIt->second;
|
|
||||||
auto pbIt = partRefToBrick.find(partRef);
|
|
||||||
if (pbIt != partRefToBrick.end()) {
|
|
||||||
const char* bref = pbIt->second->Attribute("refID");
|
|
||||||
if (bref) bricksIncluded.insert(std::string(bref));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// mark used
|
|
||||||
for (const auto& b : bricksIncluded) usedBrickRefs.insert(b);
|
|
||||||
usedRigidSystems.insert(rs);
|
|
||||||
|
|
||||||
std::vector<tinyxml2::XMLElement*> rsVec{ rs };
|
|
||||||
auto normalized = makeOutput(bricksIncluded, rsVec);
|
|
||||||
results.push_back(normalized);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3) Any remaining bricks not included become their own files
|
|
||||||
for (const auto& [bref, brickPtr] : brickByRef) {
|
|
||||||
if (usedBrickRefs.find(bref) != usedBrickRefs.end()) continue;
|
|
||||||
std::unordered_set<std::string> bricksIncluded{ bref };
|
|
||||||
auto normalized = makeOutput(bricksIncluded, {});
|
|
||||||
results.push_back(normalized);
|
|
||||||
usedBrickRefs.insert(bref);
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
|
|
||||||
@@ -19,7 +18,6 @@ namespace Lxfml {
|
|||||||
// Normalizes a LXFML model to be positioned relative to its local 0, 0, 0 rather than a game worlds 0, 0, 0.
|
// Normalizes a LXFML model to be positioned relative to its local 0, 0, 0 rather than a game worlds 0, 0, 0.
|
||||||
// Returns a struct of its new center and the updated LXFML containing these edits.
|
// Returns a struct of its new center and the updated LXFML containing these edits.
|
||||||
[[nodiscard]] Result NormalizePosition(const std::string_view data, const NiPoint3& curPosition = NiPoint3Constant::ZERO);
|
[[nodiscard]] Result NormalizePosition(const std::string_view data, const NiPoint3& curPosition = NiPoint3Constant::ZERO);
|
||||||
[[nodiscard]] std::vector<Result> Split(const std::string_view data, const NiPoint3& curPosition = NiPoint3Constant::ZERO);
|
|
||||||
|
|
||||||
// these are only for the migrations due to a bug in one of the implementations.
|
// these are only for the migrations due to a bug in one of the implementations.
|
||||||
[[nodiscard]] Result NormalizePositionOnlyFirstPart(const std::string_view data);
|
[[nodiscard]] Result NormalizePositionOnlyFirstPart(const std::string_view data);
|
||||||
|
|||||||
@@ -53,21 +53,16 @@ Lxfml::Result Lxfml::NormalizePositionOnlyFirstPart(const std::string_view data)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
||||||
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
||||||
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
||||||
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
if (x < lowest.x) lowest.x = x;
|
||||||
if (x < lowest.x) lowest.x = x;
|
if (y < lowest.y) lowest.y = y;
|
||||||
if (y < lowest.y) lowest.y = y;
|
if (z < lowest.z) lowest.z = z;
|
||||||
if (z < lowest.z) lowest.z = z;
|
|
||||||
|
|
||||||
if (highest.x < x) highest.x = x;
|
if (highest.x < x) highest.x = x;
|
||||||
if (highest.y < y) highest.y = y;
|
if (highest.y < y) highest.y = y;
|
||||||
if (highest.z < z) highest.z = z;
|
if (highest.z < z) highest.z = z;
|
||||||
} catch (std::exception& e) {
|
|
||||||
LOG("Failed to parse a split value of either (%s), (%s), or (%s).", split[9].c_str(), split[10].c_str(), split[11].c_str());
|
|
||||||
return toReturn; // Early return since we failed to parse this lxfml.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto delta = (highest - lowest) / 2.0f;
|
auto delta = (highest - lowest) / 2.0f;
|
||||||
|
|||||||
@@ -1,77 +1,105 @@
|
|||||||
#include "Metrics.h"
|
#include "Metrics.hpp"
|
||||||
|
|
||||||
#include "StringifiedEnum.h"
|
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
namespace {
|
std::unordered_map<MetricVariable, Metric*> Metrics::m_Metrics = {};
|
||||||
std::unordered_map<MetricVariable, Metric> g_Metrics = {};
|
std::vector<MetricVariable> Metrics::m_Variables = {
|
||||||
std::vector<MetricVariable> g_Variables = {
|
MetricVariable::GameLoop,
|
||||||
MetricVariable::GameLoop,
|
MetricVariable::PacketHandling,
|
||||||
MetricVariable::PacketHandling,
|
MetricVariable::UpdateEntities,
|
||||||
MetricVariable::UpdateEntities,
|
MetricVariable::UpdateSpawners,
|
||||||
MetricVariable::UpdateSpawners,
|
MetricVariable::Physics,
|
||||||
MetricVariable::Physics,
|
MetricVariable::UpdateReplica,
|
||||||
MetricVariable::UpdateReplica,
|
MetricVariable::Ghosting,
|
||||||
MetricVariable::Ghosting,
|
MetricVariable::CPUTime,
|
||||||
MetricVariable::CPUTime,
|
MetricVariable::Sleep,
|
||||||
MetricVariable::Sleep,
|
MetricVariable::Frame,
|
||||||
MetricVariable::Frame,
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void Metrics::AddMeasurement(MetricVariable variable, int64_t value) {
|
void Metrics::AddMeasurement(MetricVariable variable, int64_t value) {
|
||||||
auto& metric = g_Metrics[variable];
|
const auto& iter = m_Metrics.find(variable);
|
||||||
|
|
||||||
|
Metric* metric;
|
||||||
|
|
||||||
|
if (iter == m_Metrics.end()) {
|
||||||
|
metric = new Metric();
|
||||||
|
|
||||||
|
m_Metrics[variable] = metric;
|
||||||
|
} else {
|
||||||
|
metric = iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
AddMeasurement(metric, value);
|
AddMeasurement(metric, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metrics::AddMeasurement(Metric& metric, int64_t value) {
|
void Metrics::AddMeasurement(Metric* metric, int64_t value) {
|
||||||
const auto index = metric.measurementIndex;
|
const auto index = metric->measurementIndex;
|
||||||
|
|
||||||
metric.measurements[index] = value;
|
metric->measurements[index] = value;
|
||||||
|
|
||||||
if (metric.max == -1 || value > metric.max) {
|
if (metric->max == -1 || value > metric->max) {
|
||||||
metric.max = value;
|
metric->max = value;
|
||||||
} else if (metric.min == -1 || metric.min > value) {
|
} else if (metric->min == -1 || metric->min > value) {
|
||||||
metric.min = value;
|
metric->min = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metric.measurementSize < MAX_MEASURMENT_POINTS) {
|
if (metric->measurementSize < MAX_MEASURMENT_POINTS) {
|
||||||
metric.measurementSize++;
|
metric->measurementSize++;
|
||||||
}
|
}
|
||||||
|
|
||||||
metric.measurementIndex = (index + 1) % MAX_MEASURMENT_POINTS;
|
metric->measurementIndex = (index + 1) % MAX_MEASURMENT_POINTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Metric& Metrics::GetMetric(MetricVariable variable) {
|
const Metric* Metrics::GetMetric(MetricVariable variable) {
|
||||||
auto& metric = g_Metrics[variable];
|
const auto& iter = m_Metrics.find(variable);
|
||||||
|
|
||||||
|
if (iter == m_Metrics.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Metric* metric = iter->second;
|
||||||
|
|
||||||
int64_t average = 0;
|
int64_t average = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < metric.measurementSize; i++) {
|
for (size_t i = 0; i < metric->measurementSize; i++) {
|
||||||
average += metric.measurements[i];
|
average += metric->measurements[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
average /= metric.measurementSize;
|
average /= metric->measurementSize;
|
||||||
|
|
||||||
metric.average = average;
|
metric->average = average;
|
||||||
|
|
||||||
return metric;
|
return metric;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metrics::StartMeasurement(MetricVariable variable) {
|
void Metrics::StartMeasurement(MetricVariable variable) {
|
||||||
auto& metric = g_Metrics[variable];
|
const auto& iter = m_Metrics.find(variable);
|
||||||
|
|
||||||
metric.activeMeasurement = std::chrono::high_resolution_clock::now();
|
Metric* metric;
|
||||||
|
|
||||||
|
if (iter == m_Metrics.end()) {
|
||||||
|
metric = new Metric();
|
||||||
|
|
||||||
|
m_Metrics[variable] = metric;
|
||||||
|
} else {
|
||||||
|
metric = iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
metric->activeMeasurement = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metrics::EndMeasurement(MetricVariable variable) {
|
void Metrics::EndMeasurement(MetricVariable variable) {
|
||||||
const auto end = std::chrono::high_resolution_clock::now();
|
const auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
auto& metric = g_Metrics[variable];
|
const auto& iter = m_Metrics.find(variable);
|
||||||
|
|
||||||
const auto elapsed = end - metric.activeMeasurement;
|
if (iter == m_Metrics.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Metric* metric = iter->second;
|
||||||
|
|
||||||
|
const auto elapsed = end - metric->activeMeasurement;
|
||||||
|
|
||||||
const auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count();
|
const auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count();
|
||||||
|
|
||||||
@@ -82,12 +110,44 @@ float Metrics::ToMiliseconds(int64_t nanoseconds) {
|
|||||||
return static_cast<float>(nanoseconds) / 1e6;
|
return static_cast<float>(nanoseconds) / 1e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string_view Metrics::MetricVariableToString(MetricVariable variable) {
|
std::string Metrics::MetricVariableToString(MetricVariable variable) {
|
||||||
return StringifiedEnum::ToString(variable);
|
switch (variable) {
|
||||||
|
case MetricVariable::GameLoop:
|
||||||
|
return "GameLoop";
|
||||||
|
case MetricVariable::PacketHandling:
|
||||||
|
return "PacketHandling";
|
||||||
|
case MetricVariable::UpdateEntities:
|
||||||
|
return "UpdateEntities";
|
||||||
|
case MetricVariable::UpdateSpawners:
|
||||||
|
return "UpdateSpawners";
|
||||||
|
case MetricVariable::Physics:
|
||||||
|
return "Physics";
|
||||||
|
case MetricVariable::UpdateReplica:
|
||||||
|
return "UpdateReplica";
|
||||||
|
case MetricVariable::Sleep:
|
||||||
|
return "Sleep";
|
||||||
|
case MetricVariable::CPUTime:
|
||||||
|
return "CPUTime";
|
||||||
|
case MetricVariable::Frame:
|
||||||
|
return "Frame";
|
||||||
|
case MetricVariable::Ghosting:
|
||||||
|
return "Ghosting";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "Invalid";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<MetricVariable>& Metrics::GetAllMetrics() {
|
const std::vector<MetricVariable>& Metrics::GetAllMetrics() {
|
||||||
return g_Variables;
|
return m_Variables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Metrics::Clear() {
|
||||||
|
for (const auto& pair : m_Metrics) {
|
||||||
|
delete pair.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Metrics.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RSS Memory utilities
|
/* RSS Memory utilities
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <string_view>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#define MAX_MEASURMENT_POINTS 1024
|
|
||||||
|
|
||||||
enum class MetricVariable : int32_t {
|
|
||||||
GameLoop,
|
|
||||||
PacketHandling,
|
|
||||||
UpdateEntities,
|
|
||||||
UpdateSpawners,
|
|
||||||
Physics,
|
|
||||||
UpdateReplica,
|
|
||||||
Ghosting,
|
|
||||||
CPUTime,
|
|
||||||
Sleep,
|
|
||||||
Frame,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Metric {
|
|
||||||
int64_t measurements[MAX_MEASURMENT_POINTS] = {};
|
|
||||||
size_t measurementIndex = 0;
|
|
||||||
size_t measurementSize = 0;
|
|
||||||
int64_t max = -1;
|
|
||||||
int64_t min = -1;
|
|
||||||
int64_t average = 0;
|
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> activeMeasurement;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Metrics {
|
|
||||||
void AddMeasurement(MetricVariable variable, int64_t value);
|
|
||||||
void AddMeasurement(Metric& metric, int64_t value);
|
|
||||||
const Metric& GetMetric(MetricVariable variable);
|
|
||||||
void StartMeasurement(MetricVariable variable);
|
|
||||||
void EndMeasurement(MetricVariable variable);
|
|
||||||
float ToMiliseconds(int64_t nanoseconds);
|
|
||||||
const std::string_view MetricVariableToString(MetricVariable variable);
|
|
||||||
const std::vector<MetricVariable>& GetAllMetrics();
|
|
||||||
|
|
||||||
size_t GetPeakRSS();
|
|
||||||
size_t GetCurrentRSS();
|
|
||||||
size_t GetProcessID();
|
|
||||||
};
|
|
||||||
61
dCommon/Metrics.hpp
Normal file
61
dCommon/Metrics.hpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dCommonVars.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#define MAX_MEASURMENT_POINTS 1024
|
||||||
|
|
||||||
|
enum class MetricVariable : int32_t
|
||||||
|
{
|
||||||
|
GameLoop,
|
||||||
|
PacketHandling,
|
||||||
|
UpdateEntities,
|
||||||
|
UpdateSpawners,
|
||||||
|
Physics,
|
||||||
|
UpdateReplica,
|
||||||
|
Ghosting,
|
||||||
|
CPUTime,
|
||||||
|
Sleep,
|
||||||
|
Frame,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Metric
|
||||||
|
{
|
||||||
|
int64_t measurements[MAX_MEASURMENT_POINTS] = {};
|
||||||
|
size_t measurementIndex = 0;
|
||||||
|
size_t measurementSize = 0;
|
||||||
|
int64_t max = -1;
|
||||||
|
int64_t min = -1;
|
||||||
|
int64_t average = 0;
|
||||||
|
std::chrono::time_point<std::chrono::high_resolution_clock> activeMeasurement;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Metrics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~Metrics();
|
||||||
|
|
||||||
|
static void AddMeasurement(MetricVariable variable, int64_t value);
|
||||||
|
static void AddMeasurement(Metric* metric, int64_t value);
|
||||||
|
static const Metric* GetMetric(MetricVariable variable);
|
||||||
|
static void StartMeasurement(MetricVariable variable);
|
||||||
|
static void EndMeasurement(MetricVariable variable);
|
||||||
|
static float ToMiliseconds(int64_t nanoseconds);
|
||||||
|
static std::string MetricVariableToString(MetricVariable variable);
|
||||||
|
static const std::vector<MetricVariable>& GetAllMetrics();
|
||||||
|
|
||||||
|
static size_t GetPeakRSS();
|
||||||
|
static size_t GetCurrentRSS();
|
||||||
|
static size_t GetProcessID();
|
||||||
|
|
||||||
|
static void Clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Metrics();
|
||||||
|
|
||||||
|
static std::unordered_map<MetricVariable, Metric*> m_Metrics;
|
||||||
|
static std::vector<MetricVariable> m_Variables;
|
||||||
|
};
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#ifndef NICOLOR_H
|
|
||||||
#define NICOLOR_H
|
|
||||||
|
|
||||||
struct NiColor {
|
|
||||||
float m_Red;
|
|
||||||
float m_Green;
|
|
||||||
float m_Blue;
|
|
||||||
|
|
||||||
constexpr NiColor(float red, float green, float blue) : m_Red(red), m_Green(green), m_Blue(blue) {}
|
|
||||||
constexpr NiColor() : NiColor(0.0f, 0.0f, 0.0f) {}
|
|
||||||
|
|
||||||
/* reduce RGB files to grayscale, with or without alpha
|
|
||||||
* using the equation given in Poynton's ColorFAQ at
|
|
||||||
* <http://www.inforamp.net/~poynton/> // dead link
|
|
||||||
* Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
|
|
||||||
*
|
|
||||||
* Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
|
|
||||||
*
|
|
||||||
* We approximate this with
|
|
||||||
*
|
|
||||||
* Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
|
|
||||||
*
|
|
||||||
* which can be expressed with integers as
|
|
||||||
*
|
|
||||||
* Y = (6969 * R + 23434 * G + 2365 * B)/32768
|
|
||||||
*
|
|
||||||
* The calculation is to be done in a linear colorspace.
|
|
||||||
*
|
|
||||||
* Other integer coefficents can be used via png_set_rgb_to_gray().
|
|
||||||
*/
|
|
||||||
float ToXYZ() const { return (m_Red * 0.212671f) + (m_Green * 0.71516f) + (m_Blue * 0.072169f); };
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // NICOLOR_H
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
#ifndef __NIPOINT3_H__
|
#ifndef __NIPOINT3_H__
|
||||||
#define __NIPOINT3_H__
|
#define __NIPOINT3_H__
|
||||||
#ifndef GLM_ENABLE_EXPERIMENTAL
|
|
||||||
# define GLM_ENABLE_EXPERIMENTAL
|
|
||||||
#endif
|
|
||||||
/*!
|
/*!
|
||||||
\file NiPoint3.hpp
|
\file NiPoint3.hpp
|
||||||
\brief Defines a point in space in XYZ coordinates
|
\brief Defines a point in space in XYZ coordinates
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#ifndef NIQUATERNION_H
|
#ifndef NIQUATERNION_H
|
||||||
#define NIQUATERNION_H
|
#define NIQUATERNION_H
|
||||||
#ifndef GLM_ENABLE_EXPERIMENTAL
|
|
||||||
# define GLM_ENABLE_EXPERIMENTAL
|
|
||||||
#endif
|
|
||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
|
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ Sd0::Sd0(std::istream& buffer) {
|
|||||||
uint32_t bufferSize = buffer.tellg();
|
uint32_t bufferSize = buffer.tellg();
|
||||||
buffer.seekg(0, std::ios::beg);
|
buffer.seekg(0, std::ios::beg);
|
||||||
WriteSize(firstChunk, bufferSize);
|
WriteSize(firstChunk, bufferSize);
|
||||||
// its expected that if we got here, we got an old sd0 buffer where we ignored the sd0 part
|
|
||||||
// that means this can be at most the compressed chunk limit.
|
|
||||||
if (bufferSize > MAX_UNCOMPRESSED_CHUNK_SIZE) {
|
|
||||||
LOG("Possible bad chunk size of %i specified, rejecting.", bufferSize);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
firstChunk.resize(firstChunk.size() + bufferSize);
|
firstChunk.resize(firstChunk.size() + bufferSize);
|
||||||
auto* dataStart = reinterpret_cast<char*>(firstChunk.data() + GetDataOffset(true));
|
auto* dataStart = reinterpret_cast<char*>(firstChunk.data() + GetDataOffset(true));
|
||||||
if (!buffer.read(dataStart, bufferSize)) {
|
if (!buffer.read(dataStart, bufferSize)) {
|
||||||
@@ -77,12 +71,6 @@ Sd0::Sd0(std::istream& buffer) {
|
|||||||
|
|
||||||
WriteSize(chunk, chunkSize);
|
WriteSize(chunk, chunkSize);
|
||||||
|
|
||||||
// Assuming a good buffer that is large enough to take up 2 zlib buffers
|
|
||||||
// any buffer should be compressed enough to take up less size than its uncompressed counterpart
|
|
||||||
if (chunkSize > MAX_UNCOMPRESSED_CHUNK_SIZE) {
|
|
||||||
LOG("Possible bad chunk size of %i specified, rejecting.", chunkSize);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
chunk.resize(chunkSize + dataOffset);
|
chunk.resize(chunkSize + dataOffset);
|
||||||
auto* dataStart = reinterpret_cast<char*>(chunk.data() + dataOffset);
|
auto* dataStart = reinterpret_cast<char*>(chunk.data() + dataOffset);
|
||||||
if (!buffer.read(dataStart, chunkSize)) {
|
if (!buffer.read(dataStart, chunkSize)) {
|
||||||
@@ -107,11 +95,6 @@ void Sd0::FromData(const uint8_t* data, size_t bufferSize) {
|
|||||||
startOffset, numToCopy,
|
startOffset, numToCopy,
|
||||||
compressedChunk.data(), compressedChunk.size());
|
compressedChunk.data(), compressedChunk.size());
|
||||||
|
|
||||||
if (compressedSize == -1) {
|
|
||||||
LOG("Failed to compress chunk, aborting");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& chunk = m_Chunks.emplace_back();
|
auto& chunk = m_Chunks.emplace_back();
|
||||||
bool firstBuffer = m_Chunks.size() == 1;
|
bool firstBuffer = m_Chunks.size() == 1;
|
||||||
auto dataOffset = GetDataOffset(firstBuffer);
|
auto dataOffset = GetDataOffset(firstBuffer);
|
||||||
@@ -136,12 +119,6 @@ std::string Sd0::GetAsStringUncompressed() const {
|
|||||||
auto dataOffset = GetDataOffset(first);
|
auto dataOffset = GetDataOffset(first);
|
||||||
first = false;
|
first = false;
|
||||||
const auto chunkSize = chunk.size();
|
const auto chunkSize = chunk.size();
|
||||||
if (chunkSize <= static_cast<size_t>(dataOffset)) {
|
|
||||||
LOG("Bad chunkSize for data, aborting");
|
|
||||||
toReturn = "";
|
|
||||||
totalSize = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto oldSize = toReturn.size();
|
auto oldSize = toReturn.size();
|
||||||
toReturn.resize(oldSize + MAX_UNCOMPRESSED_CHUNK_SIZE);
|
toReturn.resize(oldSize + MAX_UNCOMPRESSED_CHUNK_SIZE);
|
||||||
@@ -151,13 +128,6 @@ std::string Sd0::GetAsStringUncompressed() const {
|
|||||||
reinterpret_cast<uint8_t*>(toReturn.data()) + oldSize, MAX_UNCOMPRESSED_CHUNK_SIZE,
|
reinterpret_cast<uint8_t*>(toReturn.data()) + oldSize, MAX_UNCOMPRESSED_CHUNK_SIZE,
|
||||||
error);
|
error);
|
||||||
|
|
||||||
if (uncompressedSize == -1) {
|
|
||||||
LOG("Failed to decompress chunk, aborting");
|
|
||||||
toReturn = "";
|
|
||||||
totalSize = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalSize += uncompressedSize;
|
totalSize += uncompressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
namespace ZCompression {
|
namespace ZCompression {
|
||||||
uint32_t GetMaxCompressedLength(uint32_t nLenSrc) {
|
int32_t GetMaxCompressedLength(int32_t nLenSrc) {
|
||||||
uint32_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
|
int32_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
|
||||||
return (nLenSrc + 6 + (n16kBlocks * 5));
|
return (nLenSrc + 6 + (n16kBlocks * 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Compress(const uint8_t* abSrc, uint32_t nLenSrc, uint8_t* abDst, uint32_t nLenDst) {
|
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst) {
|
||||||
z_stream zInfo = { 0 };
|
z_stream zInfo = { 0 };
|
||||||
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
||||||
zInfo.total_out = zInfo.avail_out = nLenDst;
|
zInfo.total_out = zInfo.avail_out = nLenDst;
|
||||||
@@ -27,7 +27,7 @@ namespace ZCompression {
|
|||||||
return(nRet);
|
return(nRet);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Decompress(const uint8_t* abSrc, uint32_t nLenSrc, uint8_t* abDst, uint32_t nLenDst, int32_t& nErr) {
|
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr) {
|
||||||
// Get the size of the decompressed data
|
// Get the size of the decompressed data
|
||||||
z_stream zInfo = { 0 };
|
z_stream zInfo = { 0 };
|
||||||
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
zInfo.total_in = zInfo.avail_in = nLenSrc;
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace ZCompression {
|
namespace ZCompression {
|
||||||
uint32_t GetMaxCompressedLength(uint32_t nLenSrc);
|
int32_t GetMaxCompressedLength(int32_t nLenSrc);
|
||||||
|
|
||||||
int32_t Compress(const uint8_t* abSrc, uint32_t nLenSrc, uint8_t* abDst, uint32_t nLenDst);
|
int32_t Compress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst);
|
||||||
|
|
||||||
int32_t Decompress(const uint8_t* abSrc, uint32_t nLenSrc, uint8_t* abDst, uint32_t nLenDst, int32_t& nErr);
|
int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
constexpr uint32_t CRC32_INIT = 0xFFFFFFFF;
|
constexpr uint32_t CRC32_INIT = 0xFFFFFFFF;
|
||||||
constexpr auto NULL_TERMINATOR = std::string_view{ "\0\0\0", 4 };
|
constexpr auto NULL_TERMINATOR = std::string_view{"\0\0\0", 4};
|
||||||
|
|
||||||
AssetManager::AssetManager(const std::filesystem::path& path) {
|
AssetManager::AssetManager(const std::filesystem::path& path) {
|
||||||
if (!std::filesystem::is_directory(path)) {
|
if (!std::filesystem::is_directory(path)) {
|
||||||
@@ -25,7 +25,7 @@ AssetManager::AssetManager(const std::filesystem::path& path) {
|
|||||||
if (!std::filesystem::exists(m_Path / ".." / "versions")) {
|
if (!std::filesystem::exists(m_Path / ".." / "versions")) {
|
||||||
throw std::runtime_error("No \"versions\" directory found in the parent directories of \"res\" - packed asset bundle cannot be loaded.");
|
throw std::runtime_error("No \"versions\" directory found in the parent directories of \"res\" - packed asset bundle cannot be loaded.");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_AssetBundleType = eAssetBundleType::Packed;
|
m_AssetBundleType = eAssetBundleType::Packed;
|
||||||
|
|
||||||
m_RootPath = (m_Path / "..");
|
m_RootPath = (m_Path / "..");
|
||||||
@@ -34,7 +34,7 @@ AssetManager::AssetManager(const std::filesystem::path& path) {
|
|||||||
if (!std::filesystem::exists(m_Path / ".." / ".." / "versions")) {
|
if (!std::filesystem::exists(m_Path / ".." / ".." / "versions")) {
|
||||||
throw std::runtime_error("No \"versions\" directory found in the parent directories of \"res\" - packed asset bundle cannot be loaded.");
|
throw std::runtime_error("No \"versions\" directory found in the parent directories of \"res\" - packed asset bundle cannot be loaded.");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_AssetBundleType = eAssetBundleType::Packed;
|
m_AssetBundleType = eAssetBundleType::Packed;
|
||||||
|
|
||||||
m_RootPath = (m_Path / ".." / "..");
|
m_RootPath = (m_Path / ".." / "..");
|
||||||
@@ -54,15 +54,15 @@ AssetManager::AssetManager(const std::filesystem::path& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (m_AssetBundleType) {
|
switch (m_AssetBundleType) {
|
||||||
case eAssetBundleType::Packed: {
|
case eAssetBundleType::Packed: {
|
||||||
this->LoadPackIndex();
|
this->LoadPackIndex();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eAssetBundleType::None:
|
case eAssetBundleType::None:
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case eAssetBundleType::Unpacked: {
|
case eAssetBundleType::Unpacked: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ bool AssetManager::HasFile(std::string fixedName) const {
|
|||||||
std::replace(fixedName.begin(), fixedName.end(), '\\', '/');
|
std::replace(fixedName.begin(), fixedName.end(), '\\', '/');
|
||||||
if (std::filesystem::exists(m_ResPath / fixedName)) return true;
|
if (std::filesystem::exists(m_ResPath / fixedName)) return true;
|
||||||
|
|
||||||
if (this->m_AssetBundleType == eAssetBundleType::Unpacked || !m_PackIndex) return false;
|
if (this->m_AssetBundleType == eAssetBundleType::Unpacked) return false;
|
||||||
|
|
||||||
std::replace(fixedName.begin(), fixedName.end(), '/', '\\');
|
std::replace(fixedName.begin(), fixedName.end(), '/', '\\');
|
||||||
if (fixedName.rfind("client\\res\\", 0) != 0) fixedName = "client\\res\\" + fixedName;
|
if (fixedName.rfind("client\\res\\", 0) != 0) fixedName = "client\\res\\" + fixedName;
|
||||||
@@ -145,12 +145,8 @@ bool AssetManager::GetFile(std::string fixedName, char** data, uint32_t* len) co
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto& pack = this->m_PackIndex->GetPacks().at(packIndex);
|
const auto& pack = this->m_PackIndex->GetPacks().at(packIndex);
|
||||||
bool success = false;
|
const bool success = pack.ReadFileFromPack(crc, data, len);
|
||||||
try {
|
|
||||||
success = pack.ReadFileFromPack(crc, data, len);
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
LOG("Failed to read file %s from pack file", fixedName.c_str());
|
|
||||||
}
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,9 +81,6 @@ public:
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
AssetStream GetFile(const char* name) const;
|
AssetStream GetFile(const char* name) const;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
AssetStream GetFile(const std::string& name) const { return GetFile(name.c_str()); };
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadPackIndex();
|
void LoadPackIndex();
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ bool Pack::HasFile(const uint32_t crc) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Pack::ReadFileFromPack(const uint32_t crc, char** data, uint32_t* len) const {
|
bool Pack::ReadFileFromPack(const uint32_t crc, char** data, uint32_t* len) const {
|
||||||
const auto pathStr = m_FilePath.string();
|
|
||||||
// Time for some wacky C file reading for speed reasons
|
// Time for some wacky C file reading for speed reasons
|
||||||
|
|
||||||
PackRecord pkRecord{};
|
PackRecord pkRecord{};
|
||||||
@@ -66,21 +65,16 @@ bool Pack::ReadFileFromPack(const uint32_t crc, char** data, uint32_t* len) cons
|
|||||||
bool isCompressed = (pkRecord.m_IsCompressed & 0xff) > 0;
|
bool isCompressed = (pkRecord.m_IsCompressed & 0xff) > 0;
|
||||||
auto inPackSize = isCompressed ? pkRecord.m_CompressedSize : pkRecord.m_UncompressedSize;
|
auto inPackSize = isCompressed ? pkRecord.m_CompressedSize : pkRecord.m_UncompressedSize;
|
||||||
|
|
||||||
FILE* file = nullptr;
|
FILE* file;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
fopen_s(&file, pathStr.c_str(), "rb");
|
fopen_s(&file, m_FilePath.string().c_str(), "rb");
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
// macOS has 64bit file IO by default
|
// macOS has 64bit file IO by default
|
||||||
file = fopen(pathStr.c_str(), "rb");
|
file = fopen(m_FilePath.string().c_str(), "rb");
|
||||||
#else
|
#else
|
||||||
file = fopen64(pathStr.c_str(), "rb");
|
file = fopen64(m_FilePath.string().c_str(), "rb");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!file) {
|
|
||||||
LOG("No file found for path %s", pathStr.c_str());
|
|
||||||
throw std::runtime_error("Could not find file " + pathStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(file, pos, SEEK_SET);
|
fseek(file, pos, SEEK_SET);
|
||||||
|
|
||||||
if (!isCompressed) {
|
if (!isCompressed) {
|
||||||
@@ -108,18 +102,14 @@ bool Pack::ReadFileFromPack(const uint32_t crc, char** data, uint32_t* len) cons
|
|||||||
int32_t readInData = fread(&size, sizeof(uint32_t), 1, file);
|
int32_t readInData = fread(&size, sizeof(uint32_t), 1, file);
|
||||||
pos += 4; // Move pointer position 4 to the right
|
pos += 4; // Move pointer position 4 to the right
|
||||||
|
|
||||||
std::unique_ptr<char[]> chunk(new char[size]);
|
char* chunk = static_cast<char*>(malloc(size));
|
||||||
int32_t readInData2 = fread(chunk.get(), sizeof(int8_t), size, file);
|
int32_t readInData2 = fread(chunk, sizeof(int8_t), size, file);
|
||||||
pos += size; // Move pointer position the amount of bytes read to the right
|
pos += size; // Move pointer position the amount of bytes read to the right
|
||||||
|
|
||||||
int32_t err;
|
int32_t err;
|
||||||
const auto countToRead = ZCompression::Decompress(reinterpret_cast<uint8_t*>(chunk.get()), size, reinterpret_cast<uint8_t*>(decompressedData + currentReadPos), Sd0::MAX_UNCOMPRESSED_CHUNK_SIZE, err);
|
currentReadPos += ZCompression::Decompress(reinterpret_cast<uint8_t*>(chunk), size, reinterpret_cast<uint8_t*>(decompressedData + currentReadPos), Sd0::MAX_UNCOMPRESSED_CHUNK_SIZE, err);
|
||||||
if (countToRead == -1) {
|
|
||||||
LOG("Error decompressing zlib data from file %s", pathStr.c_str());
|
|
||||||
throw std::runtime_error("Error decompressing zlib data from file " + pathStr);
|
|
||||||
}
|
|
||||||
currentReadPos += countToRead;
|
|
||||||
|
|
||||||
|
free(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = decompressedData;
|
*data = decompressedData;
|
||||||
|
|||||||
@@ -1,166 +0,0 @@
|
|||||||
#ifndef SCENE_COLOR_H
|
|
||||||
#define SCENE_COLOR_H
|
|
||||||
|
|
||||||
#include "NiColor.h"
|
|
||||||
#include <array>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace SceneColor {
|
|
||||||
// these are not random values, they are the actual template colors used by the game
|
|
||||||
static constexpr std::array<NiColor, 146> TEMPLATE_COLORS = {{
|
|
||||||
{ 0.5019608f, 0.5019608f, 0.5019608f },
|
|
||||||
{ 1.0f, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 1.0f, 0.0f },
|
|
||||||
{ 0.0f, 0.0f, 1.0f },
|
|
||||||
{ 1.0f, 1.0f, 0.0f },
|
|
||||||
{ 1.0f, 0.0f, 1.0f },
|
|
||||||
{ 0.0f, 1.0f, 1.0f },
|
|
||||||
{ 0.5019608f, 0.0f, 1.0f },
|
|
||||||
{ 1.0f, 0.5019608f, 0.0f },
|
|
||||||
{ 1.0f, 0.5019608f, 0.5019608f },
|
|
||||||
{ 0.5019608f, 0.2509804f, 0.0f },
|
|
||||||
{ 0.5019608f, 0.0f, 0.2509804f },
|
|
||||||
{ 0.0f, 0.5019608f, 0.2509804f },
|
|
||||||
{ 0.2509804f, 0.0f, 0.5019608f },
|
|
||||||
{ 0.8745098f, 0.0f, 0.2509804f },
|
|
||||||
{ 0.2509804f, 0.8745098f, 0.5019608f },
|
|
||||||
{ 1.0f, 0.7490196f, 0.0f },
|
|
||||||
{ 1.0f, 0.2509804f, 0.0627451f },
|
|
||||||
{ 0.2509804f, 0.0f, 0.8745098f },
|
|
||||||
{ 0.7490196f, 0.0627451f, 0.0627451f },
|
|
||||||
{ 0.0627451f, 0.7490196f, 0.0627451f },
|
|
||||||
{ 1.0f, 0.5019608f, 1.0f },
|
|
||||||
{ 0.9372549f, 0.8705882f, 0.8039216f },
|
|
||||||
{ 0.8039216f, 0.5843138f, 0.4588235f },
|
|
||||||
{ 0.9921569f, 0.8509804f, 0.7098039f },
|
|
||||||
{ 0.4705882f, 0.8588235f, 0.8862745f },
|
|
||||||
{ 0.5294118f, 0.6627451f, 0.4196078f },
|
|
||||||
{ 1.0f, 0.6431373f, 0.454902f },
|
|
||||||
{ 0.9803922f, 0.9058824f, 0.7098039f },
|
|
||||||
{ 0.6235294f, 0.5058824f, 0.4392157f },
|
|
||||||
{ 0.9921569f, 0.4862745f, 0.4313726f },
|
|
||||||
{ 0.0f, 0.0f, 0.0f },
|
|
||||||
{ 0.6745098f, 0.8980392f, 0.9333333f },
|
|
||||||
{ 0.1215686f, 0.4588235f, 0.9960784f },
|
|
||||||
{ 0.6352941f, 0.6352941f, 0.8156863f },
|
|
||||||
{ 0.4f, 0.6f, 0.8f },
|
|
||||||
{ 0.05098039f, 0.5960785f, 0.7294118f },
|
|
||||||
{ 0.4509804f, 0.4f, 0.7411765f },
|
|
||||||
{ 0.8705882f, 0.3647059f, 0.5137255f },
|
|
||||||
{ 0.7960784f, 0.254902f, 0.3294118f },
|
|
||||||
{ 0.7058824f, 0.4039216f, 0.3019608f },
|
|
||||||
{ 1.0f, 0.4980392f, 0.2862745f },
|
|
||||||
{ 0.9176471f, 0.4941176f, 0.3647059f },
|
|
||||||
{ 0.6901961f, 0.7176471f, 0.7764706f },
|
|
||||||
{ 1.0f, 1.0f, 0.6f },
|
|
||||||
{ 0.1098039f, 0.827451f, 0.6352941f },
|
|
||||||
{ 1.0f, 0.6666667f, 0.8f },
|
|
||||||
{ 0.8666667f, 0.2666667f, 0.572549f },
|
|
||||||
{ 0.1137255f, 0.6745098f, 0.8392157f },
|
|
||||||
{ 0.7372549f, 0.3647059f, 0.345098f },
|
|
||||||
{ 0.8666667f, 0.5803922f, 0.4588235f },
|
|
||||||
{ 0.6039216f, 0.8078431f, 0.9215686f },
|
|
||||||
{ 1.0f, 0.7372549f, 0.8509804f },
|
|
||||||
{ 0.9921569f, 0.8588235f, 0.427451f },
|
|
||||||
{ 0.1686275f, 0.4235294f, 0.7686275f },
|
|
||||||
{ 0.9372549f, 0.8039216f, 0.7215686f },
|
|
||||||
{ 0.4313726f, 0.3176471f, 0.3764706f },
|
|
||||||
{ 0.8078431f, 1.0f, 0.1137255f },
|
|
||||||
{ 0.427451f, 0.682353f, 0.5058824f },
|
|
||||||
{ 0.7647059f, 0.3921569f, 0.772549f },
|
|
||||||
{ 0.8f, 0.4f, 0.4f },
|
|
||||||
{ 0.9058824f, 0.7764706f, 0.5921569f },
|
|
||||||
{ 0.9882353f, 0.8509804f, 0.4588235f },
|
|
||||||
{ 0.6588235f, 0.8941177f, 0.627451f },
|
|
||||||
{ 0.5843138f, 0.5686275f, 0.5490196f },
|
|
||||||
{ 0.1098039f, 0.6745098f, 0.4705882f },
|
|
||||||
{ 0.06666667f, 0.3921569f, 0.7058824f },
|
|
||||||
{ 0.9411765f, 0.9098039f, 0.5686275f },
|
|
||||||
{ 1.0f, 0.1137255f, 0.8078431f },
|
|
||||||
{ 0.6980392f, 0.9254902f, 0.3647059f },
|
|
||||||
{ 0.3647059f, 0.4627451f, 0.7960784f },
|
|
||||||
{ 0.7921569f, 0.2156863f, 0.4039216f },
|
|
||||||
{ 0.2313726f, 0.6901961f, 0.5607843f },
|
|
||||||
{ 0.9882353f, 0.7058824f, 0.8352941f },
|
|
||||||
{ 1.0f, 0.9568627f, 0.3098039f },
|
|
||||||
{ 1.0f, 0.7411765f, 0.5333334f },
|
|
||||||
{ 0.9647059f, 0.3921569f, 0.6862745f },
|
|
||||||
{ 0.6666667f, 0.9411765f, 0.8196079f },
|
|
||||||
{ 0.8039216f, 0.2901961f, 0.2980392f },
|
|
||||||
{ 0.9294118f, 0.8196079f, 0.6117647f },
|
|
||||||
{ 0.5921569f, 0.6039216f, 0.6666667f },
|
|
||||||
{ 0.7843137f, 0.2196078f, 0.3529412f },
|
|
||||||
{ 0.9372549f, 0.5960785f, 0.6666667f },
|
|
||||||
{ 0.9921569f, 0.7372549f, 0.7058824f },
|
|
||||||
{ 0.1019608f, 0.282353f, 0.4627451f },
|
|
||||||
{ 0.1882353f, 0.7294118f, 0.5607843f },
|
|
||||||
{ 0.772549f, 0.2941177f, 0.5490196f },
|
|
||||||
{ 0.09803922f, 0.454902f, 0.8235294f },
|
|
||||||
{ 0.7294118f, 0.7215686f, 0.4235294f },
|
|
||||||
{ 1.0f, 0.4588235f, 0.2196078f },
|
|
||||||
{ 1.0f, 0.1686275f, 0.1686275f },
|
|
||||||
{ 0.972549f, 0.8352941f, 0.4078431f },
|
|
||||||
{ 0.9019608f, 0.6588235f, 0.8431373f },
|
|
||||||
{ 0.254902f, 0.2901961f, 0.2980392f },
|
|
||||||
{ 1.0f, 0.4313726f, 0.2901961f },
|
|
||||||
{ 0.1098039f, 0.6627451f, 0.7882353f },
|
|
||||||
{ 1.0f, 0.8117647f, 0.6705883f },
|
|
||||||
{ 0.772549f, 0.8156863f, 0.9019608f },
|
|
||||||
{ 0.9921569f, 0.8666667f, 0.9019608f },
|
|
||||||
{ 0.08235294f, 0.5019608f, 0.4705882f },
|
|
||||||
{ 0.9882353f, 0.454902f, 0.9921569f },
|
|
||||||
{ 0.9686275f, 0.5607843f, 0.654902f },
|
|
||||||
{ 0.5568628f, 0.2705882f, 0.5215687f },
|
|
||||||
{ 0.454902f, 0.2588235f, 0.7843137f },
|
|
||||||
{ 0.6156863f, 0.5058824f, 0.7294118f },
|
|
||||||
{ 1.0f, 0.2862745f, 0.4235294f },
|
|
||||||
{ 0.8392157f, 0.5411765f, 0.3490196f },
|
|
||||||
{ 0.4431373f, 0.2941177f, 0.1372549f },
|
|
||||||
{ 1.0f, 0.282353f, 0.8156863f },
|
|
||||||
{ 0.9333333f, 0.1254902f, 0.3019608f },
|
|
||||||
{ 1.0f, 0.3254902f, 0.2862745f },
|
|
||||||
{ 0.7529412f, 0.2666667f, 0.5607843f },
|
|
||||||
{ 0.1215686f, 0.8078431f, 0.7960784f },
|
|
||||||
{ 0.4705882f, 0.3176471f, 0.6627451f },
|
|
||||||
{ 1.0f, 0.6078432f, 0.6666667f },
|
|
||||||
{ 0.9882353f, 0.1568628f, 0.2784314f },
|
|
||||||
{ 0.4627451f, 1.0f, 0.4784314f },
|
|
||||||
{ 0.6235294f, 0.8862745f, 0.7490196f },
|
|
||||||
{ 0.6470588f, 0.4117647f, 0.3098039f },
|
|
||||||
{ 0.5411765f, 0.4745098f, 0.3647059f },
|
|
||||||
{ 0.2705882f, 0.8078431f, 0.6352941f },
|
|
||||||
{ 0.8039216f, 0.772549f, 0.7607843f },
|
|
||||||
{ 0.5019608f, 0.854902f, 0.9215686f },
|
|
||||||
{ 0.9254902f, 0.9176471f, 0.7450981f },
|
|
||||||
{ 1.0f, 0.8117647f, 0.282353f },
|
|
||||||
{ 0.9921569f, 0.3686275f, 0.3254902f },
|
|
||||||
{ 0.9803922f, 0.654902f, 0.4235294f },
|
|
||||||
{ 0.09411765f, 0.654902f, 0.7098039f },
|
|
||||||
{ 0.9215686f, 0.7803922f, 0.8745098f },
|
|
||||||
{ 0.9882353f, 0.5372549f, 0.6745098f },
|
|
||||||
{ 0.8588235f, 0.8431373f, 0.8235294f },
|
|
||||||
{ 0.8705882f, 0.6666667f, 0.5333334f },
|
|
||||||
{ 0.4666667f, 0.8666667f, 0.9058824f },
|
|
||||||
{ 1.0f, 1.0f, 0.4f },
|
|
||||||
{ 0.572549f, 0.4313726f, 0.682353f },
|
|
||||||
{ 0.1960784f, 0.2901961f, 0.6980392f },
|
|
||||||
{ 0.9686275f, 0.3254902f, 0.5803922f },
|
|
||||||
{ 1.0f, 0.627451f, 0.5372549f },
|
|
||||||
{ 0.5607843f, 0.3137255f, 0.6156863f },
|
|
||||||
{ 1.0f, 1.0f, 1.0f },
|
|
||||||
{ 0.6352941f, 0.6784314f, 0.8156863f },
|
|
||||||
{ 0.9882353f, 0.4235294f, 0.5215687f },
|
|
||||||
{ 0.8039216f, 0.6431373f, 0.8705882f },
|
|
||||||
{ 0.9882353f, 0.9098039f, 0.5137255f },
|
|
||||||
{ 0.772549f, 0.8901961f, 0.5176471f },
|
|
||||||
{ 1.0f, 0.682353f, 0.2588235f },
|
|
||||||
}};
|
|
||||||
|
|
||||||
static constexpr NiColor FALLBACK_COLOR{ 1.0f, 1.0f, 1.0f };
|
|
||||||
|
|
||||||
inline const NiColor& Get(uint8_t index) {
|
|
||||||
return (index < TEMPLATE_COLORS.size()) ? TEMPLATE_COLORS[index] : FALLBACK_COLOR;
|
|
||||||
}
|
|
||||||
} // namespace SceneColor
|
|
||||||
|
|
||||||
#endif // SCENE_COLOR_H
|
|
||||||
@@ -47,8 +47,6 @@ void dConfig::LoadConfig() {
|
|||||||
void dConfig::ReloadConfig() {
|
void dConfig::ReloadConfig() {
|
||||||
this->m_ConfigValues.clear();
|
this->m_ConfigValues.clear();
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
for (const auto& handler : m_ConfigHandlers) handler();
|
|
||||||
LogSettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& dConfig::GetValue(std::string key) {
|
const std::string& dConfig::GetValue(std::string key) {
|
||||||
@@ -60,18 +58,6 @@ const std::string& dConfig::GetValue(std::string key) {
|
|||||||
return this->m_ConfigValues[key];
|
return this->m_ConfigValues[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
void dConfig::AddConfigHandler(std::function<void()> handler) {
|
|
||||||
m_ConfigHandlers.push_back(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dConfig::LogSettings() const {
|
|
||||||
LOG("Configuration settings:");
|
|
||||||
for (const auto& [key, value] : m_ConfigValues) {
|
|
||||||
const auto& valueLog = key.find("password") != std::string::npos ? "<HIDDEN>" : value;
|
|
||||||
LOG(" %s = %s", key.c_str(), valueLog.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dConfig::ProcessLine(const std::string& line) {
|
void dConfig::ProcessLine(const std::string& line) {
|
||||||
auto splitLoc = line.find('=');
|
auto splitLoc = line.find('=');
|
||||||
auto key = line.substr(0, splitLoc);
|
auto key = line.substr(0, splitLoc);
|
||||||
@@ -84,7 +70,3 @@ void dConfig::ProcessLine(const std::string& line) {
|
|||||||
|
|
||||||
this->m_ConfigValues.insert(std::make_pair(key, value));
|
this->m_ConfigValues.insert(std::make_pair(key, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dConfig::GetValue(const std::string& key, const char* emptyValue) {
|
|
||||||
return GetValue(key, std::string(emptyValue));
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <functional>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "GeneralUtils.h"
|
|
||||||
|
|
||||||
class dConfig {
|
class dConfig {
|
||||||
public:
|
public:
|
||||||
dConfig(const std::string& filepath);
|
dConfig(const std::string& filepath);
|
||||||
@@ -24,14 +20,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
const std::string& GetValue(std::string key);
|
const std::string& GetValue(std::string key);
|
||||||
|
|
||||||
// Gets a value from the config and returns the parsed value, or the default value should parsing have failed.
|
|
||||||
template<typename T>
|
|
||||||
T GetValue(const std::string& key, const T emptyValue = T()) {
|
|
||||||
return GeneralUtils::TryParse<T>(GetValue(key)).value_or(emptyValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetValue(const std::string& key, const char* emptyValue);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the config from a file
|
* Loads the config from a file
|
||||||
*/
|
*/
|
||||||
@@ -41,21 +29,10 @@ public:
|
|||||||
* Reloads the config file to reset values
|
* Reloads the config file to reset values
|
||||||
*/
|
*/
|
||||||
void ReloadConfig();
|
void ReloadConfig();
|
||||||
|
|
||||||
// Adds a function to be called when the config is (re)loaded
|
|
||||||
void AddConfigHandler(std::function<void()> handler);
|
|
||||||
void LogSettings() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessLine(const std::string& line);
|
void ProcessLine(const std::string& line);
|
||||||
|
|
||||||
|
private:
|
||||||
std::map<std::string, std::string> m_ConfigValues;
|
std::map<std::string, std::string> m_ConfigValues;
|
||||||
std::vector<std::function<void()>> m_ConfigHandlers;
|
|
||||||
std::string m_ConfigFilePath;
|
std::string m_ConfigFilePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
|
||||||
inline std::string dConfig::GetValue(const std::string& key, const std::string emptyValue) {
|
|
||||||
const auto& value = GetValue(key);
|
|
||||||
return value.empty() ? emptyValue : value;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
namespace MessageType {
|
namespace MessageType {
|
||||||
enum class Master : uint32_t {
|
enum class Master : uint32_t {
|
||||||
REQUEST_ZONE_TRANSFER = 1,
|
REQUEST_PERSISTENT_ID = 1,
|
||||||
|
REQUEST_PERSISTENT_ID_RESPONSE,
|
||||||
|
REQUEST_ZONE_TRANSFER,
|
||||||
REQUEST_ZONE_TRANSFER_RESPONSE,
|
REQUEST_ZONE_TRANSFER_RESPONSE,
|
||||||
SERVER_INFO,
|
SERVER_INFO,
|
||||||
REQUEST_SESSION_KEY,
|
REQUEST_SESSION_KEY,
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
// These are the same define, but they mean two different things in different contexts
|
// These are the same define, but they mean two different things in different contexts
|
||||||
// so a different define to distinguish what calculation is happening will help clarity.
|
// so a different define to distinguish what calculation is happening will help clarity.
|
||||||
#define FRAMES_TO_MS(x) (1000 / (x))
|
#define FRAMES_TO_MS(x) 1000 / x
|
||||||
#define MS_TO_FRAMES(x) (1000 / (x))
|
#define MS_TO_FRAMES(x) 1000 / x
|
||||||
|
|
||||||
//=========== FRAME TIMINGS ===========
|
//=========== FRAME TIMINGS ===========
|
||||||
constexpr uint32_t highFramerate = 60;
|
constexpr uint32_t highFramerate = 60;
|
||||||
@@ -58,7 +58,6 @@ constexpr LWOCLONEID LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID
|
|||||||
constexpr LWOINSTANCEID LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID
|
constexpr LWOINSTANCEID LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID
|
||||||
constexpr LWOMAPID LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID
|
constexpr LWOMAPID LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID
|
||||||
constexpr uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID
|
constexpr uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID
|
||||||
constexpr uint32_t MAX_MESSAGE_LENGTH = 0x500000; //!< Prevent exceptionally large msgs from being processed. Should always be used to check user provided inputs.
|
|
||||||
|
|
||||||
constexpr float PI = 3.14159f;
|
constexpr float PI = 3.14159f;
|
||||||
|
|
||||||
@@ -111,6 +110,18 @@ private:
|
|||||||
|
|
||||||
constexpr LWOSCENEID LWOSCENEID_INVALID = -1;
|
constexpr LWOSCENEID LWOSCENEID_INVALID = -1;
|
||||||
|
|
||||||
|
struct LWONameValue {
|
||||||
|
uint32_t length = 0; //!< The length of the name
|
||||||
|
std::u16string name; //!< The name
|
||||||
|
|
||||||
|
LWONameValue() = default;
|
||||||
|
|
||||||
|
LWONameValue(const std::u16string& name) {
|
||||||
|
this->name = name;
|
||||||
|
this->length = static_cast<uint32_t>(name.length());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct FriendData {
|
struct FriendData {
|
||||||
public:
|
public:
|
||||||
bool isOnline = false;
|
bool isOnline = false;
|
||||||
|
|||||||
@@ -18,10 +18,7 @@ enum class eCharacterVersion : uint32_t {
|
|||||||
SPEED_BASE,
|
SPEED_BASE,
|
||||||
// Fixes nexus force explorer missions
|
// Fixes nexus force explorer missions
|
||||||
NJ_JAYMISSIONS,
|
NJ_JAYMISSIONS,
|
||||||
NEXUS_FORCE_EXPLORER, // Fixes pet ids in player inventories
|
UP_TO_DATE, // will become NEXUS_FORCE_EXPLORER
|
||||||
PET_IDS, // Fixes pet ids in player inventories
|
|
||||||
INVENTORY_PERSISTENT_IDS, // Fixes racing meta missions
|
|
||||||
UP_TO_DATE, // will become RACING_META_MISSIONS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ECHARACTERVERSION__H__
|
#endif //!__ECHARACTERVERSION__H__
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
#ifndef __ELOGINRESPONSE__H__
|
|
||||||
#define __ELOGINRESPONSE__H__
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
enum class eLoginResponse : uint8_t {
|
|
||||||
GENERAL_FAILED = 0,
|
|
||||||
SUCCESS,
|
|
||||||
BANNED,
|
|
||||||
// Unused 3
|
|
||||||
// Unused 4
|
|
||||||
PERMISSIONS_NOT_HIGH_ENOUGH = 5,
|
|
||||||
INVALID_USER,
|
|
||||||
ACCOUNT_LOCKED,
|
|
||||||
WRONG_PASS,
|
|
||||||
ACCOUNT_ACTIVATION_PENDING,
|
|
||||||
ACCOUNT_DISABLED,
|
|
||||||
GAME_TIME_EXPIRED,
|
|
||||||
FREE_TRIAL_ENDED,
|
|
||||||
PLAY_SCHEDULE_TIME_UP,
|
|
||||||
ACCOUNT_NOT_ACTIVATED
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__ELOGINRESPONSE__H__
|
|
||||||
@@ -50,10 +50,7 @@ enum class eMissionState : int {
|
|||||||
/**
|
/**
|
||||||
* The mission has been completed before and has now been completed again. Used for daily missions.
|
* The mission has been completed before and has now been completed again. Used for daily missions.
|
||||||
*/
|
*/
|
||||||
COMPLETE_READY_TO_COMPLETE = 12,
|
COMPLETE_READY_TO_COMPLETE = 12
|
||||||
|
|
||||||
// The mission is failed (don't know where this is used)
|
|
||||||
FAILED = 16,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__MISSIONSTATE__H__
|
#endif //!__MISSIONSTATE__H__
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
#ifndef EOBJECTBITS_H
|
#ifndef __EOBJECTBITS__H__
|
||||||
#define EOBJECTBITS_H
|
#define __EOBJECTBITS__H__
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
enum class eObjectBits : size_t {
|
enum class eObjectBits : size_t {
|
||||||
|
PERSISTENT = 32,
|
||||||
CLIENT = 46,
|
CLIENT = 46,
|
||||||
SPAWNED = 58,
|
SPAWNED = 58,
|
||||||
CHARACTER = 60
|
CHARACTER = 60
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!EOBJECTBITS_H
|
#endif //!__EOBJECTBITS__H__
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
#ifndef __ESERVERDISCONNECTIDENTIFIERS__H__
|
|
||||||
#define __ESERVERDISCONNECTIDENTIFIERS__H__
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
enum class eServerDisconnectIdentifiers : uint32_t {
|
|
||||||
UNKNOWN_SERVER_ERROR = 0,
|
|
||||||
WRONG_GAME_VERSION,
|
|
||||||
WRONG_SERVER_VERSION,
|
|
||||||
CONNECTION_ON_INVALID_PORT,
|
|
||||||
DUPLICATE_LOGIN,
|
|
||||||
SERVER_SHUTDOWN,
|
|
||||||
SERVER_MAP_LOAD_FAILURE,
|
|
||||||
INVALID_SESSION_KEY,
|
|
||||||
ACCOUNT_NOT_IN_PENDING_LIST,
|
|
||||||
CHARACTER_NOT_FOUND,
|
|
||||||
CHARACTER_CORRUPTED,
|
|
||||||
KICK,
|
|
||||||
SAVE_FAILURE,
|
|
||||||
FREE_TRIAL_EXPIRED,
|
|
||||||
PLAY_SCHEDULE_TIME_DONE
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__ESERVERDISCONNECTIDENTIFIERS__H__
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
|
|
||||||
|
|
||||||
void CDActivitiesTable::LoadValuesFromDatabase() {
|
void CDActivitiesTable::LoadValuesFromDatabase() {
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
@@ -55,13 +56,3 @@ std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActiviti
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<const CDActivities> CDActivitiesTable::GetActivity(const uint32_t activityID) {
|
|
||||||
auto& entries = GetEntries();
|
|
||||||
for (const auto& entry : entries) {
|
|
||||||
if (entry.ActivityID == activityID) {
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
struct CDActivities {
|
struct CDActivities {
|
||||||
uint32_t ActivityID;
|
uint32_t ActivityID;
|
||||||
@@ -32,5 +31,4 @@ public:
|
|||||||
|
|
||||||
// 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::optional<const CDActivities> GetActivity(const uint32_t activityID);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -154,8 +154,8 @@ std::map<LOT, uint32_t> CDItemComponentTable::ParseCraftingCurrencies(const CDIt
|
|||||||
// Checking for 2 here, not sure what to do when there's more stuff than expected
|
// Checking for 2 here, not sure what to do when there's more stuff than expected
|
||||||
if (amountSplit.size() == 2) {
|
if (amountSplit.size() == 2) {
|
||||||
currencies.insert({
|
currencies.insert({
|
||||||
GeneralUtils::TryParse<LOT>(amountSplit[0], LOT_NULL),
|
std::stoull(amountSplit[0]),
|
||||||
GeneralUtils::TryParse<uint32_t>(amountSplit[1], 0)
|
std::stoi(amountSplit[1])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,14 +93,13 @@ std::vector<CDMissions> CDMissionsTable::Query(std::function<bool(CDMissions)> p
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const {
|
const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const {
|
||||||
const CDMissions* toReturn = &Default;
|
|
||||||
for (const auto& entry : GetEntries()) {
|
for (const auto& entry : GetEntries()) {
|
||||||
if (entry.id == missionID) {
|
if (entry.id == missionID) {
|
||||||
toReturn = &entry;
|
return const_cast<CDMissions*>(&entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
return &Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const {
|
const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const {
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ public:
|
|||||||
// 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);
|
||||||
|
|
||||||
// Cannot be null.
|
|
||||||
const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
|
const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
|
||||||
|
|
||||||
const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const;
|
const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const;
|
||||||
|
|||||||
@@ -38,11 +38,3 @@ std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObje
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDObjectSkills> CDObjectSkillsTable::Get(const LOT lot) const {
|
|
||||||
std::vector<CDObjectSkills> toReturn;
|
|
||||||
for (const auto& entry : GetEntries()) {
|
|
||||||
if (entry.objectTemplate == lot) toReturn.push_back(entry);
|
|
||||||
}
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,13 +4,12 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct CDObjectSkills {
|
struct CDObjectSkills {
|
||||||
uint32_t objectTemplate; //!< The LOT of the item
|
uint32_t objectTemplate; //!< The LOT of the item
|
||||||
uint32_t skillID; //!< The Skill ID of the object
|
uint32_t skillID; //!< The Skill ID of the object
|
||||||
uint32_t castOnType; //!< ???
|
uint32_t castOnType; //!< ???
|
||||||
int32_t AICombatWeight; //!< ???
|
uint32_t AICombatWeight; //!< ???
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDObjectSkillsTable : public CDTable<CDObjectSkillsTable, std::vector<CDObjectSkills>> {
|
class CDObjectSkillsTable : public CDTable<CDObjectSkillsTable, std::vector<CDObjectSkills>> {
|
||||||
@@ -18,6 +17,5 @@ public:
|
|||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
|
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
|
||||||
std::vector<CDObjectSkills> Get(const LOT lot) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const CDObjects& CDObjectsTable::GetByID(const uint32_t lot) {
|
|||||||
entry.name = tableData.getStringField("name", "");
|
entry.name = tableData.getStringField("name", "");
|
||||||
UNUSED(entry.placeable = tableData.getIntField("placeable", -1));
|
UNUSED(entry.placeable = tableData.getIntField("placeable", -1));
|
||||||
entry.type = tableData.getStringField("type", "");
|
entry.type = tableData.getStringField("type", "");
|
||||||
UNUSED(entry.description = tableData.getStringField(4, ""));
|
UNUSED(ntry.description = tableData.getStringField(4, ""));
|
||||||
UNUSED(entry.localize = tableData.getIntField("localize", -1));
|
UNUSED(entry.localize = tableData.getIntField("localize", -1));
|
||||||
UNUSED(entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1));
|
UNUSED(entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1));
|
||||||
UNUSED(entry.displayName = tableData.getStringField("displayName", ""));
|
UNUSED(entry.displayName = tableData.getStringField("displayName", ""));
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ CDRailActivatorComponent CDRailActivatorComponentTable::GetEntryByID(int32_t id)
|
|||||||
std::pair<uint32_t, std::u16string> CDRailActivatorComponentTable::EffectPairFromString(std::string& str) {
|
std::pair<uint32_t, std::u16string> CDRailActivatorComponentTable::EffectPairFromString(std::string& str) {
|
||||||
const auto split = GeneralUtils::SplitString(str, ':');
|
const auto split = GeneralUtils::SplitString(str, ':');
|
||||||
if (split.size() == 2) {
|
if (split.size() == 2) {
|
||||||
return { GeneralUtils::TryParse(split.at(0), 0), GeneralUtils::ASCIIToUTF16(split.at(1)) };
|
return { std::stoi(split.at(0)), GeneralUtils::ASCIIToUTF16(split.at(1)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public:
|
|||||||
virtual void Commit() = 0;
|
virtual void Commit() = 0;
|
||||||
virtual bool GetAutoCommit() = 0;
|
virtual bool GetAutoCommit() = 0;
|
||||||
virtual void SetAutoCommit(bool value) = 0;
|
virtual void SetAutoCommit(bool value) = 0;
|
||||||
virtual void DeleteCharacter(const LWOOBJID characterId) = 0;
|
virtual void DeleteCharacter(const uint32_t characterId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__GAMEDATABASE__H__
|
#endif //!__GAMEDATABASE__H__
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ enum class eActivityType : uint32_t {
|
|||||||
class IActivityLog {
|
class IActivityLog {
|
||||||
public:
|
public:
|
||||||
// Update the activity log for the given account.
|
// Update the activity log for the given account.
|
||||||
virtual void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) = 0;
|
virtual void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IACTIVITYLOG__H__
|
#endif //!__IACTIVITYLOG__H__
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class IBehaviors {
|
|||||||
public:
|
public:
|
||||||
struct Info {
|
struct Info {
|
||||||
LWOOBJID behaviorId{};
|
LWOOBJID behaviorId{};
|
||||||
LWOOBJID characterId{};
|
uint32_t characterId{};
|
||||||
std::string behaviorInfo;
|
std::string behaviorInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public:
|
|||||||
std::string clientVersion;
|
std::string clientVersion;
|
||||||
std::string otherPlayer;
|
std::string otherPlayer;
|
||||||
std::string selection;
|
std::string selection;
|
||||||
LWOOBJID characterId{};
|
uint32_t characterId{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add a new bug report to the database.
|
// Add a new bug report to the database.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public:
|
|||||||
struct Info {
|
struct Info {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string pendingName;
|
std::string pendingName;
|
||||||
LWOOBJID id{};
|
uint32_t id{};
|
||||||
uint32_t accountId{};
|
uint32_t accountId{};
|
||||||
bool needsRename{};
|
bool needsRename{};
|
||||||
LWOCLONEID cloneId{};
|
LWOCLONEID cloneId{};
|
||||||
@@ -25,25 +25,25 @@ public:
|
|||||||
virtual std::vector<std::string> GetApprovedCharacterNames() = 0;
|
virtual std::vector<std::string> GetApprovedCharacterNames() = 0;
|
||||||
|
|
||||||
// Get the character info for the given character id.
|
// Get the character info for the given character id.
|
||||||
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) = 0;
|
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) = 0;
|
||||||
|
|
||||||
// Get the character info for the given character name.
|
// Get the character info for the given character name.
|
||||||
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view name) = 0;
|
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view name) = 0;
|
||||||
|
|
||||||
// Get the character ids for the given account.
|
// Get the character ids for the given account.
|
||||||
virtual std::vector<LWOOBJID> GetAccountCharacterIds(const LWOOBJID accountId) = 0;
|
virtual std::vector<uint32_t> GetAccountCharacterIds(const uint32_t accountId) = 0;
|
||||||
|
|
||||||
// Insert a new character into the database.
|
// Insert a new character into the database.
|
||||||
virtual void InsertNewCharacter(const ICharInfo::Info info) = 0;
|
virtual void InsertNewCharacter(const ICharInfo::Info info) = 0;
|
||||||
|
|
||||||
// Set the name of the given character.
|
// Set the name of the given character.
|
||||||
virtual void SetCharacterName(const LWOOBJID characterId, const std::string_view name) = 0;
|
virtual void SetCharacterName(const uint32_t characterId, const std::string_view name) = 0;
|
||||||
|
|
||||||
// Set the pending name of the given character.
|
// Set the pending name of the given character.
|
||||||
virtual void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) = 0;
|
virtual void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) = 0;
|
||||||
|
|
||||||
// Updates the given character ids last login to be right now.
|
// Updates the given character ids last login to be right now.
|
||||||
virtual void UpdateLastLoggedInCharacter(const LWOOBJID characterId) = 0;
|
virtual void UpdateLastLoggedInCharacter(const uint32_t characterId) = 0;
|
||||||
|
|
||||||
virtual bool IsNameInUse(const std::string_view name) = 0;
|
virtual bool IsNameInUse(const std::string_view name) = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
class ICharXml {
|
class ICharXml {
|
||||||
public:
|
public:
|
||||||
// Get the character xml for the given character id.
|
// Get the character xml for the given character id.
|
||||||
virtual std::string GetCharacterXml(const LWOOBJID charId) = 0;
|
virtual std::string GetCharacterXml(const uint32_t charId) = 0;
|
||||||
|
|
||||||
// Update the character xml for the given character id.
|
// Update the character xml for the given character id.
|
||||||
virtual void UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) = 0;
|
virtual void UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) = 0;
|
||||||
|
|
||||||
// Insert the character xml for the given character id.
|
// Insert the character xml for the given character id.
|
||||||
virtual void InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) = 0;
|
virtual void InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ICHARXML__H__
|
#endif //!__ICHARXML__H__
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ICommandLog {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// Insert a new slash command log entry.
|
// Insert a new slash command log entry.
|
||||||
virtual void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) = 0;
|
virtual void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ICOMMANDLOG__H__
|
#endif //!__ICOMMANDLOG__H__
|
||||||
|
|||||||
@@ -8,25 +8,25 @@
|
|||||||
class IFriends {
|
class IFriends {
|
||||||
public:
|
public:
|
||||||
struct BestFriendStatus {
|
struct BestFriendStatus {
|
||||||
LWOOBJID playerCharacterId{};
|
uint32_t playerCharacterId{};
|
||||||
LWOOBJID friendCharacterId{};
|
uint32_t friendCharacterId{};
|
||||||
uint32_t bestFriendStatus{};
|
uint32_t bestFriendStatus{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the friends list for the given character id.
|
// Get the friends list for the given character id.
|
||||||
virtual std::vector<FriendData> GetFriendsList(const LWOOBJID charId) = 0;
|
virtual std::vector<FriendData> GetFriendsList(const uint32_t charId) = 0;
|
||||||
|
|
||||||
// Get the best friend status for the given player and friend character ids.
|
// Get the best friend status for the given player and friend character ids.
|
||||||
virtual std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
virtual std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
||||||
|
|
||||||
// Set the best friend status for the given player and friend character ids.
|
// Set the best friend status for the given player and friend character ids.
|
||||||
virtual void SetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId, const uint32_t bestFriendStatus) = 0;
|
virtual void SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) = 0;
|
||||||
|
|
||||||
// Add a friend to the given character id.
|
// Add a friend to the given character id.
|
||||||
virtual void AddFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
virtual void AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
||||||
|
|
||||||
// Remove a friend from the given character id.
|
// Remove a friend from the given character id.
|
||||||
virtual void RemoveFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
virtual void RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IFRIENDS__H__
|
#endif //!__IFRIENDS__H__
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ class IIgnoreList {
|
|||||||
public:
|
public:
|
||||||
struct Info {
|
struct Info {
|
||||||
std::string name;
|
std::string name;
|
||||||
LWOOBJID id;
|
uint32_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual std::vector<Info> GetIgnoreList(const LWOOBJID playerId) = 0;
|
virtual std::vector<Info> GetIgnoreList(const uint32_t playerId) = 0;
|
||||||
virtual void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) = 0;
|
virtual void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) = 0;
|
||||||
virtual void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) = 0;
|
virtual void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IIGNORELIST__H__
|
#endif //!__IIGNORELIST__H__
|
||||||
|
|||||||
@@ -5,13 +5,12 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "dCommonVars.h"
|
|
||||||
|
|
||||||
class ILeaderboard {
|
class ILeaderboard {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
LWOOBJID charId{};
|
uint32_t charId{};
|
||||||
uint32_t lastPlayedTimestamp{};
|
uint32_t lastPlayedTimestamp{};
|
||||||
float primaryScore{};
|
float primaryScore{};
|
||||||
float secondaryScore{};
|
float secondaryScore{};
|
||||||
@@ -37,12 +36,12 @@ public:
|
|||||||
virtual std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) = 0;
|
virtual std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) = 0;
|
||||||
virtual std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) = 0;
|
virtual std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) = 0;
|
||||||
virtual std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) = 0;
|
virtual std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) = 0;
|
||||||
virtual std::optional<Score> GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) = 0;
|
virtual std::optional<Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) = 0;
|
||||||
|
|
||||||
virtual void SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) = 0;
|
virtual void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
|
||||||
virtual void UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) = 0;
|
virtual void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
|
||||||
virtual void IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) = 0;
|
virtual void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) = 0;
|
||||||
virtual void IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) = 0;
|
virtual void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ILEADERBOARD__H__
|
#endif //!__ILEADERBOARD__H__
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ public:
|
|||||||
virtual void InsertNewMail(const MailInfo& mail) = 0;
|
virtual void InsertNewMail(const MailInfo& mail) = 0;
|
||||||
|
|
||||||
// Get the mail for the given character id.
|
// Get the mail for the given character id.
|
||||||
virtual std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) = 0;
|
virtual std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) = 0;
|
||||||
|
|
||||||
// Get the mail for the given mail id.
|
// Get the mail for the given mail id.
|
||||||
virtual std::optional<MailInfo> GetMail(const uint64_t mailId) = 0;
|
virtual std::optional<MailInfo> GetMail(const uint64_t mailId) = 0;
|
||||||
|
|
||||||
// Get the number of unread mail for the given character id.
|
// Get the number of unread mail for the given character id.
|
||||||
virtual uint32_t GetUnreadMailCount(const LWOOBJID characterId) = 0;
|
virtual uint32_t GetUnreadMailCount(const uint32_t characterId) = 0;
|
||||||
|
|
||||||
// Mark the given mail as read.
|
// Mark the given mail as read.
|
||||||
virtual void MarkMailRead(const uint64_t mailId) = 0;
|
virtual void MarkMailRead(const uint64_t mailId) = 0;
|
||||||
|
|||||||
@@ -6,19 +6,14 @@
|
|||||||
|
|
||||||
class IObjectIdTracker {
|
class IObjectIdTracker {
|
||||||
public:
|
public:
|
||||||
// Only the first 48 bits of the ids are the id, the last 16 bits are reserved for flags.
|
|
||||||
struct Range {
|
|
||||||
uint64_t minID{}; // Only the first 48 bits are the id, the last 16 bits are reserved for flags.
|
|
||||||
uint64_t maxID{}; // Only the first 48 bits are the id, the last 16 bits are reserved for flags.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the current persistent id.
|
// Get the current persistent id.
|
||||||
virtual std::optional<uint64_t> GetCurrentPersistentId() = 0;
|
virtual std::optional<uint32_t> GetCurrentPersistentId() = 0;
|
||||||
|
|
||||||
// Insert the default persistent id.
|
// Insert the default persistent id.
|
||||||
virtual void InsertDefaultPersistentId() = 0;
|
virtual void InsertDefaultPersistentId() = 0;
|
||||||
|
|
||||||
virtual Range GetPersistentIdRange() = 0;
|
// Update the persistent id.
|
||||||
|
virtual void UpdatePersistentId(const uint32_t newId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IOBJECTIDTRACKER__H__
|
#endif //!__IOBJECTIDTRACKER__H__
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public:
|
|||||||
std::string description;
|
std::string description;
|
||||||
std::string rejectionReason;
|
std::string rejectionReason;
|
||||||
LWOOBJID id{};
|
LWOOBJID id{};
|
||||||
LWOOBJID ownerId{};
|
uint32_t ownerId{};
|
||||||
LWOCLONEID cloneId{};
|
LWOCLONEID cloneId{};
|
||||||
int32_t privacyOption{};
|
int32_t privacyOption{};
|
||||||
uint32_t modApproved{};
|
uint32_t modApproved{};
|
||||||
@@ -27,29 +27,25 @@ public:
|
|||||||
uint32_t mapId{};
|
uint32_t mapId{};
|
||||||
std::string searchString;
|
std::string searchString;
|
||||||
ePropertySortType sortChoice{};
|
ePropertySortType sortChoice{};
|
||||||
LWOOBJID playerId{};
|
uint32_t playerId{};
|
||||||
uint32_t numResults{};
|
uint32_t numResults{};
|
||||||
uint32_t startIndex{};
|
uint32_t startIndex{};
|
||||||
uint32_t playerSort{};
|
uint32_t playerSort{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PropertyEntranceResult {
|
struct PropertyEntranceResult {
|
||||||
// This is the number of entries that are in the query IF it were ran without a limit.
|
|
||||||
int32_t totalEntriesMatchingQuery{};
|
int32_t totalEntriesMatchingQuery{};
|
||||||
// The entries that match the query. This should only contain up to 12 entries.
|
// The entries that match the query. This should only contain up to 12 entries.
|
||||||
std::vector<IProperty::Info> entries;
|
std::vector<IProperty::Info> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the property info for the given property id.
|
|
||||||
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) = 0;
|
|
||||||
|
|
||||||
// Get the property info for the given property id.
|
// Get the property info for the given property id.
|
||||||
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
||||||
|
|
||||||
// Get the properties for the given property lookup params.
|
// Get the properties for the given property lookup params.
|
||||||
// This is expected to return a result set of up to 12 properties
|
// This is expected to return a result set of up to 12 properties
|
||||||
// so as not to transfer too much data at once.
|
// so as not to transfer too much data at once.
|
||||||
virtual IProperty::PropertyEntranceResult GetProperties(const PropertyLookup& params) = 0;
|
virtual std::optional<IProperty::PropertyEntranceResult> GetProperties(const PropertyLookup& params) = 0;
|
||||||
|
|
||||||
// Update the property moderation info for the given property id.
|
// Update the property moderation info for the given property id.
|
||||||
virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0;
|
virtual void UpdatePropertyModerationInfo(const IProperty::Info& info) = 0;
|
||||||
|
|||||||
@@ -16,16 +16,16 @@ public:
|
|||||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||||
LWOOBJID id{};
|
LWOOBJID id{};
|
||||||
LOT lot{};
|
LOT lot{};
|
||||||
LWOOBJID ugcId{};
|
uint32_t ugcId{};
|
||||||
std::array<LWOOBJID, 5> behaviors{};
|
std::array<LWOOBJID, 5> behaviors{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inserts a new UGC model into the database.
|
// Inserts a new UGC model into the database.
|
||||||
virtual void InsertNewUgcModel(
|
virtual void InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data,
|
std::stringstream& sd0Data,
|
||||||
const uint64_t blueprintId,
|
const uint32_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const LWOOBJID characterId) = 0;
|
const uint32_t characterId) = 0;
|
||||||
|
|
||||||
// Get the property models for the given property id.
|
// Get the property models for the given property id.
|
||||||
virtual std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) = 0;
|
virtual std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) = 0;
|
||||||
@@ -45,6 +45,6 @@ public:
|
|||||||
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
||||||
|
|
||||||
// Gets a model by ID
|
// Gets a model by ID
|
||||||
virtual std::optional<Model> GetModel(const LWOOBJID modelID) = 0;
|
virtual Model GetModel(const LWOOBJID modelID) = 0;
|
||||||
};
|
};
|
||||||
#endif //!__IPROPERTIESCONTENTS__H__
|
#endif //!__IPROPERTIESCONTENTS__H__
|
||||||
|
|||||||
@@ -29,7 +29,5 @@ public:
|
|||||||
|
|
||||||
// Inserts a new UGC model into the database.
|
// Inserts a new UGC model into the database.
|
||||||
virtual void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) = 0;
|
virtual void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) = 0;
|
||||||
|
|
||||||
virtual std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) = 0;
|
|
||||||
};
|
};
|
||||||
#endif //!__IUGC__H__
|
#endif //!__IUGC__H__
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
class IUgcModularBuild {
|
class IUgcModularBuild {
|
||||||
public:
|
public:
|
||||||
virtual void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) = 0;
|
virtual void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) = 0;
|
||||||
virtual void DeleteUgcBuild(const LWOOBJID bigId) = 0;
|
virtual void DeleteUgcBuild(const LWOOBJID bigId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ void MySQLDatabase::SetAutoCommit(bool value) {
|
|||||||
con->setAutoCommit(value);
|
con->setAutoCommit(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::DeleteCharacter(const LWOOBJID characterId) {
|
void MySQLDatabase::DeleteCharacter(const uint32_t characterId) {
|
||||||
ExecuteDelete("DELETE FROM charxml WHERE id=? LIMIT 1;", characterId);
|
ExecuteDelete("DELETE FROM charxml WHERE id=? LIMIT 1;", characterId);
|
||||||
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
||||||
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
||||||
|
|||||||
@@ -9,20 +9,6 @@
|
|||||||
typedef std::unique_ptr<sql::PreparedStatement>& UniquePreppedStmtRef;
|
typedef std::unique_ptr<sql::PreparedStatement>& UniquePreppedStmtRef;
|
||||||
typedef std::unique_ptr<sql::ResultSet> UniqueResultSet;
|
typedef std::unique_ptr<sql::ResultSet> UniqueResultSet;
|
||||||
|
|
||||||
// This struct is used to keep the PreparedStatement alive alongside the ResultSet, since the ResultSet will be invalidated if the PreparedStatement is destroyed.
|
|
||||||
// Declaring the members in reverse order of usage to ensure the PreparedStatement is destroyed after the ResultSet. This is guaranteed by the C++ standard.
|
|
||||||
struct PreparedStmtResultSet {
|
|
||||||
std::unique_ptr<sql::PreparedStatement> m_stmt;
|
|
||||||
std::unique_ptr<sql::ResultSet> m_resultSet;
|
|
||||||
|
|
||||||
PreparedStmtResultSet(sql::PreparedStatement* stmt = nullptr, sql::ResultSet* resultSet = nullptr)
|
|
||||||
: m_stmt(stmt), m_resultSet(resultSet) {}
|
|
||||||
|
|
||||||
sql::ResultSet* operator->() const {
|
|
||||||
return m_resultSet.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Purposefully no definition for this to provide linker errors in the case someone tries to
|
// Purposefully no definition for this to provide linker errors in the case someone tries to
|
||||||
// bind a parameter to a type that isn't defined.
|
// bind a parameter to a type that isn't defined.
|
||||||
template<typename ParamType>
|
template<typename ParamType>
|
||||||
@@ -54,31 +40,31 @@ public:
|
|||||||
|
|
||||||
std::vector<std::string> GetApprovedCharacterNames() override;
|
std::vector<std::string> GetApprovedCharacterNames() override;
|
||||||
|
|
||||||
std::vector<FriendData> GetFriendsList(LWOOBJID charID) override;
|
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) override;
|
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
||||||
void SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) override;
|
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
||||||
void AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||||
void RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||||
void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
||||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
||||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
std::vector<IUgc::Model> GetAllUgcModels() override;
|
||||||
void CreateMigrationHistoryTable() override;
|
void CreateMigrationHistoryTable() override;
|
||||||
bool IsMigrationRun(const std::string_view str) override;
|
bool IsMigrationRun(const std::string_view str) override;
|
||||||
void InsertMigration(const std::string_view str) override;
|
void InsertMigration(const std::string_view str) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
||||||
std::string GetCharacterXml(const LWOOBJID accountId) override;
|
std::string GetCharacterXml(const uint32_t accountId) override;
|
||||||
void UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) override;
|
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
||||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||||
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
||||||
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
||||||
void DeleteCharacter(const LWOOBJID characterId) override;
|
void DeleteCharacter(const uint32_t characterId) override;
|
||||||
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||||
void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||||
void UpdateLastLoggedInCharacter(const LWOOBJID characterId) override;
|
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
||||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
||||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
||||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
||||||
@@ -97,68 +83,63 @@ public:
|
|||||||
void InsertNewMail(const MailInfo& mail) override;
|
void InsertNewMail(const MailInfo& mail) override;
|
||||||
void InsertNewUgcModel(
|
void InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data,
|
std::stringstream& sd0Data,
|
||||||
const uint64_t blueprintId,
|
const uint32_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const LWOOBJID characterId) override;
|
const uint32_t characterId) override;
|
||||||
std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) override;
|
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||||
uint32_t GetUnreadMailCount(const LWOOBJID characterId) override;
|
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
||||||
void MarkMailRead(const uint64_t mailId) override;
|
void MarkMailRead(const uint64_t mailId) override;
|
||||||
void DeleteMail(const uint64_t mailId) override;
|
void DeleteMail(const uint64_t mailId) override;
|
||||||
void ClaimMailItem(const uint64_t mailId) override;
|
void ClaimMailItem(const uint64_t mailId) override;
|
||||||
void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) override;
|
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
||||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||||
std::optional<uint64_t> GetCurrentPersistentId() override;
|
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||||
IObjectIdTracker::Range GetPersistentIdRange() override;
|
|
||||||
void InsertDefaultPersistentId() override;
|
void InsertDefaultPersistentId() override;
|
||||||
|
void UpdatePersistentId(const uint32_t id) override;
|
||||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||||
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||||
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||||
std::vector<IIgnoreList::Info> GetIgnoreList(const LWOOBJID playerId) override;
|
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
||||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||||
void AddBehavior(const IBehaviors::Info& info) override;
|
void AddBehavior(const IBehaviors::Info& info) override;
|
||||||
std::string GetBehavior(const LWOOBJID behaviorId) override;
|
std::string GetBehavior(const LWOOBJID behaviorId) override;
|
||||||
void RemoveBehavior(const LWOOBJID characterId) override;
|
void RemoveBehavior(const LWOOBJID characterId) override;
|
||||||
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
||||||
IProperty::PropertyEntranceResult GetProperties(const IProperty::PropertyLookup& params) override;
|
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override;
|
||||||
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
||||||
void SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override;
|
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||||
void UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override;
|
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||||
std::optional<ILeaderboard::Score> GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) override;
|
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
||||||
void IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) override;
|
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
||||||
void IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) override;
|
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
||||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override;
|
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
||||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||||
uint32_t GetAccountCount() override;
|
uint32_t GetAccountCount() override;
|
||||||
bool IsNameInUse(const std::string_view name) override;
|
bool IsNameInUse(const std::string_view name) override;
|
||||||
std::optional<IPropertyContents::Model> GetModel(const LWOOBJID modelID) override;
|
IPropertyContents::Model GetModel(const LWOOBJID modelID) override;
|
||||||
std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) override;
|
|
||||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) override;
|
|
||||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Generic query functions that can be used for any query.
|
// Generic query functions that can be used for any query.
|
||||||
// Return type may be different depending on the query, so it is up to the caller to check the return type.
|
// Return type may be different depending on the query, so it is up to the caller to check the return type.
|
||||||
// The first argument is the query string, and the rest are the parameters to bind to the query.
|
// The first argument is the query string, and the rest are the parameters to bind to the query.
|
||||||
// The return type is a PreparedStmtResultSet which keeps the PreparedStatement alive alongside the ResultSet.
|
// The return type is a unique_ptr to the result set, which is deleted automatically when it goes out of scope
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
inline PreparedStmtResultSet ExecuteSelect(const std::string& query, Args&&... args) {
|
inline std::unique_ptr<sql::ResultSet> ExecuteSelect(const std::string& query, Args&&... args) {
|
||||||
PreparedStmtResultSet toReturn;
|
std::unique_ptr<sql::PreparedStatement> preppedStmt(CreatePreppedStmt(query));
|
||||||
toReturn.m_stmt.reset(CreatePreppedStmt(query));
|
SetParams(preppedStmt, std::forward<Args>(args)...);
|
||||||
SetParams(toReturn.m_stmt, std::forward<Args>(args)...);
|
DLU_SQL_TRY_CATCH_RETHROW(return std::unique_ptr<sql::ResultSet>(preppedStmt->executeQuery()));
|
||||||
DLU_SQL_TRY_CATCH_RETHROW(toReturn.m_resultSet.reset(toReturn.m_stmt->executeQuery()));
|
|
||||||
// Return the PreparedStmtResultSet, which now owns both the PreparedStatement and ResultSet via unique_ptr and will ensure they are properly cleaned up.
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
@@ -187,91 +168,91 @@ private:
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string_view param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string_view param) {
|
||||||
LOG_DEBUG("%s", param.data());
|
// LOG("%s", param.data());
|
||||||
stmt->setString(index, param.data());
|
stmt->setString(index, param.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const char* param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const char* param) {
|
||||||
LOG_DEBUG("%s", param);
|
// LOG("%s", param);
|
||||||
stmt->setString(index, param);
|
stmt->setString(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string param) {
|
||||||
LOG_DEBUG("%s", param.c_str());
|
// LOG("%s", param.c_str());
|
||||||
stmt->setString(index, param.c_str());
|
stmt->setString(index, param.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int8_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int8_t param) {
|
||||||
LOG_DEBUG("%u", param);
|
// LOG("%u", param);
|
||||||
stmt->setByte(index, param);
|
stmt->setByte(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint8_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint8_t param) {
|
||||||
LOG_DEBUG("%d", param);
|
// LOG("%d", param);
|
||||||
stmt->setByte(index, param);
|
stmt->setByte(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int16_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int16_t param) {
|
||||||
LOG_DEBUG("%u", param);
|
// LOG("%u", param);
|
||||||
stmt->setShort(index, param);
|
stmt->setShort(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint16_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint16_t param) {
|
||||||
LOG_DEBUG("%d", param);
|
// LOG("%d", param);
|
||||||
stmt->setShort(index, param);
|
stmt->setShort(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint32_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint32_t param) {
|
||||||
LOG_DEBUG("%u", param);
|
// LOG("%u", param);
|
||||||
stmt->setUInt(index, param);
|
stmt->setUInt(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int32_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int32_t param) {
|
||||||
LOG_DEBUG("%d", param);
|
// LOG("%d", param);
|
||||||
stmt->setInt(index, param);
|
stmt->setInt(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int64_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int64_t param) {
|
||||||
LOG_DEBUG("%llu", param);
|
// LOG("%llu", param);
|
||||||
stmt->setInt64(index, param);
|
stmt->setInt64(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint64_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint64_t param) {
|
||||||
LOG_DEBUG("%llu", param);
|
// LOG("%llu", param);
|
||||||
stmt->setUInt64(index, param);
|
stmt->setUInt64(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const float param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const float param) {
|
||||||
LOG_DEBUG("%f", param);
|
// LOG("%f", param);
|
||||||
stmt->setFloat(index, param);
|
stmt->setFloat(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const double param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const double param) {
|
||||||
LOG_DEBUG("%f", param);
|
// LOG("%f", param);
|
||||||
stmt->setDouble(index, param);
|
stmt->setDouble(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const bool param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const bool param) {
|
||||||
LOG_DEBUG("%s", param ? "true" : "false");
|
// LOG("%d", param);
|
||||||
stmt->setBoolean(index, param);
|
stmt->setBoolean(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istream* param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istream* param) {
|
||||||
LOG_DEBUG("Blob");
|
// LOG("Blob");
|
||||||
// This is the one time you will ever see me use const_cast.
|
// This is the one time you will ever see me use const_cast.
|
||||||
stmt->setBlob(index, const_cast<std::istream*>(param));
|
stmt->setBlob(index, const_cast<std::istream*>(param));
|
||||||
}
|
}
|
||||||
@@ -279,21 +260,10 @@ inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istr
|
|||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
||||||
if (param) {
|
if (param) {
|
||||||
LOG_DEBUG("%d", param.value());
|
// LOG("%d", param.value());
|
||||||
stmt->setInt(index, param.value());
|
stmt->setInt(index, param.value());
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG("Null");
|
// LOG("Null");
|
||||||
stmt->setNull(index, sql::DataType::SQLNULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::optional<LWOOBJID> param) {
|
|
||||||
if (param) {
|
|
||||||
LOG_DEBUG("%d", param.value());
|
|
||||||
stmt->setInt64(index, param.value());
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG("Null");
|
|
||||||
stmt->setNull(index, sql::DataType::SQLNULL);
|
stmt->setNull(index, sql::DataType::SQLNULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
void MySQLDatabase::UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
void MySQLDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||||
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
||||||
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ std::vector<std::string> MySQLDatabase::GetApprovedCharacterNames() {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> CharInfoFromQueryResult(PreparedStmtResultSet& stmt) {
|
std::optional<ICharInfo::Info> CharInfoFromQueryResult(std::unique_ptr<sql::ResultSet> stmt) {
|
||||||
if (!stmt->next()) {
|
if (!stmt->next()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICharInfo::Info toReturn;
|
ICharInfo::Info toReturn;
|
||||||
|
|
||||||
toReturn.id = stmt->getInt64("id");
|
toReturn.id = stmt->getUInt("id");
|
||||||
toReturn.name = stmt->getString("name").c_str();
|
toReturn.name = stmt->getString("name").c_str();
|
||||||
toReturn.pendingName = stmt->getString("pending_name").c_str();
|
toReturn.pendingName = stmt->getString("pending_name").c_str();
|
||||||
toReturn.needsRename = stmt->getBoolean("needs_rename");
|
toReturn.needsRename = stmt->getBoolean("needs_rename");
|
||||||
@@ -30,23 +30,25 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(PreparedStmtResultSet& st
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const LWOOBJID charId) {
|
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const uint32_t charId) {
|
||||||
auto result = ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId);
|
return CharInfoFromQueryResult(
|
||||||
return CharInfoFromQueryResult(result);
|
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const std::string_view name) {
|
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const std::string_view name) {
|
||||||
auto result = ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE name = ? LIMIT 1;", name);
|
return CharInfoFromQueryResult(
|
||||||
return CharInfoFromQueryResult(result);
|
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE name = ? LIMIT 1;", name)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LWOOBJID> MySQLDatabase::GetAccountCharacterIds(const LWOOBJID accountId) {
|
std::vector<uint32_t> MySQLDatabase::GetAccountCharacterIds(const uint32_t accountId) {
|
||||||
auto result = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
auto result = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
||||||
|
|
||||||
std::vector<LWOOBJID> toReturn;
|
std::vector<uint32_t> toReturn;
|
||||||
toReturn.reserve(result->rowsCount());
|
toReturn.reserve(result->rowsCount());
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
toReturn.push_back(result->getInt64("id"));
|
toReturn.push_back(result->getUInt("id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
@@ -63,15 +65,15 @@ void MySQLDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
|||||||
static_cast<uint32_t>(time(NULL)));
|
static_cast<uint32_t>(time(NULL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::SetCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
void MySQLDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
void MySQLDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1", name, static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdateLastLoggedInCharacter(const LWOOBJID characterId) {
|
void MySQLDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ? LIMIT 1", static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ? LIMIT 1", static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::string MySQLDatabase::GetCharacterXml(const LWOOBJID charId) {
|
std::string MySQLDatabase::GetCharacterXml(const uint32_t charId) {
|
||||||
auto result = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
auto result = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
||||||
|
|
||||||
if (!result->next()) {
|
if (!result->next()) {
|
||||||
@@ -10,10 +10,10 @@ std::string MySQLDatabase::GetCharacterXml(const LWOOBJID charId) {
|
|||||||
return result->getString("xml_data").c_str();
|
return result->getString("xml_data").c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) {
|
void MySQLDatabase::UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) {
|
||||||
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
void MySQLDatabase::InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
||||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
void MySQLDatabase::InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) {
|
void MySQLDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
||||||
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::vector<FriendData> MySQLDatabase::GetFriendsList(const LWOOBJID charId) {
|
std::vector<FriendData> MySQLDatabase::GetFriendsList(const uint32_t charId) {
|
||||||
auto friendsList = ExecuteSelect(
|
auto friendsList = ExecuteSelect(
|
||||||
R"QUERY(
|
R"QUERY(
|
||||||
SELECT fr.requested_player AS player, best_friend AS bff, ci.name AS name FROM
|
SELECT fr.requested_player AS player, best_friend AS bff, ci.name AS name FROM
|
||||||
@@ -19,7 +19,7 @@ std::vector<FriendData> MySQLDatabase::GetFriendsList(const LWOOBJID charId) {
|
|||||||
|
|
||||||
while (friendsList->next()) {
|
while (friendsList->next()) {
|
||||||
FriendData fd;
|
FriendData fd;
|
||||||
fd.friendID = friendsList->getUInt64("player");
|
fd.friendID = friendsList->getUInt("player");
|
||||||
fd.isBestFriend = friendsList->getInt("bff") == 3; // 0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
fd.isBestFriend = friendsList->getInt("bff") == 3; // 0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||||
fd.friendName = friendsList->getString("name").c_str();
|
fd.friendName = friendsList->getString("name").c_str();
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ std::vector<FriendData> MySQLDatabase::GetFriendsList(const LWOOBJID charId) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||||
auto result = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
auto result = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
friendCharacterId,
|
friendCharacterId,
|
||||||
@@ -42,14 +42,14 @@ std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(con
|
|||||||
}
|
}
|
||||||
|
|
||||||
IFriends::BestFriendStatus toReturn;
|
IFriends::BestFriendStatus toReturn;
|
||||||
toReturn.playerCharacterId = result->getUInt64("player_id");
|
toReturn.playerCharacterId = result->getUInt("player_id");
|
||||||
toReturn.friendCharacterId = result->getUInt64("friend_id");
|
toReturn.friendCharacterId = result->getUInt("friend_id");
|
||||||
toReturn.bestFriendStatus = result->getUInt("best_friend");
|
toReturn.bestFriendStatus = result->getUInt("best_friend");
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::SetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId, const uint32_t bestFriendStatus) {
|
void MySQLDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) {
|
||||||
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||||
bestFriendStatus,
|
bestFriendStatus,
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
@@ -59,11 +59,11 @@ void MySQLDatabase::SetBestFriendStatus(const LWOOBJID playerCharacterId, const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::AddFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
void MySQLDatabase::AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||||
ExecuteInsert("INSERT IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
ExecuteInsert("INSERT IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::RemoveFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
void MySQLDatabase::RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||||
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
friendCharacterId,
|
friendCharacterId,
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> MySQLDatabase::GetIgnoreList(const LWOOBJID playerId) {
|
std::vector<IIgnoreList::Info> MySQLDatabase::GetIgnoreList(const uint32_t playerId) {
|
||||||
auto result = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
auto result = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> ignoreList;
|
std::vector<IIgnoreList::Info> ignoreList;
|
||||||
|
|
||||||
ignoreList.reserve(result->rowsCount());
|
ignoreList.reserve(result->rowsCount());
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
ignoreList.push_back(IIgnoreList::Info{ result->getString("name").c_str(), result->getInt64("ignore_id") });
|
ignoreList.push_back(IIgnoreList::Info{ result->getString("name").c_str(), result->getUInt("ignore_id") });
|
||||||
}
|
}
|
||||||
|
|
||||||
return ignoreList;
|
return ignoreList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
void MySQLDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||||
ExecuteInsert("INSERT IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
ExecuteInsert("INSERT IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
void MySQLDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||||
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ std::optional<uint32_t> MySQLDatabase::GetDonationTotal(const uint32_t activityI
|
|||||||
return donation_total->getUInt("donation_total");
|
return donation_total->getUInt("donation_total");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> ProcessQuery(PreparedStmtResultSet& rows) {
|
std::vector<ILeaderboard::Entry> ProcessQuery(UniqueResultSet& rows) {
|
||||||
std::vector<ILeaderboard::Entry> entries;
|
std::vector<ILeaderboard::Entry> entries;
|
||||||
entries.reserve(rows->rowsCount());
|
entries.reserve(rows->rowsCount());
|
||||||
|
|
||||||
while (rows->next()) {
|
while (rows->next()) {
|
||||||
auto& entry = entries.emplace_back();
|
auto& entry = entries.emplace_back();
|
||||||
|
|
||||||
entry.charId = rows->getUInt64("character_id");
|
entry.charId = rows->getUInt("character_id");
|
||||||
entry.lastPlayedTimestamp = rows->getUInt("lp_unix");
|
entry.lastPlayedTimestamp = rows->getUInt("lp_unix");
|
||||||
entry.primaryScore = rows->getFloat("primaryScore");
|
entry.primaryScore = rows->getFloat("primaryScore");
|
||||||
entry.secondaryScore = rows->getFloat("secondaryScore");
|
entry.secondaryScore = rows->getFloat("secondaryScore");
|
||||||
@@ -58,21 +58,21 @@ std::vector<ILeaderboard::Entry> MySQLDatabase::GetNsLeaderboard(const uint32_t
|
|||||||
return ProcessQuery(leaderboard);
|
return ProcessQuery(leaderboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
void MySQLDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
||||||
ExecuteInsert("INSERT leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, character_id = ?, game_id = ?;",
|
ExecuteInsert("INSERT leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, character_id = ?, game_id = ?;",
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
void MySQLDatabase::UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
||||||
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;",
|
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;",
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) {
|
void MySQLDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) {
|
||||||
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) {
|
std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
|
||||||
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
||||||
auto res = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
auto res = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
if (res->next()) {
|
if (res->next()) {
|
||||||
@@ -86,6 +86,6 @@ std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const LWOOBJID
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) {
|
void MySQLDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t gameId) {
|
||||||
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void MySQLDatabase::InsertNewMail(const MailInfo& mail) {
|
|||||||
mail.itemCount);
|
mail.itemCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) {
|
std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||||
auto res = ExecuteSelect(
|
auto res = ExecuteSelect(
|
||||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
||||||
" FROM mail WHERE receiver_id=? limit ?;",
|
" FROM mail WHERE receiver_id=? limit ?;",
|
||||||
@@ -48,7 +48,7 @@ std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const LWOOBJID characterId
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<MailInfo> MySQLDatabase::GetMail(const uint64_t mailId) {
|
std::optional<MailInfo> MySQLDatabase::GetMail(const uint64_t mailId) {
|
||||||
auto res = ExecuteSelect("SELECT attachment_lot, attachment_count, receiver_id FROM mail WHERE id=? LIMIT 1;", mailId);
|
auto res = ExecuteSelect("SELECT attachment_lot, attachment_count FROM mail WHERE id=? LIMIT 1;", mailId);
|
||||||
|
|
||||||
if (!res->next()) {
|
if (!res->next()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -57,12 +57,11 @@ std::optional<MailInfo> MySQLDatabase::GetMail(const uint64_t mailId) {
|
|||||||
MailInfo toReturn;
|
MailInfo toReturn;
|
||||||
toReturn.itemLOT = res->getInt("attachment_lot");
|
toReturn.itemLOT = res->getInt("attachment_lot");
|
||||||
toReturn.itemCount = res->getInt("attachment_count");
|
toReturn.itemCount = res->getInt("attachment_count");
|
||||||
toReturn.receiverId = res->getUInt64("receiver_id");
|
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MySQLDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
uint32_t MySQLDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
||||||
auto res = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
auto res = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
||||||
|
|
||||||
if (!res->next()) {
|
if (!res->next()) {
|
||||||
|
|||||||
@@ -1,42 +1,17 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::optional<uint64_t> MySQLDatabase::GetCurrentPersistentId() {
|
std::optional<uint32_t> MySQLDatabase::GetCurrentPersistentId() {
|
||||||
auto result = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
auto result = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
||||||
if (!result->next()) {
|
if (!result->next()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return result->getUInt64("last_object_id");
|
return result->getUInt("last_object_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::InsertDefaultPersistentId() {
|
void MySQLDatabase::InsertDefaultPersistentId() {
|
||||||
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
||||||
}
|
}
|
||||||
|
|
||||||
IObjectIdTracker::Range MySQLDatabase::GetPersistentIdRange() {
|
void MySQLDatabase::UpdatePersistentId(const uint32_t newId) {
|
||||||
IObjectIdTracker::Range range;
|
ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = ?;", newId);
|
||||||
auto prevCommit = GetAutoCommit();
|
|
||||||
SetAutoCommit(false);
|
|
||||||
|
|
||||||
// THIS MUST ABSOLUTELY NOT FAIL. These IDs are expected to be unique. As such a transactional select is used to safely get a range
|
|
||||||
// of IDs that will never be used again. A separate feature could track unused IDs and recycle them, but that is not implemented.
|
|
||||||
ExecuteCustomQuery("START TRANSACTION;");
|
|
||||||
// 200 seems like a good range to reserve at once. Only way this would be noticable is if a player
|
|
||||||
// added hundreds of items at once.
|
|
||||||
// Doing the update first ensures that all other connections are blocked from accessing this table until we commit.
|
|
||||||
auto result = ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = last_object_id + 200;");
|
|
||||||
// If no rows were updated, it means the table is empty, so we need to insert the default row first.
|
|
||||||
if (result == 0) {
|
|
||||||
InsertDefaultPersistentId();
|
|
||||||
result = ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = last_object_id + 200;");
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point all connections are waiting on us to finish the transaction, so we can safely select the ID we just set.
|
|
||||||
auto selectRes = ExecuteSelect("SELECT last_object_id FROM object_id_tracker;");
|
|
||||||
selectRes->next();
|
|
||||||
range.maxID = selectRes->getUInt64("last_object_id");
|
|
||||||
range.minID = range.maxID - 199;
|
|
||||||
|
|
||||||
ExecuteCustomQuery("COMMIT;");
|
|
||||||
SetAutoCommit(prevCommit);
|
|
||||||
return range;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,10 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
#include "ePropertySortType.h"
|
#include "ePropertySortType.h"
|
||||||
|
|
||||||
IProperty::Info ReadPropertyInfo(PreparedStmtResultSet& result) {
|
std::optional<IProperty::PropertyEntranceResult> MySQLDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
||||||
IProperty::Info info;
|
std::optional<IProperty::PropertyEntranceResult> result;
|
||||||
info.id = result->getUInt64("id");
|
|
||||||
info.ownerId = result->getInt64("owner_id");
|
|
||||||
info.cloneId = result->getUInt64("clone_id");
|
|
||||||
info.name = result->getString("name").c_str();
|
|
||||||
info.description = result->getString("description").c_str();
|
|
||||||
info.privacyOption = result->getInt("privacy_option");
|
|
||||||
info.rejectionReason = result->getString("rejection_reason").c_str();
|
|
||||||
info.lastUpdatedTime = result->getUInt("last_updated");
|
|
||||||
info.claimedTime = result->getUInt("time_claimed");
|
|
||||||
info.reputation = result->getUInt("reputation");
|
|
||||||
info.modApproved = result->getUInt("mod_approved");
|
|
||||||
info.performanceCost = result->getFloat("performance_cost");
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
IProperty::PropertyEntranceResult MySQLDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
|
||||||
IProperty::PropertyEntranceResult result;
|
|
||||||
std::string query;
|
std::string query;
|
||||||
PreparedStmtResultSet properties;
|
std::unique_ptr<sql::ResultSet> properties;
|
||||||
|
|
||||||
if (params.sortChoice == SORT_TYPE_FEATURED || params.sortChoice == SORT_TYPE_FRIENDS) {
|
if (params.sortChoice == SORT_TYPE_FEATURED || params.sortChoice == SORT_TYPE_FRIENDS) {
|
||||||
query = R"QUERY(
|
query = R"QUERY(
|
||||||
@@ -73,7 +56,8 @@ IProperty::PropertyEntranceResult MySQLDatabase::GetProperties(const IProperty::
|
|||||||
params.playerId
|
params.playerId
|
||||||
);
|
);
|
||||||
if (count->next()) {
|
if (count->next()) {
|
||||||
result.totalEntriesMatchingQuery = count->getUInt("count");
|
if (!result) result = IProperty::PropertyEntranceResult();
|
||||||
|
result->totalEntriesMatchingQuery = count->getUInt("count");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (params.sortChoice == SORT_TYPE_REPUTATION) {
|
if (params.sortChoice == SORT_TYPE_REPUTATION) {
|
||||||
@@ -126,12 +110,26 @@ IProperty::PropertyEntranceResult MySQLDatabase::GetProperties(const IProperty::
|
|||||||
params.playerSort
|
params.playerSort
|
||||||
);
|
);
|
||||||
if (count->next()) {
|
if (count->next()) {
|
||||||
result.totalEntriesMatchingQuery = count->getUInt("count");
|
if (!result) result = IProperty::PropertyEntranceResult();
|
||||||
|
result->totalEntriesMatchingQuery = count->getUInt("count");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (properties->next()) {
|
while (properties->next()) {
|
||||||
result.entries.push_back(ReadPropertyInfo(properties));
|
if (!result) result = IProperty::PropertyEntranceResult();
|
||||||
|
auto& entry = result->entries.emplace_back();
|
||||||
|
entry.id = properties->getUInt64("id");
|
||||||
|
entry.ownerId = properties->getUInt64("owner_id");
|
||||||
|
entry.cloneId = properties->getUInt64("clone_id");
|
||||||
|
entry.name = properties->getString("name").c_str();
|
||||||
|
entry.description = properties->getString("description").c_str();
|
||||||
|
entry.privacyOption = properties->getInt("privacy_option");
|
||||||
|
entry.rejectionReason = properties->getString("rejection_reason").c_str();
|
||||||
|
entry.lastUpdatedTime = properties->getUInt("last_updated");
|
||||||
|
entry.claimedTime = properties->getUInt("time_claimed");
|
||||||
|
entry.reputation = properties->getUInt("reputation");
|
||||||
|
entry.modApproved = properties->getUInt("mod_approved");
|
||||||
|
entry.performanceCost = properties->getFloat("performance_cost");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -146,7 +144,21 @@ std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID map
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReadPropertyInfo(propertyEntry);
|
IProperty::Info toReturn;
|
||||||
|
toReturn.id = propertyEntry->getUInt64("id");
|
||||||
|
toReturn.ownerId = propertyEntry->getUInt64("owner_id");
|
||||||
|
toReturn.cloneId = propertyEntry->getUInt64("clone_id");
|
||||||
|
toReturn.name = propertyEntry->getString("name").c_str();
|
||||||
|
toReturn.description = propertyEntry->getString("description").c_str();
|
||||||
|
toReturn.privacyOption = propertyEntry->getInt("privacy_option");
|
||||||
|
toReturn.rejectionReason = propertyEntry->getString("rejection_reason").c_str();
|
||||||
|
toReturn.lastUpdatedTime = propertyEntry->getUInt("last_updated");
|
||||||
|
toReturn.claimedTime = propertyEntry->getUInt("time_claimed");
|
||||||
|
toReturn.reputation = propertyEntry->getUInt("reputation");
|
||||||
|
toReturn.modApproved = propertyEntry->getUInt("mod_approved");
|
||||||
|
toReturn.performanceCost = propertyEntry->getFloat("performance_cost");
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
void MySQLDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
||||||
@@ -183,15 +195,3 @@ void MySQLDatabase::InsertNewProperty(const IProperty::Info& info, const uint32_
|
|||||||
zoneId.GetMapID()
|
zoneId.GetMapID()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOOBJID id) {
|
|
||||||
auto propertyEntry = ExecuteSelect(
|
|
||||||
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
|
||||||
"FROM properties WHERE id = ?;", id);
|
|
||||||
|
|
||||||
if (!propertyEntry->next()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReadPropertyInfo(propertyEntry);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -64,27 +64,26 @@ void MySQLDatabase::RemoveModel(const LWOOBJID& modelId) {
|
|||||||
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IPropertyContents::Model> MySQLDatabase::GetModel(const LWOOBJID modelID) {
|
IPropertyContents::Model MySQLDatabase::GetModel(const LWOOBJID modelID) {
|
||||||
auto result = ExecuteSelect("SELECT * FROM properties_contents WHERE id = ?", modelID);
|
auto result = ExecuteSelect("SELECT * FROM properties_contents WHERE id = ?", modelID);
|
||||||
|
|
||||||
std::optional<IPropertyContents::Model> model = std::nullopt;
|
IPropertyContents::Model model{};
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
model = IPropertyContents::Model{};
|
model.id = result->getUInt64("id");
|
||||||
model->id = result->getUInt64("id");
|
model.lot = static_cast<LOT>(result->getUInt("lot"));
|
||||||
model->lot = static_cast<LOT>(result->getUInt("lot"));
|
model.position.x = result->getFloat("x");
|
||||||
model->position.x = result->getFloat("x");
|
model.position.y = result->getFloat("y");
|
||||||
model->position.y = result->getFloat("y");
|
model.position.z = result->getFloat("z");
|
||||||
model->position.z = result->getFloat("z");
|
model.rotation.w = result->getFloat("rw");
|
||||||
model->rotation.w = result->getFloat("rw");
|
model.rotation.x = result->getFloat("rx");
|
||||||
model->rotation.x = result->getFloat("rx");
|
model.rotation.y = result->getFloat("ry");
|
||||||
model->rotation.y = result->getFloat("ry");
|
model.rotation.z = result->getFloat("rz");
|
||||||
model->rotation.z = result->getFloat("rz");
|
model.ugcId = result->getUInt64("ugc_id");
|
||||||
model->ugcId = result->getUInt64("ugc_id");
|
model.behaviors[0] = result->getUInt64("behavior_1");
|
||||||
model->behaviors[0] = result->getUInt64("behavior_1");
|
model.behaviors[1] = result->getUInt64("behavior_2");
|
||||||
model->behaviors[1] = result->getUInt64("behavior_2");
|
model.behaviors[2] = result->getUInt64("behavior_3");
|
||||||
model->behaviors[2] = result->getUInt64("behavior_3");
|
model.behaviors[3] = result->getUInt64("behavior_4");
|
||||||
model->behaviors[3] = result->getUInt64("behavior_4");
|
model.behaviors[4] = result->getUInt64("behavior_5");
|
||||||
model->behaviors[4] = result->getUInt64("behavior_5");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
|
|||||||
@@ -1,17 +1,5 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
IUgc::Model ReadModel(PreparedStmtResultSet& result) {
|
|
||||||
IUgc::Model model;
|
|
||||||
|
|
||||||
// blob is owned by the query, so we need to do a deep copy :/
|
|
||||||
std::unique_ptr<std::istream> blob(result->getBlob("lxfml"));
|
|
||||||
model.lxfmlData << blob->rdbuf();
|
|
||||||
model.id = result->getUInt64("ugcID");
|
|
||||||
model.modelID = result->getUInt64("modelID");
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<IUgc::Model> MySQLDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
std::vector<IUgc::Model> MySQLDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
||||||
auto result = ExecuteSelect(
|
auto result = ExecuteSelect(
|
||||||
"SELECT lxfml, u.id as ugcID, pc.id as modelID FROM ugc AS u JOIN properties_contents AS pc ON u.id = pc.ugc_id WHERE lot = 14 AND property_id = ? AND pc.ugc_id IS NOT NULL;",
|
"SELECT lxfml, u.id as ugcID, pc.id as modelID FROM ugc AS u JOIN properties_contents AS pc ON u.id = pc.ugc_id WHERE lot = 14 AND property_id = ? AND pc.ugc_id IS NOT NULL;",
|
||||||
@@ -20,7 +8,14 @@ std::vector<IUgc::Model> MySQLDatabase::GetUgcModels(const LWOOBJID& propertyId)
|
|||||||
std::vector<IUgc::Model> toReturn;
|
std::vector<IUgc::Model> toReturn;
|
||||||
|
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
toReturn.push_back(ReadModel(result));
|
IUgc::Model model;
|
||||||
|
|
||||||
|
// blob is owned by the query, so we need to do a deep copy :/
|
||||||
|
std::unique_ptr<std::istream> blob(result->getBlob("lxfml"));
|
||||||
|
model.lxfmlData << blob->rdbuf();
|
||||||
|
model.id = result->getUInt64("ugcID");
|
||||||
|
model.modelID = result->getUInt64("modelID");
|
||||||
|
toReturn.push_back(std::move(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
@@ -32,7 +27,14 @@ std::vector<IUgc::Model> MySQLDatabase::GetAllUgcModels() {
|
|||||||
std::vector<IUgc::Model> models;
|
std::vector<IUgc::Model> models;
|
||||||
models.reserve(result->rowsCount());
|
models.reserve(result->rowsCount());
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
models.push_back(ReadModel(result));
|
IUgc::Model model;
|
||||||
|
model.id = result->getInt64("ugcID");
|
||||||
|
model.modelID = result->getUInt64("modelID");
|
||||||
|
|
||||||
|
// blob is owned by the query, so we need to do a deep copy :/
|
||||||
|
std::unique_ptr<std::istream> blob(result->getBlob("lxfml"));
|
||||||
|
model.lxfmlData << blob->rdbuf();
|
||||||
|
models.push_back(std::move(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
return models;
|
return models;
|
||||||
@@ -43,10 +45,10 @@ void MySQLDatabase::RemoveUnreferencedUgcModels() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::InsertNewUgcModel(
|
void MySQLDatabase::InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data, // cant be const sad
|
std:: stringstream& sd0Data, // cant be const sad
|
||||||
const uint64_t blueprintId,
|
const uint32_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const LWOOBJID characterId) {
|
const uint32_t characterId) {
|
||||||
const std::istream stream(sd0Data.rdbuf());
|
const std::istream stream(sd0Data.rdbuf());
|
||||||
ExecuteInsert(
|
ExecuteInsert(
|
||||||
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
||||||
@@ -69,14 +71,3 @@ void MySQLDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::stringstrea
|
|||||||
const std::istream stream(lxfml.rdbuf());
|
const std::istream stream(lxfml.rdbuf());
|
||||||
ExecuteUpdate("UPDATE ugc SET lxfml = ? WHERE id = ?;", &stream, modelId);
|
ExecuteUpdate("UPDATE ugc SET lxfml = ? WHERE id = ?;", &stream, modelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IUgc::Model> MySQLDatabase::GetUgcModel(const LWOOBJID ugcId) {
|
|
||||||
auto result = ExecuteSelect("SELECT u.id AS ugcID, lxfml, pc.id AS modelID FROM ugc AS u JOIN properties_contents AS pc ON pc.ugc_id = u.id WHERE u.id = ?", ugcId);
|
|
||||||
|
|
||||||
std::optional<IUgc::Model> toReturn = std::nullopt;
|
|
||||||
if (result->next()) {
|
|
||||||
toReturn = ReadModel(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
void MySQLDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) {
|
void MySQLDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) {
|
||||||
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
|
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,13 +61,13 @@ bool SQLiteDatabase::GetAutoCommit() {
|
|||||||
|
|
||||||
void SQLiteDatabase::SetAutoCommit(bool value) {
|
void SQLiteDatabase::SetAutoCommit(bool value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
if (!GetAutoCommit()) con->compileStatement("COMMIT;").execDML();
|
|
||||||
} else {
|
|
||||||
if (GetAutoCommit()) con->compileStatement("BEGIN;").execDML();
|
if (GetAutoCommit()) con->compileStatement("BEGIN;").execDML();
|
||||||
|
} else {
|
||||||
|
if (!GetAutoCommit()) con->compileStatement("COMMIT;").execDML();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::DeleteCharacter(const LWOOBJID characterId) {
|
void SQLiteDatabase::DeleteCharacter(const uint32_t characterId) {
|
||||||
ExecuteDelete("DELETE FROM charxml WHERE id=?;", characterId);
|
ExecuteDelete("DELETE FROM charxml WHERE id=?;", characterId);
|
||||||
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
||||||
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
||||||
|
|||||||
@@ -38,31 +38,31 @@ public:
|
|||||||
|
|
||||||
std::vector<std::string> GetApprovedCharacterNames() override;
|
std::vector<std::string> GetApprovedCharacterNames() override;
|
||||||
|
|
||||||
std::vector<FriendData> GetFriendsList(LWOOBJID charID) override;
|
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) override;
|
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
||||||
void SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) override;
|
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
||||||
void AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||||
void RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||||
void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
||||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
||||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
std::vector<IUgc::Model> GetAllUgcModels() override;
|
||||||
void CreateMigrationHistoryTable() override;
|
void CreateMigrationHistoryTable() override;
|
||||||
bool IsMigrationRun(const std::string_view str) override;
|
bool IsMigrationRun(const std::string_view str) override;
|
||||||
void InsertMigration(const std::string_view str) override;
|
void InsertMigration(const std::string_view str) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
||||||
std::string GetCharacterXml(const LWOOBJID accountId) override;
|
std::string GetCharacterXml(const uint32_t accountId) override;
|
||||||
void UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) override;
|
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
||||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||||
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
||||||
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
||||||
void DeleteCharacter(const LWOOBJID characterId) override;
|
void DeleteCharacter(const uint32_t characterId) override;
|
||||||
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||||
void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||||
void UpdateLastLoggedInCharacter(const LWOOBJID characterId) override;
|
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
||||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
||||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
||||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
||||||
@@ -81,53 +81,51 @@ public:
|
|||||||
void InsertNewMail(const MailInfo& mail) override;
|
void InsertNewMail(const MailInfo& mail) override;
|
||||||
void InsertNewUgcModel(
|
void InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data,
|
std::stringstream& sd0Data,
|
||||||
const uint64_t blueprintId,
|
const uint32_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const LWOOBJID characterId) override;
|
const uint32_t characterId) override;
|
||||||
std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) override;
|
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||||
uint32_t GetUnreadMailCount(const LWOOBJID characterId) override;
|
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
||||||
void MarkMailRead(const uint64_t mailId) override;
|
void MarkMailRead(const uint64_t mailId) override;
|
||||||
void DeleteMail(const uint64_t mailId) override;
|
void DeleteMail(const uint64_t mailId) override;
|
||||||
void ClaimMailItem(const uint64_t mailId) override;
|
void ClaimMailItem(const uint64_t mailId) override;
|
||||||
void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) override;
|
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
||||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||||
std::optional<uint64_t> GetCurrentPersistentId() override;
|
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||||
IObjectIdTracker::Range GetPersistentIdRange() override;
|
|
||||||
void InsertDefaultPersistentId() override;
|
void InsertDefaultPersistentId() override;
|
||||||
|
void UpdatePersistentId(const uint32_t id) override;
|
||||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||||
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||||
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||||
std::vector<IIgnoreList::Info> GetIgnoreList(const LWOOBJID playerId) override;
|
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
||||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||||
void AddBehavior(const IBehaviors::Info& info) override;
|
void AddBehavior(const IBehaviors::Info& info) override;
|
||||||
std::string GetBehavior(const LWOOBJID behaviorId) override;
|
std::string GetBehavior(const LWOOBJID behaviorId) override;
|
||||||
void RemoveBehavior(const LWOOBJID characterId) override;
|
void RemoveBehavior(const LWOOBJID characterId) override;
|
||||||
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
||||||
IProperty::PropertyEntranceResult GetProperties(const IProperty::PropertyLookup& params) override;
|
std::optional<IProperty::PropertyEntranceResult> GetProperties(const IProperty::PropertyLookup& params) override;
|
||||||
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetDescendingLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
||||||
void SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override;
|
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||||
void UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override;
|
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||||
std::optional<ILeaderboard::Score> GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) override;
|
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
||||||
void IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) override;
|
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
||||||
void IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) override;
|
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
||||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override;
|
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
||||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||||
uint32_t GetAccountCount() override;
|
uint32_t GetAccountCount() override;
|
||||||
bool IsNameInUse(const std::string_view name) override;
|
bool IsNameInUse(const std::string_view name) override;
|
||||||
std::optional<IPropertyContents::Model> GetModel(const LWOOBJID modelID) override;
|
IPropertyContents::Model GetModel(const LWOOBJID modelID) override;
|
||||||
std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) override;
|
|
||||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) override;
|
|
||||||
private:
|
private:
|
||||||
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
|
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
|
||||||
|
|
||||||
@@ -170,91 +168,91 @@ private:
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::string_view param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const std::string_view param) {
|
||||||
LOG_DEBUG("%s", param.data());
|
LOG("%s", param.data());
|
||||||
stmt.bind(index, param.data());
|
stmt.bind(index, param.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const char* param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const char* param) {
|
||||||
LOG_DEBUG("%s", param);
|
LOG("%s", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::string param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const std::string param) {
|
||||||
LOG_DEBUG("%s", param.c_str());
|
LOG("%s", param.c_str());
|
||||||
stmt.bind(index, param.c_str());
|
stmt.bind(index, param.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int8_t param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const int8_t param) {
|
||||||
LOG_DEBUG("%u", param);
|
LOG("%u", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint8_t param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const uint8_t param) {
|
||||||
LOG_DEBUG("%d", param);
|
LOG("%d", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int16_t param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const int16_t param) {
|
||||||
LOG_DEBUG("%u", param);
|
LOG("%u", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint16_t param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const uint16_t param) {
|
||||||
LOG_DEBUG("%d", param);
|
LOG("%d", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint32_t param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const uint32_t param) {
|
||||||
LOG_DEBUG("%u", param);
|
LOG("%u", param);
|
||||||
stmt.bind(index, static_cast<int32_t>(param));
|
stmt.bind(index, static_cast<int32_t>(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int32_t param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const int32_t param) {
|
||||||
LOG_DEBUG("%d", param);
|
LOG("%d", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const int64_t param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const int64_t param) {
|
||||||
LOG_DEBUG("%llu", param);
|
LOG("%llu", param);
|
||||||
stmt.bind(index, static_cast<sqlite_int64>(param));
|
stmt.bind(index, static_cast<sqlite_int64>(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const uint64_t param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const uint64_t param) {
|
||||||
LOG_DEBUG("%llu", param);
|
LOG("%llu", param);
|
||||||
stmt.bind(index, static_cast<sqlite_int64>(param));
|
stmt.bind(index, static_cast<sqlite_int64>(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const float param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const float param) {
|
||||||
LOG_DEBUG("%f", param);
|
LOG("%f", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const double param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const double param) {
|
||||||
LOG_DEBUG("%f", param);
|
LOG("%f", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const bool param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const bool param) {
|
||||||
LOG_DEBUG("%d", param);
|
LOG("%d", param);
|
||||||
stmt.bind(index, param);
|
stmt.bind(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::istream* param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const std::istream* param) {
|
||||||
LOG_DEBUG("Blob");
|
LOG("Blob");
|
||||||
// This is the one time you will ever see me use const_cast.
|
// This is the one time you will ever see me use const_cast.
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
stream << param->rdbuf();
|
stream << param->rdbuf();
|
||||||
@@ -264,21 +262,10 @@ inline void SetParam(PreppedStmtRef stmt, const int index, const std::istream* p
|
|||||||
template<>
|
template<>
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
inline void SetParam(PreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
||||||
if (param) {
|
if (param) {
|
||||||
LOG_DEBUG("%d", param.value());
|
LOG("%d", param.value());
|
||||||
stmt.bind(index, static_cast<int>(param.value()));
|
stmt.bind(index, static_cast<int>(param.value()));
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG("Null");
|
LOG("Null");
|
||||||
stmt.bindNull(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void SetParam(PreppedStmtRef stmt, const int index, const std::optional<LWOOBJID> param) {
|
|
||||||
if (param) {
|
|
||||||
LOG_DEBUG("%d", param.value());
|
|
||||||
stmt.bind(index, static_cast<sqlite_int64>(param.value()));
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG("Null");
|
|
||||||
stmt.bindNull(index);
|
stmt.bindNull(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
void SQLiteDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||||
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
||||||
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(CppSQLite3Query stmt) {
|
|||||||
|
|
||||||
ICharInfo::Info toReturn;
|
ICharInfo::Info toReturn;
|
||||||
|
|
||||||
toReturn.id = stmt.getInt64Field("id");
|
toReturn.id = stmt.getIntField("id");
|
||||||
toReturn.name = stmt.getStringField("name");
|
toReturn.name = stmt.getStringField("name");
|
||||||
toReturn.pendingName = stmt.getStringField("pending_name");
|
toReturn.pendingName = stmt.getStringField("pending_name");
|
||||||
toReturn.needsRename = stmt.getIntField("needs_rename");
|
toReturn.needsRename = stmt.getIntField("needs_rename");
|
||||||
@@ -31,7 +31,7 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(CppSQLite3Query stmt) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const LWOOBJID charId) {
|
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const uint32_t charId) {
|
||||||
return CharInfoFromQueryResult(
|
return CharInfoFromQueryResult(
|
||||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId).second
|
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId).second
|
||||||
);
|
);
|
||||||
@@ -43,12 +43,12 @@ std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const std::strin
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LWOOBJID> SQLiteDatabase::GetAccountCharacterIds(const LWOOBJID accountId) {
|
std::vector<uint32_t> SQLiteDatabase::GetAccountCharacterIds(const uint32_t accountId) {
|
||||||
auto [_, result] = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
auto [_, result] = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
||||||
|
|
||||||
std::vector<LWOOBJID> toReturn;
|
std::vector<uint32_t> toReturn;
|
||||||
while (!result.eof()) {
|
while (!result.eof()) {
|
||||||
toReturn.push_back(result.getInt64Field("id"));
|
toReturn.push_back(result.getIntField("id"));
|
||||||
result.nextRow();
|
result.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,15 +66,15 @@ void SQLiteDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
|||||||
static_cast<uint32_t>(time(NULL)));
|
static_cast<uint32_t>(time(NULL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::SetCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
void SQLiteDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
void SQLiteDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateLastLoggedInCharacter(const LWOOBJID characterId) {
|
void SQLiteDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ?;", static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ?;", static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
std::string SQLiteDatabase::GetCharacterXml(const LWOOBJID charId) {
|
std::string SQLiteDatabase::GetCharacterXml(const uint32_t charId) {
|
||||||
auto [_, result] = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
auto [_, result] = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
||||||
|
|
||||||
if (result.eof()) {
|
if (result.eof()) {
|
||||||
@@ -10,10 +10,10 @@ std::string SQLiteDatabase::GetCharacterXml(const LWOOBJID charId) {
|
|||||||
return result.getStringField("xml_data");
|
return result.getStringField("xml_data");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) {
|
void SQLiteDatabase::UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) {
|
||||||
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
void SQLiteDatabase::InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
||||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
void SQLiteDatabase::InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) {
|
void SQLiteDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
||||||
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user