diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..46c26b03 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,109 @@ +#Original at https://github.com/Source2ZE/CS2Fixes/blob/main/.github/workflows/build.yml +name: CI + +on: + push: + tags: + - '*' + branches: + - main + paths-ignore: + - LICENSE + - README.md + - 'configs**' + - '**.sln' + - '**.vcxproj**' + pull_request: + paths-ignore: + - LICENSE + - README.md + - 'configs**' + - '**.sln' + - '**.vcxproj**' + +jobs: + build: + name: Build + runs-on: ${{ matrix.os }} + env: + HL2SDKCS2: ${{ github.workspace }}/mm-cs2-scrim/sdk + container: ${{ matrix.container }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + include: + - os: windows-latest + - os: ubuntu-latest + container: registry.gitlab.steamos.cloud/steamrt/sniper/sdk + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + path: mm-cs2-scrim + submodules: recursive + + - name: Checkout Metamod + uses: actions/checkout@v4 + with: + repository: alliedmodders/metamod-source + ref: master + path: mmsource-2.0 + submodules: recursive + + - name: Checkout AMBuild + uses: actions/checkout@v4 + with: + repository: alliedmodders/ambuild + path: ambuild + + - name: Install AMBuild + run: | + cd ambuild && python setup.py install && cd .. + + - name: Build + working-directory: mm-cs2-scrim + shell: bash + run: | + mkdir build && cd build + python ../configure.py --enable-optimize --symbol-files --sdks cs2 + ambuild + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ runner.os }} + path: mm-cs2-scrim/build/package + + release: + name: Release + if: startsWith(github.ref, 'refs/tags/') + needs: build + runs-on: ubuntu-latest + + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + + - name: Package + run: | + version=`echo $GITHUB_REF | sed "s/refs\/tags\///"` + ls -Rall + if [ -d "./Linux/" ]; then + cd ./Linux/ + tar -czf ../${{ github.event.repository.name }}-${version}-linux.tar.gz * + cd - + fi + if [ -d "./Windows/" ]; then + cd ./Windows/ + zip -r ../${{ github.event.repository.name }}-${version}-windows.zip * + cd - + fi + + - name: Release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ github.event.repository.name }}-* + tag: ${{ github.ref }} + file_glob: true \ No newline at end of file diff --git a/.github/workflows/compile-metamod-addon.yaml b/.github/workflows/compile-metamod-addon.yaml index 272dad29..f112c7ef 100644 --- a/.github/workflows/compile-metamod-addon.yaml +++ b/.github/workflows/compile-metamod-addon.yaml @@ -4,14 +4,15 @@ on: - pull_request env: - HL2SDKCS2: /home/runner/work/mm-cs2-scrim/mm-cs2-scrim/sdk - MMSOURCE_DEV: /home/runner/work/mm-cs2-scrim/mm-cs2-scrim/metamod-source + HL2SDKCS2: /__w/mm-cs2-scrim/mm-cs2-scrim/sdk + MMSOURCE_DEV: /__w/mm-cs2-scrim/mm-cs2-scrim/metamod-source CC: clang CXX: clang++ jobs: build: runs-on: ubuntu-latest + container: registry.gitlab.steamos.cloud/steamrt/sniper/sdk steps: - name: Checkout @@ -42,7 +43,7 @@ jobs: ls -la - name: Update submodules run: | - cd /home/runner/work/mm-cs2-scrim/mm-cs2-scrim/metamod-source + cd metamod-source git submodule update --recursive - name: Compile @@ -57,9 +58,9 @@ jobs: sudo apt-get install python3 -y sudo apt-get install gcc -y echo --- - cd /home/runner/work/mm-cs2-scrim/mm-cs2-scrim/ambuild && sudo python3 ./setup.py install + cd ambuild && sudo python3 ./setup.py install ls -la - cd /home/runner/work/mm-cs2-scrim/mm-cs2-scrim + cd ../ ls -la - mkdir build && cd build && python3 ../configure.py --enable-optimize --symbol-files --sdks cs2 + mkdir build && cd build && python3 ../configure.py --sdks cs2 --targets x86_64 ambuild \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7c4dc0ae..0d6e7d75 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -[Dd]ebug/ +/[Dd]ebug/ [Dd]ebugPublic/ -[Rr]elease/ +/[Rr]elease/ [Rr]eleases/ [Pp]ublish/ [Pp]roperties/ diff --git a/AMBuildScript b/AMBuildScript index 005d9333..d17845a9 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -278,7 +278,6 @@ class MMSPluginConfig(object): cxx.linkflags += ['/NODEFAULTLIB:libcmt'] else: cxx.cflags += ['/MT'] - cxx.linkflags += ['/NODEFAULTLIB:libcmt'] cxx.defines += [ '_CRT_SECURE_NO_DEPRECATE', '_CRT_SECURE_NO_WARNINGS', @@ -470,8 +469,7 @@ class MMSPluginConfig(object): else: compiler.postlink += [os.path.join(lib_folder, 'interfaces_i486.a')] - if sdk.name == 'bms': - compiler.postlink += [os.path.join(lib_folder, 'mathlib.a')] + compiler.postlink += [os.path.join(lib_folder, 'mathlib.a')] binary = self.Library(compiler, name) compiler = binary.compiler diff --git a/AMBuilder b/AMBuilder index f9d387bd..836542c3 100644 --- a/AMBuilder +++ b/AMBuilder @@ -26,21 +26,26 @@ for sdk_name in MMSPlugin.sdks: os.path.join(builder.sourcePath, 'vendor', 'subhook'), os.path.join(builder.sourcePath, 'vendor', 'funchook', 'include'), os.path.join(builder.sourcePath, 'vendor', 'protobuf-3.21.8', 'src'), + os.path.join(builder.sourcePath, 'protobuf', 'generated'), ] + target_folder = 'Debug' if builder.options.debug else 'Release' + target_protobuf = 'libprotobufd' if builder.options.debug else 'libprotobuf' + if binary.compiler.target.platform == 'linux': binary.compiler.postlink += [ - os.path.join(builder.sourcePath, 'vendor', 'funchook', 'lib', 'libfunchook.a'), - os.path.join(builder.sourcePath, 'vendor', 'funchook', 'lib', 'libdistorm.a'), - os.path.join(builder.sourcePath, 'vendor', 'protobuf-lib', 'libprotobuf.a'), + os.path.join(builder.sourcePath, 'vendor', 'funchook', 'lib', target_folder, 'libfunchook.a'), + os.path.join(builder.sourcePath, 'vendor', 'funchook', 'lib', target_folder, 'libdistorm.a'), + os.path.join(builder.sourcePath, 'vendor', 'protobuf-lib', target_folder, target_protobuf + '.a'), ] binary.sources += ['src/utils/plat_unix.cpp'] elif binary.compiler.target.platform == 'windows': binary.compiler.postlink += [ os.path.join('psapi.lib'), - os.path.join(builder.sourcePath, 'vendor', 'funchook', 'lib', 'funchook.lib'), - os.path.join(builder.sourcePath, 'vendor', 'funchook', 'lib', 'distorm.lib'), - os.path.join(builder.sourcePath, 'vendor', 'protobuf-lib', 'libprotobuf.lib'), + os.path.join(builder.sourcePath, 'vendor', 'funchook', 'lib', target_folder, 'funchook.lib'), + os.path.join(builder.sourcePath, 'vendor', 'funchook', 'lib', target_folder, 'distorm.lib'), + os.path.join(builder.sourcePath, 'vendor', 'protobuf-lib', target_folder, target_protobuf + '.lib'), + os.path.join(builder.sourcePath, 'sdk', 'lib', 'public', 'win64', 'steam_api64.lib') ] binary.sources += ['src/utils/plat_win.cpp'] @@ -48,27 +53,33 @@ for sdk_name in MMSPlugin.sdks: binary.sources += [ 'src/cs2fixes.cpp', 'src/mempatch.cpp', - 'src/patches.cpp', 'src/cvars.cpp', - 'src/adminsystem.cpp', + 'src/adminsystem.cpp', 'src/commands.cpp', 'src/addresses.cpp', 'src/detours.cpp', 'src/events.cpp', 'src/utils/entity.cpp', 'src/cs2_sdk/schema.cpp', - 'src/cs2_sdk/interfaces/cs2_interfaces.cpp', - 'src/cs2_sdk/interfaces/centitysystem.cpp', 'src/ctimer.cpp', 'src/playermanager.cpp', 'src/gameconfig.cpp', + 'src/gamesystem.cpp', + 'src/entitylistener.cpp', ] if sdk_name in ['dota', 'cs2']: binary.sources += [ + os.path.join(sdk.path, 'entity2', 'entitysystem.cpp'), + os.path.join(sdk.path, 'entity2', 'entityidentity.cpp'), + os.path.join(sdk.path, 'entity2', 'entitykeyvalues.cpp'), os.path.join(sdk.path, 'tier1', 'convar.cpp'), - os.path.join(sdk.path, 'tier1', 'generichash.cpp'), - os.path.join(sdk.path, 'public', 'tier0', 'memoverride.cpp'), + os.path.join(sdk.path, 'tier1', 'keyvalues3.cpp'), + ] + + if sdk_name in ['dota', 'cs2'] and (binary.compiler.target.platform == 'windows' and builder.options.debug != '1') or binary.compiler.target.platform == 'linux': + binary.sources += [ + os.path.join(sdk.path, 'public', 'tier0', 'memoverride.cpp') ] if cxx.target.arch == 'x86': diff --git a/CFGs/cs2scrim/cs2scrim.cfg b/CFGs/cs2scrim/cs2scrim.cfg new file mode 100644 index 00000000..f6e39be5 --- /dev/null +++ b/CFGs/cs2scrim/cs2scrim.cfg @@ -0,0 +1,19 @@ +// cvars for cs2scrim plugin +// you can enable/disable features from this config file +// by default all the features are enabled internally + +//console command | Value | Chat command +cs2scrim_coach 1 //.coach +cs2scrim_pracc 1 //.pracc +cs2scrim_scrim 1 //.scrim +cs2scrim_demo 1 //.record .stoprecord +cs2scrim_restore 1 //.restore +cs2scrim_rcon 1 //.rcon +cs2scrim_pause 1 //.pause .unpause +cs2scrim_practice_spawn 1 //.spawn +cs2scrim_admin_ban 1 //.ban +cs2scrim_admin_kick 1 //.kick +cs2scrim_admin_gag 1 //.gag +cs2scrim_admin_slay 1 //.slay +cs2scrim_admin_teleport 1 //.goto +cs2scrim_admin_team 1 //.setteam diff --git a/CFGs/gotvcfg.cfg b/CFGs/gotvcfg.cfg index 659bcd1b..556efe8c 100644 --- a/CFGs/gotvcfg.cfg +++ b/CFGs/gotvcfg.cfg @@ -1,24 +1,24 @@ sv_hibernate_postgame_delay 180 -tv_allow_camera_man 1 // Auto director allows spectators to become camera man +tv_allow_camera_man 0 // Auto director allows spectators to become camera man tv_allow_static_shots 1 // Auto director uses fixed level cameras for shots tv_autorecord 0 // Automatically records all games as GOTV demos. tv_chatgroupsize 0 // Set the default chat group size tv_chattimelimit 8 // Limits spectators to chat only every n seconds tv_debug 0 // GOTV debug info. -tv_delaymapchange 1 // Delays map change until broadcast is complete -tv_deltacache 2 // Enable delta entity bit stream cache +tv_delaymapchange 0 // Delays map change until broadcast is complete +tv_deltacache 0 // Enable delta entity bit stream cache tv_dispatchmode 1 // Dispatch clients to relay proxies: 0=never, 1=if appropriate, 2=always tv_enable 1 // Activates GOTV on server. -tv_maxclients 10 // Maximum client number on GOTV server. -tv_maxrate 20000 // Max GOTV spectator bandwidth rate allowed, 0 == unlimited +tv_maxclients 1 // Maximum client number on GOTV server. +tv_maxrate 0 // Max GOTV spectator bandwidth rate allowed, 0 == unlimited tv_name "CS2Scrim - GOTV" // GOTV host name tv_overridemaster 0 // Overrides the GOTV master root address. tv_port 27016 // Host SourceTV port tv_relaypassword schmetterling // GOTV password for relay proxies tv_relayvoice 0 // Relay voice data: 0=off, 1=on tv_snapshotrate 128 // Snapshots broadcasted per second -tv_timeout 30 // GOTV connection timeout in seconds. +tv_timeout 15 // GOTV connection timeout in seconds. tv_title "CS2Scrim - GOTV" // Set title for GOTV spectator UI tv_transmitall 1 // Transmit all entities (not only director view) diff --git a/CFGs/pracc.cfg b/CFGs/pracc.cfg index e23f79d1..fdde274e 100644 --- a/CFGs/pracc.cfg +++ b/CFGs/pracc.cfg @@ -50,4 +50,5 @@ sv_grenade_trajectory_prac_pipreview 1 buddha_reset_hp 100 buddha 1 -say "Practice CFG Mode loaded" \ No newline at end of file +say "Practice CFG loaded" +say "by ρλd" \ No newline at end of file diff --git a/CFGs/scrim.cfg b/CFGs/scrim.cfg index fb216316..d519b311 100644 --- a/CFGs/scrim.cfg +++ b/CFGs/scrim.cfg @@ -4,8 +4,10 @@ mp_autokick 0 mp_match_can_clinch 0 mp_freezetime 20 +mp_warmup_end mp_restartgame 1 cash_team_bonus_shorthanded 0 -say mr24 loaded \ No newline at end of file +say "Competitive MR24 loaded" +say "by ρλd" \ No newline at end of file diff --git a/CS2Fixes.vcxproj b/CS2Fixes.vcxproj index d04ccd57..32faff61 100644 --- a/CS2Fixes.vcxproj +++ b/CS2Fixes.vcxproj @@ -1,4 +1,4 @@ - + @@ -124,15 +124,17 @@ NotUsing pch.h stdcpp20 - src/utils;src/cs2_sdk;sdk/public;sdk/public/tier0;sdk/game/shared;sdk/game/server;sdk/public/tier1;minhook/include;$(MMSOURCE112)/core;$(MMSOURCE112)/core/sourcehook;vendor/subhook;vendor/funchook/include;sdk/public/entity2;sdk/public/game/server;vendor/protobuf-3.21.8/src;$(SolutionDir);%(AdditionalIncludeDirectories) + protobuf/generated;src/utils;src/cs2_sdk;sdk/public;sdk/public/tier0;sdk/game/shared;sdk/game/server;sdk/public/tier1;sdk/public/mathlib;minhook/include;$(MMSOURCE112)/core;$(MMSOURCE112)/core/sourcehook;vendor/subhook;vendor/funchook/include;sdk/public/entity2;sdk/public/game/server;vendor/protobuf-3.21.8/src;$(SolutionDir);%(AdditionalIncludeDirectories) %(UndefinePreprocessorDefinitions) + MultiThreadedDebug + true Windows true false - interfaces.lib;tier0.lib;tier1.lib;psapi.lib;funchook.lib;distorm.lib;vendor/protobuf-lib/libprotobuf.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) - sdk/lib/public/win64;%(AdditionalLibraryDirectories) + interfaces.lib;mathlib.lib;tier0.lib;tier1.lib;psapi.lib;funchook.lib;distorm.lib;steam_api64.lib;vendor/protobuf-lib/Debug/libprotobufd.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + sdk/lib/public/win64;vendor/funchook/lib/Debug;%(AdditionalLibraryDirectories) @@ -148,9 +150,10 @@ NotUsing pch.h stdcpp20 - src/utils;src/cs2_sdk;sdk/public;sdk/public/tier0;sdk/game/shared;sdk/game/server;sdk/public/tier1;minhook/include;$(MMSOURCE112)/core;$(MMSOURCE112)/core/sourcehook;vendor/subhook;vendor/funchook/include;sdk/public/entity2;sdk/public/game/server;vendor/protobuf-3.21.8/src;$(SolutionDir);%(AdditionalIncludeDirectories) + protobuf/generated;src/utils;src/cs2_sdk;sdk/public;sdk/public/tier0;sdk/game/shared;sdk/game/server;sdk/public/tier1;sdk/public/mathlib;minhook/include;$(MMSOURCE112)/core;$(MMSOURCE112)/core/sourcehook;vendor/subhook;vendor/funchook/include;sdk/public/entity2;sdk/public/game/server;vendor/protobuf-3.21.8/src;$(SolutionDir);%(AdditionalIncludeDirectories) MultiThreaded %(UndefinePreprocessorDefinitions) + true Windows @@ -158,29 +161,39 @@ true true false - interfaces.lib;tier0.lib;tier1.lib;psapi.lib;funchook.lib;distorm.lib;vendor/protobuf-lib/libprotobuf.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) - sdk/lib/public/win64;vendor/funchook/lib;%(AdditionalLibraryDirectories) + interfaces.lib;mathlib.lib;tier0.lib;tier1.lib;psapi.lib;funchook.lib;distorm.lib;steam_api64.lib;vendor/protobuf-lib/Release/libprotobuf.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + sdk/lib/public/win64;vendor/funchook/lib/Release;%(AdditionalLibraryDirectories) - + + + + + - - + + + + + + + + @@ -191,6 +204,7 @@ + @@ -198,22 +212,31 @@ - - + + + + + - - - + + + + + + + + + diff --git a/CS2Fixes.vcxproj.filters b/CS2Fixes.vcxproj.filters index 7e2e08bb..b3d06fe3 100644 --- a/CS2Fixes.vcxproj.filters +++ b/CS2Fixes.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -12,15 +12,9 @@ {65f1f5a2-6411-4f21-9255-37d1b9e5b449} - - {904ca200-d5b9-430e-9eff-66ebfe1cdccc} - {70b0b6c3-5a23-41ae-a865-ed4a40a45e1a} - - {b61ccd3e-b790-406a-ac1f-f4bb89286896} - {184daee7-8d1e-48eb-9b2c-159792ecff61} @@ -33,6 +27,9 @@ {4e7c9b65-faee-46b5-b610-9717f232a17c} + + {e1906f3f-9ee2-40df-a4d2-00ee0358b050} + @@ -44,12 +41,6 @@ Source Files - - Source Files - - - Source Files\cs2_sdk\interfaces - Source Files @@ -65,9 +56,6 @@ Source Files\utils - - Source Files\cs2_sdk\interfaces - Source Files @@ -84,7 +72,7 @@ Source Files - Source Files\cs2_sdk\entity + Source Files\utils Source Files @@ -92,6 +80,45 @@ Source Files + + Source Files\sdk + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\sdk + + + Source Files\sdk + + + Source Files + + + Source Files + + + Source Files + + + Source Files\sdk + + + Source Files\sdk + @@ -100,12 +127,6 @@ Header Files - - Header Files\cs2_sdk\interfaces - - - Header Files\cs2_sdk\interfaces - Header Files\cs2_sdk\entity @@ -115,9 +136,6 @@ Header Files\utils - - Header Files\cs2_sdk\interfaces - Header Files\utils @@ -142,12 +160,6 @@ Header Files\cs2_sdk\entity - - Header Files\cs2_sdk\entity - - - Header Files\cs2_sdk\entity - Header Files\cs2_sdk\entity @@ -175,9 +187,6 @@ Header Files - - Header Files - Header Files @@ -187,5 +196,50 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files\cs2_sdk\entity + + + Header Files\cs2_sdk\entity + + + Header Files\utils + + + Header Files\cs2_sdk\entity + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\cs2_sdk\entity + + + Header Files\cs2_sdk\entity + \ No newline at end of file diff --git a/PackageScript b/PackageScript index 6bfe5d90..47025358 100644 --- a/PackageScript +++ b/PackageScript @@ -50,7 +50,26 @@ with open(os.path.join(builder.buildPath, 'pdblog.txt'), 'wt') as fp: # Add CS2Fixes-specific files builder.AddFolder(os.path.join('addons', MMSPlugin.plugin_name, 'data')) +builder.AddFolder(os.path.join('gotv')) configs_folder = builder.AddFolder(os.path.join('addons', MMSPlugin.plugin_name, 'configs')) +zr_folder = builder.AddFolder(os.path.join('addons', MMSPlugin.plugin_name, 'configs', 'zr')) +cfg_folder = builder.AddFolder(os.path.join('cfg', MMSPlugin.plugin_name)) +mapcfg_folder = builder.AddFolder(os.path.join('cfg', MMSPlugin.plugin_name, 'maps')) gamedata_folder = builder.AddFolder(os.path.join('addons', MMSPlugin.plugin_name, 'gamedata')) +cs2scrim_cfg_folder = builder.AddFolder(os.path.join('cfg', MMSPlugin.plugin_name)) +cfg_folder = builder.AddFolder(os.path.join('cfg')) builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'admins.cfg'), configs_folder) +builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'admins.cfg.example'), configs_folder) +#builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'discordbots.cfg.example'), configs_folder) +#builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'maplist.cfg.example'), configs_folder) +#builder.AddCopy(os.path.join(builder.sourcePath, 'cfg', MMSPlugin.plugin_name, 'cs2fixes.cfg'), cfg_folder) +#builder.AddCopy(os.path.join(builder.sourcePath, 'cfg', MMSPlugin.plugin_name, 'maps', 'de_somemap.cfg'), mapcfg_folder) +#builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'zr', 'playerclass.cfg.example'), zr_folder) +#builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'zr', 'weapons.cfg.example'), zr_folder) builder.AddCopy(os.path.join('gamedata', 'cs2fixes.games.txt'), gamedata_folder) +builder.AddCopy(os.path.join(builder.sourcePath, 'CFGs', MMSPlugin.plugin_name, 'cs2scrim.cfg'), cs2scrim_cfg_folder) +builder.AddCopy(os.path.join(builder.sourcePath, 'CFGs', 'gotvcfg.cfg'), cfg_folder) +builder.AddCopy(os.path.join(builder.sourcePath, 'CFGs', 'pracc.cfg'), cfg_folder) +builder.AddCopy(os.path.join(builder.sourcePath, 'CFGs', 'unpracc.cfg'), cfg_folder) +builder.AddCopy(os.path.join(builder.sourcePath, 'CFGs', 'scrim.cfg'), cfg_folder) + diff --git a/README.md b/README.md index b4bce013..1dc711e0 100644 --- a/README.md +++ b/README.md @@ -17,27 +17,35 @@ Copy the content of the file https://github.com/marqdevx/mm-cs2-scrim/blob/main/ # Addon information This plugin adds the minimum requirements for competitive teams that need a more handy way of managing a few commands from the server side, like config management or replay recording. +The plugin has been developed with these ideas in mind: +1. Minimum impact on the server performance +2. Built for competitive teams to practice (not for tournaments) + ## Available Commands * Config and server management (Admin only) `.pracc`: launch the practice config `.scrim`: start the competitive match `.map `: change the map (example: `.map ancient`) + `.rcon `: workaround to be used as the old rcon, execute commands from server side. Usage on the console `c_rcon ` * Scrim commands `.pause`: pauses the match `.unpause`: request the unpause * Coach - `.coach`: switch to coach + `.coach`: switch to coach, also available `.coach ` `.uncoach`: return as a player * Admin only `.record`: start the demo recording - `.stoprecord`: finish the recording and save it under `gotv/.dem` + `.stoprecord`: finish the recording and save it under `gotv/.dem` example: `gotv/03March_20-08_de_anubis.dem` `.restore `: load the desired round's backup `.forceunpause`: force the unpause * Practice commands - `.spawn`: move to the desired competitive spawn i.e `.spawn 2` + `.spawn`: move to the desired competitive spawn i.e `.spawn 2` or `.spawn 1 ct` + `.last`: teleports to your latest thrown grenade lineup + `.noflash`: toggle flash effect + `.ct`, `.t`, `.spec`, `.side`: switch team side * Leveraged from [CS2Fixes](https://github.com/Source2ZE/CS2Fixes/) `c_reload_admins`: console command to reload admins.cfg @@ -52,45 +60,72 @@ This plugin adds the minimum requirements for competitive teams that need a more ## Roadmap - Scrim - [X] Pauses - - [X] Medic (round backup) + - [X] Medic (round backup/restore) - [X] Coach - [X] gotv .record - [X] include date and time - - [ ] include map name + - [X] include map name + - [X] Automatically - [ ] Damage print on round-end - Practice - Maps - [X] Map - [X] Spawns - [X] Only show competitive spawns - - Utility + - Utility (grenades) + - Flashes + - [X] No flash effect + - [X] Flashed targets and time flashed - [ ] Remove smokes - [ ] Rethrow - [ ] Throw information (air-time, bounces...) + - [X] Flash target and time - [ ] Save throws and lineups + - [X] Last - Misc - - [ ] Move to spec + - [X] Move to spec or team side - [X] Noclip - - [ ] No flash effect - [ ] Create a "menu" workaround, using shoot and reload feedback for example, to confirm or cancel + - [X] Damage information - BOTs management - [ ] Place - [ ] Boost - - [ ] Util and damage feedback +- General + - [X] rcon > I'll try to documentate everything as better as possible, feel free to leave suggestions! + +## Installation instructions + +[![Set up video](https://img.youtube.com/vi/thk78MDsQnc/0.jpg)]([https://www.youtube.com/watch?v=YOUTUBE_VIDEO_ID_HERE](https://www.youtube.com/watch?v=thk78MDsQnc)) +Set up video: https://www.youtube.com/watch?v=thk78MDsQnc + +### cs2scrim config +You can enable/disable the features of the plugin by changing the values at `/game/csgo/cfg/cs2scrim/cs2scrim.cfg` + ## Compilation ### Requirements -- [Metamod:Source](https://www.sourcemm.net/downloads.php/?branch=master) (build 1219 or higher) +- [Metamod:Source](https://www.sourcemm.net/downloads.php/?branch=master) (build 1282 or higher) - [AMBuild](https://wiki.alliedmods.net/Ambuild) -### Instructions -[![Set up video](https://img.youtube.com/vi/thk78MDsQnc/0.jpg)]([https://www.youtube.com/watch?v=YOUTUBE_VIDEO_ID_HERE](https://www.youtube.com/watch?v=thk78MDsQnc)) -Set up video: https://www.youtube.com/watch?v=thk78MDsQnc +## Credits -## Authors from the [original repository](https://github.com/Source2ZE/CS2Fixes/) +### Authors from CS2Fixes +[original repository](https://github.com/Source2ZE/CS2Fixes/) - [@xen-000](https://github.com/xen-000) - [@poggicek](https://github.com/poggicek) + +This people did the hard work, and keep doing it adding features to CS2Fixes, check them out (they also made the zombie reborn innit). +I contacted Xen through discord before releasing this repository and he gave me some suggestions and approval to release it within their license, thanks! + +### Splewis +Almost all of the features are originally from the CS:GO plugin https://github.com/splewis/csgo-practice-mode, using it as reference. Thanks @splewis! (hope to see your work on CS2) + +### CKRAS Hosting +[CKRAS Hosting Team](https://www.ckras.com/en) They liked the addon, they contacted me and helped trying out the best way to create the coach, find bugs and give feedback. + +### Cierzo eSports team +My teammates are being supportive by bringing feedback, ideas and testing, I mean, server crashes, toooo many server crashes ♥ \ No newline at end of file diff --git a/configs/admins.cfg.example b/configs/admins.cfg.example new file mode 100644 index 00000000..ba5000e0 --- /dev/null +++ b/configs/admins.cfg.example @@ -0,0 +1,31 @@ +//--------------------- +// Permission flags +//--------------------- +// a : Reserved slots +// b : Generic admin, required for admins +// c : Kick other players +// d : Banning other players +// e : Removing bans +// f : Slaying other players +// g : Changing the map +// h : Changing cvars +// i : Changing configs +// j : Special chat privileges +// k : Voting +// l : Password the server +// m : Remote console +// n : Change sv_cheats and related commands +// z : Root. It grants ALL flags so use with caution! + +// Flags 'o' to 'y' are custom flags (currently unused) + +Admins +{ + // Admin entries should follow this format + + //"name" // Unused, can be anything + //{ + // "steamid" "1234567890" // SteamID64 + // "flags" "abcdefg" // Permission flags as described above + //} +} \ No newline at end of file diff --git a/configs/discordbots.cfg.example b/configs/discordbots.cfg.example new file mode 100644 index 00000000..4d8f43c0 --- /dev/null +++ b/configs/discordbots.cfg.example @@ -0,0 +1,14 @@ +"discordbots" +{ + "YourFirstBot" + { + "webhook" "DISCORD_WEBHOOK_1" + "override_name" "false" + } + "YourSecondBot" + { + "webhook" "DISCORD_WEBHOOK_2" + "avatar" "AVATAR_IMAGE_2" + "override_name" "true" + } +} \ No newline at end of file diff --git a/configs/maplist.cfg.example b/configs/maplist.cfg.example new file mode 100644 index 00000000..29f003d7 --- /dev/null +++ b/configs/maplist.cfg.example @@ -0,0 +1,18 @@ +"Maplist" +{ + "ze_my_first_ze_map" + { + "workshop_id" "123" + "enabled" "1" + } + "ze_my_second_ze_map" + { + "workshop_id" "456" + "enabled" "1" + } + "ze_my_thirdd_ze_map" + { + "workshop_id" "789" + "enabled" "1" + } +} \ No newline at end of file diff --git a/docker-setup.sh b/docker-setup.sh index f6ed7c04..2d155891 100644 --- a/docker-setup.sh +++ b/docker-setup.sh @@ -8,23 +8,34 @@ export MMSOURCE_DEV='/dockerVolume/metamod-source' export CC=clang export CXX=clang++ +clear + echo -------------------------------------------------------------------------- echo Starting steam sniper compilator for metamod echo -apt-get update -apt-get install python3-setuptools -y -apt-get install clang -y -apt-get install python3 -y -apt-get install gcc -y +if [ "$(which "ambuild")" != "" ]; +then + echo "AMBUILD installed" +else + echo "Installing ambuild" + + apt-get update + apt-get install python3-setuptools -y + apt-get install clang -y + apt-get install python3 -y + apt-get install gcc -y + + cd "/dockerVolume/ambuild" && python3 setup.py install -cd "/dockerVolume/ambuild" -python3 setup.py install + echo "AMBUILD Installed" +fi cd "/dockerVolume/mm-cs2-scrim" mkdir build cd build +#python ../configure.py --enable-optimize --symbol-files --sdks cs2 python3 ../configure.py --sdks cs2 --targets x86_64 ambuild diff --git a/gamedata/cs2fixes.games.txt b/gamedata/cs2fixes.games.txt index 7f9d10bb..cfbbf58a 100644 --- a/gamedata/cs2fixes.games.txt +++ b/gamedata/cs2fixes.games.txt @@ -1,222 +1,189 @@ "Games" { - "csgo" - { - "Signatures" - { - // Logging - "Msg" - { - "library" "tier0" - "windows" "@Msg" - "linux" "@Msg" - } - "ConDMsg" - { - "library" "tier0" - "windows" "@ConDMsg" - "linux" "@ConDMsg" - } - "DevMsg" - { - "library" "tier0" - "windows" "@DevMsg" - "linux" "@DevMsg" - } - "Warning" - { - "library" "tier0" - "windows" "@Warning" - "linux" "@Warning" - } - "DevWarning" - { - "library" "tier0" - "windows" "@DevWarning" - "linux" "@DevWarning" - } - "LoggingSystem_Log" - { - "library" "tier0" - "windows" "@LoggingSystem_Log" - "linux" "@LoggingSystem_Log" - } - "LoggingSystem_LogDirect" - { - "library" "tier0" - "windows" "@LoggingSystem_LogDirect" - "linux" "@LoggingSystem_LogDirect" - } - "LoggingSystem_LogAssert" - { - "library" "tier0" - "windows" "@LoggingSystem_LogAssert" - "linux" "@LoggingSystem_LogAssert" - } - - // String: "\"Console<0>\" say \"%s\"\n" - "Host_Say" - { - "library" "server" - "windows" "\x44\x89\x4C\x24\x2A\x44\x88\x44\x24\x2A\x55\x53\x56\x57\x41\x54\x41\x55" - "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x41\x55\x41\x54\x4D\x89\xC4" - } - // Called from Host_Say - "UTIL_SayTextFilter" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x2A\x55\x56\x57\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x49\x8B\xD8" - "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xD7\x31\xD2\x41\x56\x4C\x8D\x75\x98" - } - // Called from Host_Say - "UTIL_SayText2Filter" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x2A\x55\x56\x57\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x41\x0F\xB6\xF8" - "linux" "\x55\x48\x89\xE5\x41\x57\x4C\x8D\xBD\x2A\x2A\x2A\x2A\x41\x56\x4D\x89\xC6\x41\x55\x4D\x89\xCD" - } - // String: "" - "UTIL_ClientPrintAll" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x81\xEC\x70\x01\x2A\x2A\x8B\xE9" - "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xD7\x41\x56\x49\x89\xF6\x41\x55\x41\x89\xFD" - } - // String: "Console command too long" - "ClientPrint" - { - "library" "server" - "windows" "\x48\x85\xC9\x0F\x84\x2A\x2A\x2A\x2A\x48\x8B\xC4\x48\x89\x58\x18" - "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xCF\x41\x56\x49\x89\xD6\x41\x55\x41\x89\xF5\x41\x54\x4C\x8D\xA5\xA0\xFE\xFF\xFF" - } - "NetworkStateChanged" - { - "library" "server" - "windows" "\x4C\x8B\xC9\x48\x8B\x09\x48\x85\xC9\x74\x2A\x48\x8B\x41\x10" - "linux" "\x4C\x8B\x07\x4D\x85\xC0\x74\x2A\x49\x8B\x40\x10" - } - // String : "SV: %d/%s ignored %d FL_FULL_EDICT_CH" - "StateChanged" - { - "library" "server" - "windows" "\x40\x55\x53\x56\x41\x55\x41\x57\x48\x8D\x6C\x24\xB0" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x89\xD3" - } - "VoiceShouldHear" - { - "library" "engine" - "windows" "\x48\x89\x5C\x24\x10\x44\x88\x4C\x24\x20\x44\x88\x44\x24\x18" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x89\xD7\x41\x56\x49\x89\xF6\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x83\xEC\x28" - } - "IsHearingClient" - { - "library" "engine" - "windows" "\x40\x53\x48\x83\xEC\x20\x48\x8B\xD9\x3B\x91\xB8" - "linux" "\x55\x48\x89\xE5\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x08\x3B\xB7\xC8" - } - // String: "Playing sound on non-networked entity %s" - "CSoundEmitterSystem_EmitSound" - { - "library" "server" - "windows" "\x48\x8B\xC4\x4C\x89\x40\x18\x55\x57" - "linux" "\x48\xB8\x2A\x2A\x2A\x2A\xFF\xFF\xFF\xFF\x55\x48\x89\xE5\x41\x57\x41\x89\xF7" - } - // String: "hammerUniqueId" - "CBaseEntity_Spawn" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x30\x48\x8B\xF2" - "linux" "\x55\x48\x89\xE5\x41\x56\x41\x55\x41\x54\x49\x89\xF4\x53\x48\x89\xFB\x48\x83\xEC\x10\xE8\x2A\x2A\x2A\x2A" - } - // String: "weapon_econ_item_client_only" - "CCSWeaponBase_Spawn" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x18\x48\x89\x74\x24\x20\x57\x48\x81\xEC\xC0\x02\x00\x00" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x4C\x8D\xB5\x50\xFD\xFF\xFF" - } - // idk a good way to find this again, i just brute forced the vtable. offset is 133 on CTriggerPush - "TriggerPush_Touch" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x10\x48\x89\x7C\x24\x18\x55\x48\x8D\xAC\x24\x60\xE0\xFF\xFF" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xF5\x41\x54\x49\x89\xFC\x53\x48\x81\xEC\x28\x20\x2A\x2A\xE8" - } - // this is called in CTriggerPush::Touch, using IDA pseudocode look in an `if ( ( v & 0x80 ) != 0 )` and then `if ( v > 0.0 ) SetGroundEntity()` - "SetGroundEntity" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x10\x48\x89\x6C\x24\x18\x48\x89\x7C\x24\x20\x41\x56\x48\x83\xEC\x20\x0F\xB6\x81\xC0\x02\x2A\x2A\x48" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xF5\x41\x54\x49\x89\xFC\x53\x48\x83\xEC\x08\x0F\xB6\x87\xA8\x05\x2A\x2A\x83" - } - // Check vauff's pin in #scripting - "ServerMovementUnlock" - { - "library" "server" - "windows" "\x76\x2A\xF2\x0F\x10\x57\x2A\xF3\x0F\x10\x2A\x2A\x0F\x28\xCA\xF3\x0F\x59\xC0" - "linux" "\x0F\x87\x2A\x2A\x2A\x2A\x49\x8B\x7C\x24\x2A\xE8\x2A\x2A\x2A\x2A\x66\x0F\xEF\xED\x66\x0F\xD6\x85\x2A\x2A\x2A\x2A" - } - // Check vauff's pin in #scripting - "ClientMovementUnlock" - { - "library" "client" - "windows" "\x76\x2A\xF2\x0F\x10\x57\x2A\xF3\x0F\x10\x2A\x2A\x0F\x28\xCA\xF3\x0F\x59\xC0" - "linux" "\x0F\x87\x2A\x2A\x2A\x2A\x49\x8B\x7C\x24\x2A\xE8\x2A\x2A\x2A\x2A\x66\x0F\xEF\xED\x66\x0F\xD6\x85\x2A\x2A\x2A\x2A" - } - // Check tilgep's pin in #scripting - "VScriptEnable" - { - "library" "vscript" - "windows" "\xBE\x01\x2A\x2A\x2A\x2B\xD6\x74\x2A\x3B\xD6" - "linux" "\x83\xFE\x01\x0F\x84\x2A\x2A\x2A\x2A\x83" - } - // String: "Noise removal", there should be 3 customermachine checks - "HammerNoCustomerMachine" - { - "library" "hammer" - "windows" "\xFF\x15\x2A\x2A\x2A\x2A\x84\xC0\x0F\x85\x2A\x2A\x2A\x2A\xB9" - "linux" "" - } - // String: "CCSPlayerPawnBase::SwitchTeam", just keep in mind this is actually CCSPlayerController::SwitchTeam - "CCSPlayerController_SwitchTeam" - { - "library" "server" - "windows" "\x40\x56\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\xF9\x8B\xF2\x8B\xCA" - "linux" "\x55\x48\x89\xE5\x41\x55\x49\x89\xFD\x89\xF7" - } - + "csgo" + { + "Signatures" + { + // Logging + "Msg" + { + "library" "tier0" + "windows" "@Msg" + "linux" "@Msg" + } + "ConDMsg" + { + "library" "tier0" + "windows" "@ConDMsg" + "linux" "@ConDMsg" + } + "DevMsg" + { + "library" "tier0" + "windows" "@DevMsg" + "linux" "@DevMsg" + } + "Warning" + { + "library" "tier0" + "windows" "@Warning" + "linux" "@Warning" + } + "DevWarning" + { + "library" "tier0" + "windows" "@DevWarning" + "linux" "@DevWarning" + } + "LoggingSystem_Log" + { + "library" "tier0" + "windows" "@LoggingSystem_Log" + "linux" "@LoggingSystem_Log" + } + "LoggingSystem_LogDirect" + { + "library" "tier0" + "windows" "@LoggingSystem_LogDirect" + "linux" "@LoggingSystem_LogDirect" + } + "LoggingSystem_LogAssert" + { + "library" "tier0" + "windows" "@LoggingSystem_LogAssert" + "linux" "@LoggingSystem_LogAssert" + } + // Called from Host_Say + "UTIL_SayTextFilter" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x2A\x55\x56\x57\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x49\x8B\xD8" + "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xD7\x31\xD2\x41\x56\x4C\x8D\x75\x98" + } + // Called from Host_Say + "UTIL_SayText2Filter" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x2A\x55\x56\x57\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x41\x0F\xB6\xF8" + "linux" "\x55\x48\x89\xE5\x41\x57\x4C\x8D\xBD\x2A\x2A\x2A\x2A\x41\x56\x4D\x89\xC6\x41\x55\x4D\x89\xCD" + } + // String: "" + "UTIL_ClientPrintAll" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x81\xEC\x70\x01\x2A\x2A\x8B\xE9" + "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xD7\x41\x56\x49\x89\xF6\x41\x55\x41\x89\xFD" + } + // String: "Console command too long" + "ClientPrint" + { + "library" "server" + "windows" "\x48\x85\xC9\x0F\x84\x2A\x2A\x2A\x2A\x48\x8B\xC4\x48\x89\x58\x18" + "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xCF\x41\x56\x49\x89\xD6\x41\x55\x41\x89\xF5\x41\x54\x4C\x8D\xA5\xA0\xFE\xFF\xFF" + } + "NetworkStateChanged" + { + "library" "server" + "windows" "\x4C\x8B\xC9\x48\x8B\x09\x48\x85\xC9\x74\x2A\x48\x8B\x41\x10" + "linux" "\x4C\x8B\x07\x4D\x85\xC0\x74\x2A\x49\x8B\x40\x10" + } + // String : "SV: %d/%s ignored %d FL_FULL_EDICT_CH" + "StateChanged" + { + "library" "server" + "windows" "\x40\x55\x53\x56\x41\x55\x41\x57\x48\x8D\x6C\x24\xB0" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x89\xD3" + } + "IsHearingClient" + { + "library" "engine" + "windows" "\x40\x53\x48\x83\xEC\x20\x48\x8B\xD9\x3B\x91\xD0\x00\x00\x00" + "linux" "\x55\x48\x89\xE5\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x08\x3B\xB7\xE0\x00\x00\x00" + } + // String: "Playing sound on non-networked entity %s" + "CSoundEmitterSystem_EmitSound" + { + "library" "server" + "windows" "\x48\x8B\xC4\x4C\x89\x40\x18\x55\x57" + "linux" "\x48\xB8\x2A\x2A\x2A\x2A\xFF\xFF\xFF\xFF\x55\x48\x89\xE5\x41\x57\x41\x89\xF7" + } + // idk a good way to find this again, i just brute forced the vtable. offset is 133 on CTriggerPush + "TriggerPush_Touch" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x10\x48\x89\x7C\x24\x18\x55\x48\x8D\xAC\x24\x60\xE0\xFF\xFF" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xF5\x41\x54\x49\x89\xFC\x53\x48\x81\xEC\x28\x20\x2A\x2A\xE8" + } + // this is called in CTriggerPush::Touch, using IDA pseudocode look in an `if ( ( v & 0x80 ) != 0 )` and then `if ( v > 0.0 ) SetGroundEntity()` + "SetGroundEntity" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x10\x48\x89\x6C\x24\x18\x48\x89\x7C\x24\x20\x41\x56\x48\x83\xEC\x20\x4C\x8B\x05\x2A\x2A\x2A\x2A" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xF5\x41\x54\x49\x89\xFC\x53\x48\x83\xEC\x08\x8B\x87\xBC\x06\x00\x00" + } + // Check vauff's pin in #scripting + "ServerMovementUnlock" + { + "library" "server" + "windows" "\x76\x2A\xF2\x0F\x10\x57\x2A\xF3\x0F\x10\x2A\x2A\x0F\x28\xCA\xF3\x0F\x59\xC0" + "linux" "\x0F\x87\x2A\x2A\x2A\x2A\x49\x8B\x7D\x30\xE8\x2A\x2A\x2A\x2A\x66\x0F\xEF\xED\x66\x0F\xD6\x85\x2A\x2A\x2A\x2A" + } + // Check vauff's pin in #scripting + "ClientMovementUnlock" + { + "library" "client" + "windows" "\x76\x2A\xF2\x0F\x10\x57\x2A\xF3\x0F\x10\x2A\x2A\x0F\x28\xCA\xF3\x0F\x59\xC0" + "linux" "\x0F\x87\x2A\x2A\x2A\x2A\x49\x8B\x7C\x24\x2A\xE8\x2A\x2A\x2A\x2A\x66\x0F\xEF\xED\x66\x0F\xD6\x85\x2A\x2A\x2A\x2A" + } + // Check tilgep's pin in #scripting + "VScriptEnable" + { + "library" "vscript" + "windows" "\xBE\x01\x2A\x2A\x2A\x2B\xD6\x74\x2A\x3B\xD6" + "linux" "\x83\xFE\x01\x0F\x84\x2A\x2A\x2A\x2A\x83" + } + // String: "Noise removal", there should be 3 customermachine checks + "HammerNoCustomerMachine" + { + "library" "hammer" + "windows" "\xFF\x15\x2A\x2A\x2A\x2A\x84\xC0\x0F\x85\x2A\x2A\x2A\x2A\xB9" + "linux" "" + } + // String: "CCSPlayerPawnBase::SwitchTeam", just keep in mind this is actually CCSPlayerController::SwitchTeam + "CCSPlayerController_SwitchTeam" + { + "library" "server" + "windows" "\x40\x56\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\xF9\x8B\xF2\x8B\xCA" + "linux" "\x55\x48\x89\xE5\x41\x55\x49\x89\xFD\x89\xF7" + } // String: "player_jump", then find 42C80000h or in pseudocode "*(a2 + 68) = 1120403456;", changing from 100 to 145 - "CheckJumpButtonWater" - { - "library" "server" - "windows" "\xC8\x42\xEB\x2A\x48\x8B\x4B\x30" - "linux" "\xC8\x42\x66\x0F\xEF\xE4\x41\x0F\x2F\x65" - } - - // String: "StartGravity", a function call in the function with startgravity in ends with "return (sub_XXX( a1 + 48) > 1);", change the 1 to 2 - "WaterLevelGravity" - { - "library" "server" - "windows" "\x3C\x01\x49\x8B\x5B\x10\x49\x8B\x7B\x18\x0F\x97\xC0\x41\x0F\x28" - "linux" "\x3C\x01\x0F\x97\xC0\x48\x81\xC4\x50\x01" - } - + "CheckJumpButtonWater" + { + "library" "server" + "windows" "\xC8\x42\xEB\x2A\x48\x8B\x4B\x30" + "linux" "\xC8\x42\x66\x0F\xEF\xE4\x41\x0F\x2F\x65" + } + // String: "StartGravity", a function call in the function with startgravity in ends with "return (sub_XXX( a1 + 48) > 1);", change the 1 to 2 + "WaterLevelGravity" + { + "library" "server" + "windows" "\x3C\x01\x49\x8B\x5B\x10\x49\x8B\x7B\x18\x0F\x97\xC0\x41\x0F\x28" + "linux" "\x3C\x01\x0F\x97\xC0\x48\x81\xC4\x50\x01" + } // String: "PlayerMove_PostMove", generally function called before the postmove func is CategorizePosition, find the == 1.0 check in CategorizePosition - "CategorizeUnderwater" - { - "library" "server" - "windows" "\x75\x2A\xB3\x01\xEB\x2A\x32\xDB\x45\x32\xED" - "linux" "\x0F\x45\xC1\x4D\x85\xC0\x0F\x95\xC1\x20\xC8" - } - + "CategorizeUnderwater" + { + "library" "server" + "windows" "\x75\x2A\xB3\x01\xEB\x2A\x32\xDB\x45\x32\x2A" + "linux" "\x0F\x45\xC2\x4D\x85\xC0\x0F\x95\xC2\x20\xD0" + } // Called right after "Removed %s(%s)\n" "UTIL_Remove" - { - "library" "server" - "windows" "\x48\x85\xC9\x74\x2A\x48\x8B\xD1\x48\x8B\x0D\x2A\x2A\x2A\x2A" - "linux" "\x48\x89\xFE\x48\x85\xFF\x74\x2A\x48\x8D\x05\x2A\x2A\x2A\x2A\x48" - } - + { + "library" "server" + "windows" "\x48\x85\xC9\x74\x2A\x48\x8B\xD1\x48\x8B\x0D\x2A\x2A\x2A\x2A" + "linux" "\x48\x89\xFE\x48\x85\xFF\x74\x2A\x48\x8D\x05\x2A\x2A\x2A\x2A\x48" + } // "SetPosition" is passed to this "CEntitySystem_AddEntityIOEvent" { @@ -224,7 +191,6 @@ "windows" "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x40\x49\x8B\xF1" "linux" "\x55\x41\xBA\xFF\xFF\xFF\xFF" } - // "Explode" is passed to this "CEntityInstance_AcceptInput" { @@ -232,7 +198,12 @@ "windows" "\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x40\x49\x8B\xF0" "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x48\x8D\x7D\xC0" } - + "CEntityIdentity_AcceptInput" + { + "library" "server" + "windows" "\x48\x89\x54\x24\x10\x48\x89\x4C\x24\x08\x55\x53\x56\x57\x41\x55\x41\x56" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x4C\x8D\xBD\xD0\xFE\xFF\xFF\x49\x89\xD6\x41\x55\x49\x89\xF5\x41\x54\x49\x89\xCC" + } // Literally has "CGameRules::CGameRules constructed" in it "CGameRules_Constructor" { @@ -240,7 +211,6 @@ "windows" "\x40\x53\x48\x83\xEC\x20\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x8B\xD9\x48\x89\x01\x48\x89\x0D" "linux" "\x55\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x89\xE5\x53\x48\x89\xFB\x48\x83\xEC\x08\x48\x89\x07\x48\x89\x3D" } - // "multi_manager" is passed to this "CGameEntitySystem_FindEntityByClassName" { @@ -248,7 +218,6 @@ "windows" "\x48\x83\xEC\x68\x45\x33\xC9" "linux" "\x55\x45\x31\xC0\x31\xC9\x48\x89\xE5\x41\x54" } - // "commentary_semaphore" is passed to this "CGameEntitySystem_FindEntityByName" { @@ -256,110 +225,249 @@ "windows" "\x48\x81\xEC\x88\x2A\x2A\x2A\x4D\x85\xC0" "linux" "\x48\x85\xD2\x74\x2A\x55\x48\x89\xE5\x41\x54" } - // "CBaseEntity::TakeDamageOld" "CBaseEntity_TakeDamageOld" { "library" "server" "windows" "\x40\x56\x57\x48\x83\xEC\x58\x48\x8B\x41\x10" "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x83\xEC\x38\x4C\x8D\x2D\x2A\x2A\x2A\x2A\x49\x8B\x7D\x00\x48\x85\xFF\x0F\x84\x2A\x2A\x2A\x2A" - } - } - "Offsets" - { - "GameEventManager" - { - "windows" "91" - "linux" "91" - } + } + // "Game System %s is defined twice!\n" + // Note that this signature points to the instruction with sm_pFirst which is the first qword referenced in the function. + "IGameSystem_InitAllSystems_pFirst" + { + "library" "server" + "windows" "\x48\x8B\x1D\x2A\x2A\x2A\x2A\x48\x85\xDB\x0F\x84\x2A\x2A\x2A\x2A\xBE\x2A\x2A\x2A\x2A\x0F\x1F\x00\x48\x8B\x7B\x10" + "linux" "\x4C\x8B\x35\x2A\x2A\x2A\x2A\x4D\x85\xF6\x75\x2D\xE9\x2A\x2A\x2A\x2A\x0F\x1F\x40\x00\x48\x8B\x05" + } + "CBasePlayerController_SetPawn" + { + "library" "server" + "windows" "\x44\x88\x4C\x24\x2A\x55\x57\x41\x54\x41\x56\x41\x57\x48\x8D\x6C\x24\x2A" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x89\xF3\x48\x81\xEC\xC8\x00\x00\x00" + } + // String: "CNavMesh::GetNearestNavArea" + "CNavMesh_GetNearestNavArea" + { + "library" "server" + "windows" "\x48\x89\x4C\x24\x08\x55\x53\x57\x41\x54\x41\x55\x41\x56" + "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x49\x89\xD6\x41\x55\x41\x54\x53" + } + // Search "Changes's player's model", look for a function containing 'models/%s.vmdl'. Below V_snprintf is the one + // This matches 2 functions on linux, however they're literally identical + "CBaseModelEntity_SetModel" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x7C\x24\x2A\x55\x48\x8B\xEC\x48\x83\xEC\x50\x48\x8B\xF9\x4C\x8B\xC2" + "linux" "\x55\x48\x89\xF2\x48\x89\xE5\x41\x54\x49\x89\xFC\x48\x8D\x7D\xE0\x48\x83\xEC\x18\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x8B\x30\x48\x8B\x06" + } + "CGameRules_TerminateRound" + { + "library" "server" + "windows" "\x48\x8B\xC4\x4C\x89\x48\x20\x55\x57" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x81\xEC\xE8\x01\x00\x00\x48\x8D\x05\x2A\x2A\x2A\x2A" + } + "CCSPlayer_WeaponServices_CanUse" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x10\x48\x89\x6C\x24\x18\x56\x57\x41\x56\x48\x83\xEC\x30\x80\xB9\xA0\x00\x00\x00\x00" + "linux" "\x48\x85\xF6\x0F\x84\x2A\x2A\x2A\x2A\x55\x31\xC9\x48\x89\xE5\x41\x55\x49\x89\xFD" + } + "CreateEntityByName" + { + "library" "server" + "windows" "\x48\x83\xEC\x48\xC6\x44\x24\x30\x00" + "linux" "\x48\x8D\x05\x2A\x2A\x2A\x2A\x55\x48\x89\xFA" + } + "DispatchSpawn" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x10\x57\x48\x83\xEC\x30\x48\x8B\xDA\x48\x8B\xF9\x48\x85\xC9" + "linux" "\x48\x85\xFF\x74\x2A\x55\x48\x89\xE5\x41\x56" + } + // Look for "SetEntityName", that will be the vscript binding definition + // Scroll a bit down and you'll find something like this (note the offset): *(_QWORD *)(v453 + 64) = sub_1807B0350; + // that function is just a jump to the one we want + "CEntityIdentity_SetEntityName" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x10\x57\x48\x83\xEC\x20\x48\x8B\xD9\x4C\x8B\xC2" + "linux" "\x55\x48\x89\xF2\x48\x89\xE5\x41\x54\x49\x89\xFC\x48\x8D\x7D\xE0\x48\x83\xEC\x18\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x8B\x30\xE8\x2A\x2A\x2A\x2A\x48\x8B\x45\xE0" + } + // "Error - cannot add bots after game is over." + "BotNavIgnore" + { + "library" "server" + "windows" "\x0F\x84\x2A\x2A\x2A\x2A\x80\xB8\x2A\x2A\x2A\x2A\x00\x0F\x84\x2A\x2A\x2A\x2A\x80\x3D\x2A\x2A\x2A\x2A\x00\x74\x15" + "linux" "\x48\x85\xC0\x74\x2E\x80\xB8\x2A\x2A\x2A\x2A\x00\x74\x25" + } + + "FixLagCompEntityRelationship" + { + "library" "server" + "windows" "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x81\xEC\x00\x01\x00\x00\x48\x8B\x02" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x89\xD5\x41\x54\x49\x89\xFC\x48\x89\xF7" + } + + // next to "soundname", in windows it's the last referenced sub while in linux it's right after + // this is a vscript binding though so it may be removed in the future? + "CBaseEntity_EmitSoundParams" + { + "library" "server" + "windows" "\x48\x8B\xC4\x48\x89\x58\x10\x48\x89\x70\x18\x55\x57\x41\x56\x48\x8D\xA8\x08\xFF\xFF\xFF" + "linux" "\x48\xB8\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x55\x48\x89\xE5\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x89\xF3" + } + + // Called right after this in windows "Entity %s(%s) is ambiguously parented to..." + "CBaseEntity_SetParent" + { + "library" "server" + "windows" "\x4D\x8B\xD9\x48\x85\xD2\x74\x2A" + "linux" "\x48\x85\xF6\x74\x2A\x48\x8B\x47\x10\xF6\x40\x31\x02\x75\x2A\x48\x8B\x46\x10\xF6\x40\x31\x02\x75\x2A\xB8\x2A\x2A\x2A\x2A" + } + + // "CNetChan::SendNetMessage" + "SendNetMessage" + { + "library" "networksystem" + "windows" "\x48\x89\x5C\x24\x10\x48\x89\x6C\x24\x18\x48\x89\x74\x24\x20\x57\x41\x56\x41\x57\x48\x83\xEC\x40\x49\x8B\xE8" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x89\xCF\x41\x56\x4C\x8D\xB7\x90\x76\x00\x00" + } + + // "Discarding pending request" + "HostStateRequest" + { + "library" "engine" + "windows" "\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x30\x33\xF6\x48\x8B\xFA" + "linux" "\x55\x48\x89\xE5\x41\x56\x41\x55\x41\x54\x49\x89\xF4\x53\x48\x83\x7F\x30\x00" + } + } + "Offsets" + { + "GameEventManager" + { + "linux" "93" + "windows" "93" + } "GameEntitySystem" - { - "windows" "88" - "linux" "80" - } - "Teleport" - { - "windows" "149" - "linux" "148" - } - "CollisionRulesChanged" - { - "windows" "174" - "linux" "173" - } + { + "windows" "88" + "linux" "80" + } + "Teleport" + { + "windows" "149" + "linux" "148" + } + "CollisionRulesChanged" + { + "windows" "174" + "linux" "173" + } "IsEntityPawn" - { - "windows" "153" - "linux" "152" - } + { + "windows" "153" + "linux" "152" + } "IsEntityController" - { - "windows" "154" - "linux" "153" - } + { + "windows" "154" + "linux" "153" + } // String: "%s<%i><%s><%s>" ChangeTeam() CTMDBG..." - "CCSPlayerController_ChangeTeam" + "CCSPlayerController_ChangeTeam" { - "windows" "90" - "linux" "89" + "windows" "93" + "linux" "92" } // Look for the kill command, go through its callback and you should a find call like this, with v9 being a pawn pointer: - // return (*(*v9 + 2832LL))(v9, v27, 0LL); - // 2832 (354 * 8) is the offset + // return (*(*v9 + 2872LL))(v9, v27, 0LL); + // 2872 (359 * 8) is the offset "CBasePlayerPawn_CommitSuicide" { - "windows" "357" - "linux" "357" + "windows" "360" + "linux" "360" } // In the function with "[%03d] Found: %s, firing\n", you'll find a call into a pointer offset just a bit higher, that's the offset * 8 "CGameRules_FindPickerEntity" { - "windows" "27" - "linux" "28" - } - } - "Patches" - { - // Server - "ServerMovementUnlock" - { - "windows" "\xEB" - "linux" "\x90\x90\x90\x90\x90\x90" - } - "VScriptEnable" - { - "windows" "\xBE\x02" - "linux" "\x83\xFE\x02" - } + "windows" "27" + "linux" "28" + } + "PassesTriggerFilters" + { + "windows" "248" + "linux" "249" + } + "CCSPlayerController_Respawn" + { + "windows" "244" + "linux" "246" + } + "GetHammerUniqueId" + { + "windows" "102" + "linux" "101" + } + "CheckTransmitPlayerSlot" + { + "windows" "584" + "linux" "584" + } + + // "tried to sprint to a non-client", there will be a check above like this: if ( a2 >= *(v5 + 632) ) + "CNetworkGameServer_ClientList" + { + "windows" "77" + "linux" "79" + } + } + "Patches" + { + // Server + "ServerMovementUnlock" + { + "windows" "\xEB" + "linux" "\x90\x90\x90\x90\x90\x90" + } + "VScriptEnable" + { + "windows" "\xBE\x02" + "linux" "\x83\xFE\x02" + } "FixWaterFloorJump" - { - "windows" "\x11\x43" - "linux" "\x11\x43" - } - "WaterLevelGravity" - { - "windows" "\x3C\x02" - "linux" "\x3C\x02" - } - "CategorizeUnderwater" - { - "windows" "\x73" - "linux" "\x0F\x42" - } - - // Client - "ClientMovementUnlock" - { - "windows" "\xEB" - "linux" "\x90\x90\x90\x90\x90\x90" - } - - // Hammer - "HammerNoCustomerMachine" - { - "windows" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" - "linux" "" - } - } - } -} \ No newline at end of file + { + "windows" "\x11\x43" + "linux" "\x11\x43" + } + "WaterLevelGravity" + { + "windows" "\x3C\x02" + "linux" "\x3C\x02" + } + "CategorizeUnderwater" + { + "windows" "\x73" + "linux" "\x0F\x42" + } + // Jumping over a check for nav mesh + "BotNavIgnore" + { + "windows" "\xE9\x2C\x00\x00\x00\x90" + "linux" "\xE9\x15\x00\x00\x00" + } + // Client + "ClientMovementUnlock" + { + "windows" "\xEB" + "linux" "\x90\x90\x90\x90\x90\x90" + } + // Hammer + "HammerNoCustomerMachine" + { + "windows" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" + "linux" "" + } + } + } +} diff --git a/sdk b/sdk index 2a200361..43bfe744 160000 --- a/sdk +++ b/sdk @@ -1 +1 @@ -Subproject commit 2a200361ee2f76bc3582069d13cc210bea40a419 +Subproject commit 43bfe744a1af968664f5712e5b1290d48eee42b8 diff --git a/src/addresses.cpp b/src/addresses.cpp index 4135cd57..67dd41c3 100644 --- a/src/addresses.cpp +++ b/src/addresses.cpp @@ -1,7 +1,7 @@ /** * ============================================================================= * CS2Fixes - * Copyright (C) 2023 Source2ZE + * Copyright (C) 2023-2024 Source2ZE * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -19,21 +19,26 @@ #include "addresses.h" #include "utils/module.h" -#include +#include "gameconfig.h" #include "tier0/memdbgon.h" +extern CGameConfig *g_GameConfig; #define RESOLVE_SIG(gameConfig, name, variable) \ - variable = (decltype(variable))gameConfig->ResolveSignature(name) + variable = (decltype(variable))gameConfig->ResolveSignature(name); \ + if (!variable) \ + return false; \ + Message("Found %s at 0x%p\n", name, variable); -void addresses::Initialize(CGameConfig *g_GameConfig) +bool addresses::Initialize(CGameConfig *g_GameConfig) { modules::engine = new CModule(ROOTBIN, "engine2"); modules::tier0 = new CModule(ROOTBIN, "tier0"); modules::server = new CModule(GAMEBIN, "server"); modules::schemasystem = new CModule(ROOTBIN, "schemasystem"); modules::vscript = new CModule(ROOTBIN, "vscript"); + modules::networksystem = new CModule(ROOTBIN, "networksystem"); modules::client = nullptr; if (!CommandLine()->HasParm("-dedicated")) @@ -51,5 +56,19 @@ void addresses::Initialize(CGameConfig *g_GameConfig) RESOLVE_SIG(g_GameConfig, "ClientPrint", addresses::ClientPrint); RESOLVE_SIG(g_GameConfig, "SetGroundEntity", addresses::SetGroundEntity); RESOLVE_SIG(g_GameConfig, "CCSPlayerController_SwitchTeam", addresses::CCSPlayerController_SwitchTeam); + RESOLVE_SIG(g_GameConfig, "CBasePlayerController_SetPawn", addresses::CBasePlayerController_SetPawn); + //RESOLVE_SIG(g_GameConfig, "CBaseModelEntity_SetModel", addresses::CBaseModelEntity_SetModel); RESOLVE_SIG(g_GameConfig, "UTIL_Remove", addresses::UTIL_Remove); -} + //RESOLVE_SIG(g_GameConfig, "CEntitySystem_AddEntityIOEvent", addresses::CEntitySystem_AddEntityIOEvent); + //RESOLVE_SIG(g_GameConfig, "CEntityInstance_AcceptInput", addresses::CEntityInstance_AcceptInput); + RESOLVE_SIG(g_GameConfig, "CGameEntitySystem_FindEntityByClassName", addresses::CGameEntitySystem_FindEntityByClassName); + RESOLVE_SIG(g_GameConfig, "CGameEntitySystem_FindEntityByName", addresses::CGameEntitySystem_FindEntityByName); + //RESOLVE_SIG(g_GameConfig, "CGameRules_TerminateRound", addresses::CGameRules_TerminateRound); + RESOLVE_SIG(g_GameConfig, "CreateEntityByName", addresses::CreateEntityByName); + //RESOLVE_SIG(g_GameConfig, "DispatchSpawn", addresses::DispatchSpawn); + RESOLVE_SIG(g_GameConfig, "CEntityIdentity_SetEntityName", addresses::CEntityIdentity_SetEntityName); + //RESOLVE_SIG(g_GameConfig, "CBaseEntity_EmitSoundParams", addresses::CBaseEntity_EmitSoundParams); + //RESOLVE_SIG(g_GameConfig, "CBaseEntity_SetParent", addresses::CBaseEntity_SetParent); + + return true; +} \ No newline at end of file diff --git a/src/addresses.h b/src/addresses.h index 62392140..c6470d14 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -1,7 +1,7 @@ /** * ============================================================================= * CS2Fixes - * Copyright (C) 2023 Source2ZE + * Copyright (C) 2023-2024 Source2ZE * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -22,6 +22,7 @@ #include "stdint.h" #include "utils/module.h" #include "utlstring.h" +#include "variant.h" namespace modules { @@ -31,20 +32,28 @@ namespace modules inline CModule *schemasystem; inline CModule *vscript; inline CModule *client; + inline CModule* networksystem; #ifdef _WIN32 inline CModule *hammer; #endif } class CEntityInstance; +class CEntityIdentity; class CBasePlayerController; class CCSPlayerController; +class CCSPlayerPawn; +class CBaseModelEntity; class Z_CBaseEntity; class CGameConfig; +class CEntitySystem; +class IEntityFindFilter; +class CGameRules; +class CEntityKeyValues; namespace addresses { - void Initialize(CGameConfig *g_GameConfig); + bool Initialize(CGameConfig *g_GameConfig); inline void(FASTCALL *NetworkStateChanged)(int64 chainEntity, int64 offset, int64 a3); inline void(FASTCALL *StateChanged)(void *networkTransmitComponent, CEntityInstance *ent, int64 offset, int16 a4, int16 a5); @@ -52,5 +61,25 @@ namespace addresses inline void(FASTCALL *ClientPrint)(CBasePlayerController *player, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4); inline void(FASTCALL *SetGroundEntity)(Z_CBaseEntity *ent, Z_CBaseEntity *ground); inline void(FASTCALL *CCSPlayerController_SwitchTeam)(CCSPlayerController *pController, uint32 team); + inline void(FASTCALL *CBasePlayerController_SetPawn)(CBasePlayerController *pController, CCSPlayerPawn *pPawn, bool a3, bool a4); + //inline void(FASTCALL *CBaseModelEntity_SetModel)(CBaseModelEntity *pModel, const char *szModel); inline void(FASTCALL *UTIL_Remove)(CEntityInstance*); -} + + /*inline void(FASTCALL *CEntitySystem_AddEntityIOEvent)(CEntitySystem *pEntitySystem, CEntityInstance *pTarget, const char *pszInput, + CEntityInstance *pActivator, CEntityInstance *pCaller, variant_t *value, float flDelay, int outputID);*/ + + /*inline void(FASTCALL *CEntityInstance_AcceptInput)(CEntityInstance *pThis, const char *pInputName, + CEntityInstance *pActivator, CEntityInstance *pCaller, variant_t *value, int nOutputID);*/ + + inline Z_CBaseEntity *(FASTCALL *CGameEntitySystem_FindEntityByClassName)(CEntitySystem *pEntitySystem, CEntityInstance *pStartEntity, const char *szName); + + inline Z_CBaseEntity *(FASTCALL *CGameEntitySystem_FindEntityByName)(CEntitySystem *pEntitySystem, CEntityInstance *pStartEntity, const char *szName, + CEntityInstance *pSearchingEntity, CEntityInstance *pActivator, CEntityInstance *pCaller, + IEntityFindFilter *pFilter); + //inline void(FASTCALL *CGameRules_TerminateRound)(CGameRules* pGameRules, float delay, unsigned int reason, int64 a4, unsigned int a5); + inline Z_CBaseEntity *(FASTCALL* CreateEntityByName)(const char* className, int iForceEdictIndex); + //inline void(FASTCALL* DispatchSpawn)(Z_CBaseEntity* pEntity, CEntityKeyValues *pEntityKeyValues); + inline void(FASTCALL* CEntityIdentity_SetEntityName)(CEntityIdentity *pEntity, const char *pName); + inline void(FASTCALL *CBaseEntity_EmitSoundParams)(Z_CBaseEntity *pEntity, const char *pszSound, int nPitch, float flVolume, float flDelay); + inline void(FASTCALL *CBaseEntity_SetParent)(Z_CBaseEntity *pEntity, Z_CBaseEntity *pNewParent, CUtlStringToken nBoneOrAttachName, matrix3x4a_t *pOffsetTransform); +} \ No newline at end of file diff --git a/src/adminsystem.cpp b/src/adminsystem.cpp index 86c5d10a..078809dc 100644 --- a/src/adminsystem.cpp +++ b/src/adminsystem.cpp @@ -26,30 +26,78 @@ #include "playermanager.h" #include "commands.h" #include "ctimer.h" +#include "detours.h" + +#include "utils/entity.h" +#include "entity/cbaseentity.h" +#include "entity/cparticlesystem.h" +#include "entity/cgamerules.h" +#include "gamesystem.h" +#include extern IVEngineServer2 *g_pEngineServer2; -extern CEntitySystem *g_pEntitySystem; +extern CGameEntitySystem *g_pEntitySystem; +extern CGlobalVars *gpGlobals; +extern CCSGameRules *g_pGameRules; CAdminSystem* g_pAdminSystem = nullptr; -CUtlMap g_CommandList(0, 0, DefLessFunc(uint32)); bool practiceMode = false; +bool no_flash_mode = false; extern CUtlVector coaches; extern void print_coaches(); +extern bool half_last_round; +char level_name[256]; //Map name workaround for demo names, only when .map has been triggered +CUtlMap g_CommandList(0, 0, DefLessFunc(uint32)); + +extern bool g_bEnableBan; +extern bool g_bEnableCoach; +extern bool g_bEnableGag; +extern bool g_bEnableKick; +extern bool g_bEnablePause; +extern bool g_bEnablePraccSpawn; +extern bool g_bEnablePractice; +extern bool g_bEnableRcon; +extern bool g_bEnableRecord; +extern bool g_bEnableRestore; +extern bool g_bEnableScrim; +extern bool g_bEnableSlay; +extern bool g_bEnableTeamControl; +extern bool g_bEnableTeleport; + + +void PrintSingleAdminAction(const char* pszAdminName, const char* pszTargetName, const char* pszAction, const char* pszAction2 = "", const char* prefix = CHAT_PREFIX) +{ + ClientPrintAll(HUD_PRINTTALK, "%s" ADMIN_PREFIX "%s %s%s.", prefix, pszAdminName, pszAction, pszTargetName, pszAction2); +} -#define ADMIN_PREFIX "Admin %s has " +void PrintMultiAdminAction(ETargetType nType, const char* pszAdminName, const char* pszAction, const char* pszAction2 = "", const char* prefix = CHAT_PREFIX) +{ + switch (nType) + { + case ETargetType::ALL: + ClientPrintAll(HUD_PRINTTALK, "%s" ADMIN_PREFIX "%s everyone%s.", prefix, pszAdminName, pszAction, pszAction2); + break; + case ETargetType::T: + ClientPrintAll(HUD_PRINTTALK, "%s" ADMIN_PREFIX "%s terrorists%s.", prefix, pszAdminName, pszAction, pszAction2); + break; + case ETargetType::CT: + ClientPrintAll(HUD_PRINTTALK, "%s" ADMIN_PREFIX "%s counter-terrorists%s.", prefix, pszAdminName, pszAction, pszAction2); + break; + } +} CON_COMMAND_F(c_reload_admins, "Reload admin config", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND) { if (!g_pAdminSystem->LoadAdmins()) return; - for (int i = 0; i < MAXPLAYERS; i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { ZEPlayer* pPlayer = g_playerManager->GetPlayer(i); - if (!pPlayer || pPlayer->IsFakeClient()) + if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsAuthenticated()) continue; pPlayer->CheckAdmin(); @@ -58,26 +106,43 @@ CON_COMMAND_F(c_reload_admins, "Reload admin config", FCVAR_SPONLY | FCVAR_LINKE Message("Admins reloaded\n"); } -CON_COMMAND_F(c_reload_infractions, "Reload infractions file", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND) +CON_COMMAND_CHAT(rcon, "fake rcon") { - if (!g_pAdminSystem->LoadInfractions()) + if (!g_bEnableRcon) return; + + if (!player) + return; + + int iCommandPlayer = player->GetPlayerSlot(); + + ZEPlayer *pPlayer = g_playerManager->GetPlayer(iCommandPlayer); - for (int i = 0; i < MAXPLAYERS; i++) + if (!pPlayer->IsAdminFlagSet(ADMFLAG_BAN)) { - ZEPlayer* pPlayer = g_playerManager->GetPlayer(i); + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You don't have access to this command."); + return; + } - if (!pPlayer || pPlayer->IsFakeClient()) - continue; + char buf[MAX_PATH]; + V_snprintf(buf, sizeof(buf), ""); + char last_arg[MAX_PATH]; + V_snprintf(last_arg, sizeof(last_arg), ""); - pPlayer->CheckInfractions(); + for (int i = 1; i < args.ArgC(); i++){ + V_snprintf(last_arg, sizeof(last_arg), "%s", buf); + V_snprintf(buf, sizeof(buf), "%s %s",last_arg, args[i]); } - Message("Infractions reloaded\n"); + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Command sent: \04%s", buf); + g_pEngineServer2->ServerCommand(buf); } CON_COMMAND_CHAT(ban, "ban a player") { + if(!g_bEnableBan) + return; + if (!player) return; @@ -140,8 +205,46 @@ CON_COMMAND_CHAT(ban, "ban a player") ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "banned %s for %i minutes.", player->GetPlayerName(), pTarget->GetPlayerName(), iDuration); } +CON_COMMAND_CHAT(unban, "unbans a player") +{ + if(!g_bEnableBan) + return; + + if (!player) + return; + + int iCommandPlayer = player->GetPlayerSlot(); + + ZEPlayer *pPlayer = g_playerManager->GetPlayer(iCommandPlayer); + + if (!pPlayer->IsAdminFlagSet(ADMFLAG_BAN)) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You don't have access to this command."); + return; + } + + if (args.ArgC() < 2) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Usage: !unban "); + return; + } + + uint64 targetSteamID = V_StringToUint64(args[1], -1); + + if(g_pAdminSystem->FindAndRemoveInfraction(targetSteamID, CInfractionBase::Ban)){ + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "SeeamID %llu unbanned.", targetSteamID); + }else{ + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "SeeamID %llu is not banned.", targetSteamID); + } + + return; +} + CON_COMMAND_CHAT(gag, "gag a player") { + if(!g_bEnableGag) + return; + if (!player) return; @@ -222,6 +325,9 @@ CON_COMMAND_CHAT(gag, "gag a player") CON_COMMAND_CHAT(ungag, "ungags a player") { + if(!g_bEnableGag) + return; + if (!player) return; @@ -292,6 +398,9 @@ CON_COMMAND_CHAT(ungag, "ungags a player") CON_COMMAND_CHAT(kick, "kick a player") { + if(!g_bEnableKick) + return; + if (!player) return; @@ -339,6 +448,9 @@ CON_COMMAND_CHAT(kick, "kick a player") CON_COMMAND_CHAT(slay, "slay a player") { + if(!g_bEnableSlay) + return; + if (!player) return; @@ -398,6 +510,9 @@ CON_COMMAND_CHAT(slay, "slay a player") CON_COMMAND_CHAT(goto, "teleport to a player") { + if(!g_bEnableTeleport) + return; + if (!player) return; @@ -449,6 +564,9 @@ CON_COMMAND_CHAT(goto, "teleport to a player") CON_COMMAND_CHAT(bring, "bring a player") { + if(!g_bEnableTeleport) + return; + if (!player) return; @@ -510,6 +628,9 @@ CON_COMMAND_CHAT(bring, "bring a player") CON_COMMAND_CHAT(setteam, "set a player's team") { + if(!g_bEnableTeamControl) + return; + if (!player) return; @@ -550,13 +671,12 @@ CON_COMMAND_CHAT(setteam, "set a player's team") for (int i = 0; i < iNumClients; i++) { - CBasePlayerController *pTarget = (CBasePlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pSlots[i] + 1)); + CCSPlayerController *pTarget = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pSlots[i] + 1)); if (!pTarget) continue; - pTarget->m_iTeamNum = iTeam; - pTarget->GetPawn()->m_iTeamNum = iTeam; + pTarget->ChangeTeam(iTeam); if (nType < ETargetType::ALL) ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "moved %s to team %i.", player->GetPlayerName(), pTarget->GetPlayerName(), iTeam); @@ -578,7 +698,7 @@ CON_COMMAND_CHAT(setteam, "set a player's team") CON_COMMAND_CHAT(noclip, "toggle noclip on yourself") { - if (!player) + if (!player && practiceMode) return; int iCommandPlayer = player->GetPlayerSlot(); @@ -863,6 +983,21 @@ bool CAdminSystem::FindAndRemoveInfraction(ZEPlayer *player, CInfractionBase::EI return false; } +bool CAdminSystem::FindAndRemoveInfraction(uint64 iSteamID, CInfractionBase::EInfractionType type) +{ + FOR_EACH_VEC(m_vecInfractions, i) + { + if (m_vecInfractions[i]->GetSteamId64() == iSteamID && m_vecInfractions[i]->GetType() == type) + { + m_vecInfractions.Remove(i); + + return true; + } + } + + return false; +} + CAdmin *CAdminSystem::FindAdmin(uint64 iSteamID) { FOR_EACH_VEC(m_vecAdmins, i) @@ -922,6 +1057,9 @@ void CGagInfraction::UndoInfraction(ZEPlayer *player) //CS2Scrim custom commands CON_COMMAND_CHAT(scrim, "Scrim mode") { + if (!g_bEnableScrim) + return; + if (!player) return; @@ -951,6 +1089,9 @@ CON_COMMAND_CHAT(scrim, "Scrim mode") CON_COMMAND_CHAT(pracc, "Practice mode") { + if(!g_bEnablePractice) + return; + if (!player) return; @@ -978,6 +1119,9 @@ CON_COMMAND_CHAT(pracc, "Practice mode") CON_COMMAND_CHAT(forceunpause, "Force unpause") { + if(!g_bEnablePause) + return; + if (!player) return; @@ -1026,14 +1170,18 @@ CON_COMMAND_CHAT(map, "change map") return; } */ + //V_strncpy + V_snprintf(level_name, sizeof(level_name), "%s", args[1]); + char buf[MAX_PATH]; V_snprintf(buf, sizeof(buf), "changelevel de_%s", args[1]); ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"Changing map to %s...", args[1]); - new CTimer(5.0f, false, false, [buf]() + new CTimer(5.0f, false, [buf]() { g_pEngineServer2->ServerCommand(buf); + return -5.0f; }); @@ -1041,9 +1189,12 @@ CON_COMMAND_CHAT(map, "change map") CON_COMMAND_CHAT(restore, "Restore round") { + if (!g_bEnableRestore) + return; + if (!player) return; - + int iCommandPlayer = player->GetPlayerSlot(); ZEPlayer *pPlayer = g_playerManager->GetPlayer(player->GetPlayerSlot()); @@ -1079,12 +1230,17 @@ CON_COMMAND_CHAT(restore, "Restore round") ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"\4Restored round \3%i", nRounds); + half_last_round = false; //If not set to false, coach will be on the wrong team if it is the last round of the first half + g_pEngineServer2->ServerCommand(buf); } char demoName[128]; CON_COMMAND_CHAT(record, "Record demo") { + if (!g_bEnableRecord) + return; + if (!player) return; @@ -1107,12 +1263,16 @@ CON_COMMAND_CHAT(record, "Record demo") std::localtime(&result); std::strftime(actualTime, sizeof(actualTime), "%d%B_%H-%M", std::localtime(&result)); - V_snprintf(actualMap,MAX_PATH, "unknownMap"); + V_snprintf(actualMap,MAX_PATH, "%s", gpGlobals->mapname); + if((std::string)actualMap == "") V_snprintf(actualMap,MAX_PATH, "unknownMap"); + V_snprintf(demoName, MAX_PATH, "%s_%s", actualTime, actualMap); V_snprintf(buf, MAX_PATH, "tv_record gotv/%s", demoName); - ClientPrint(player, HUD_PRINTTALK, buf); g_pEngineServer2->ServerCommand(buf); + + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Demo will be saved at \4gotv/%s", demoName); + //V_snprintf(buf, MAX_PATH, "record gotv/%s", demoName); /* FormatTime(actualTime, sizeof(actualTime), "%d%B_%H-%M", GetTimestamp()); //https://www.tutorialspoint.com/c_standard_library/c_function_strftime.htm @@ -1130,6 +1290,9 @@ CON_COMMAND_CHAT(record, "Record demo") CON_COMMAND_CHAT(stoprecord, "Stop demo recording") { + if (!g_bEnableRecord) + return; + if (!player) return; @@ -1142,14 +1305,8 @@ CON_COMMAND_CHAT(stoprecord, "Stop demo recording") ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "You don't have access to this command."); return; } - - char buf[256]; - char command[256]; - V_snprintf(buf, MAX_PATH, "Demo saved at gotv/%s", demoName); - ClientPrint(player, HUD_PRINTTALK, buf); + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Demo saved at \4gotv/%s", demoName); - V_snprintf(command, MAX_PATH, "tv_stoprecord"); - g_pEngineServer2->ServerCommand(command); - + g_pEngineServer2->ServerCommand("tv_stoprecord"); } \ No newline at end of file diff --git a/src/adminsystem.h b/src/adminsystem.h index 258feff9..631819cd 100644 --- a/src/adminsystem.h +++ b/src/adminsystem.h @@ -23,36 +23,49 @@ #include "playermanager.h" #include -#define ADMFLAG_RESERVATION (1<<0) /**< Convenience macro for Admin_Reservation as a FlagBit */ -#define ADMFLAG_GENERIC (1<<1) /**< Convenience macro for Admin_Generic as a FlagBit */ -#define ADMFLAG_KICK (1<<2) /**< Convenience macro for Admin_Kick as a FlagBit */ -#define ADMFLAG_BAN (1<<3) /**< Convenience macro for Admin_Ban as a FlagBit */ -#define ADMFLAG_UNBAN (1<<4) /**< Convenience macro for Admin_Unban as a FlagBit */ -#define ADMFLAG_SLAY (1<<5) /**< Convenience macro for Admin_Slay as a FlagBit */ -#define ADMFLAG_CHANGEMAP (1<<6) /**< Convenience macro for Admin_Changemap as a FlagBit */ -#define ADMFLAG_CONVARS (1<<7) /**< Convenience macro for Admin_Convars as a FlagBit */ -#define ADMFLAG_CONFIG (1<<8) /**< Convenience macro for Admin_Config as a FlagBit */ -#define ADMFLAG_CHAT (1<<9) /**< Convenience macro for Admin_Chat as a FlagBit */ -#define ADMFLAG_VOTE (1<<10) /**< Convenience macro for Admin_Vote as a FlagBit */ -#define ADMFLAG_PASSWORD (1<<11) /**< Convenience macro for Admin_Password as a FlagBit */ -#define ADMFLAG_RCON (1<<12) /**< Convenience macro for Admin_RCON as a FlagBit */ -#define ADMFLAG_CHEATS (1<<13) /**< Convenience macro for Admin_Cheats as a FlagBit */ -#define ADMFLAG_ROOT (1<<14) /**< Convenience macro for Admin_Root as a FlagBit */ -#define ADMFLAG_CUSTOM1 (1<<15) /**< Convenience macro for Admin_Custom1 as a FlagBit */ -#define ADMFLAG_CUSTOM2 (1<<16) /**< Convenience macro for Admin_Custom2 as a FlagBit */ -#define ADMFLAG_CUSTOM3 (1<<17) /**< Convenience macro for Admin_Custom3 as a FlagBit */ -#define ADMFLAG_CUSTOM4 (1<<18) /**< Convenience macro for Admin_Custom4 as a FlagBit */ -#define ADMFLAG_CUSTOM5 (1<<19) /**< Convenience macro for Admin_Custom5 as a FlagBit */ -#define ADMFLAG_CUSTOM6 (1<<20) /**< Convenience macro for Admin_Custom6 as a FlagBit */ - +#define ADMFLAG_NONE (0) +#define ADMFLAG_RESERVATION (1 << 0) // a +#define ADMFLAG_GENERIC (1 << 1) // b +#define ADMFLAG_KICK (1 << 2) // c +#define ADMFLAG_BAN (1 << 3) // d +#define ADMFLAG_UNBAN (1 << 4) // e +#define ADMFLAG_SLAY (1 << 5) // f +#define ADMFLAG_CHANGEMAP (1 << 6) // g +#define ADMFLAG_CONVARS (1 << 7) // h +#define ADMFLAG_CONFIG (1 << 8) // i +#define ADMFLAG_CHAT (1 << 9) // j +#define ADMFLAG_VOTE (1 << 10) // k +#define ADMFLAG_PASSWORD (1 << 11) // l +#define ADMFLAG_RCON (1 << 12) // m +#define ADMFLAG_CHEATS (1 << 13) // n +#define ADMFLAG_CUSTOM1 (1 << 14) // o +#define ADMFLAG_CUSTOM2 (1 << 15) // p +#define ADMFLAG_CUSTOM3 (1 << 16) // q +#define ADMFLAG_CUSTOM4 (1 << 17) // r +#define ADMFLAG_CUSTOM5 (1 << 18) // s +#define ADMFLAG_CUSTOM6 (1 << 19) // t +#define ADMFLAG_CUSTOM7 (1 << 20) // u +#define ADMFLAG_CUSTOM8 (1 << 21) // v +#define ADMFLAG_CUSTOM9 (1 << 22) // w +#define ADMFLAG_CUSTOM10 (1 << 23) // x +#define ADMFLAG_CUSTOM11 (1 << 24) // y +#define ADMFLAG_ROOT (1 << 25) // z + +#define ADMIN_PREFIX "Admin %s has " + +void PrintSingleAdminAction(const char* pszAdminName, const char* pszTargetName, const char* pszAction, const char* pszAction2, const char* prefix); +void PrintMultiAdminAction(ETargetType nType, const char* pszAdminName, const char* pszAction, const char* pszAction2, const char* prefix); class CInfractionBase { public: - CInfractionBase(int duration, uint64 steamId) : m_iSteamID(steamId) + CInfractionBase(time_t duration, uint64 steamId, bool bEndTime = false) : m_iSteamID(steamId) { // The duration is in minutes here - m_iTimestamp = duration != 0 ? std::time(nullptr) + (duration * 60) : 0; + if (!bEndTime) + m_iTimestamp = duration != 0 ? std::time(nullptr) + (duration * 60) : 0; + else + m_iTimestamp = duration; } enum EInfractionType { @@ -64,11 +77,11 @@ class CInfractionBase virtual EInfractionType GetType() = 0; virtual void ApplyInfraction(ZEPlayer*) = 0; virtual void UndoInfraction(ZEPlayer *) = 0; - int GetTimestamp() { return m_iTimestamp; } + time_t GetTimestamp() { return m_iTimestamp; } uint64 GetSteamId64() { return m_iSteamID; } private: - int m_iTimestamp; + time_t m_iTimestamp; uint64 m_iSteamID; }; @@ -135,13 +148,13 @@ class CAdminSystem void SaveInfractions(); bool ApplyInfractions(ZEPlayer *player); bool FindAndRemoveInfraction(ZEPlayer *player, CInfractionBase::EInfractionType type); + bool FindAndRemoveInfraction(uint64 iSteamID, CInfractionBase::EInfractionType type); CAdmin *FindAdmin(uint64 iSteamID); - -private: uint64 ParseFlags(const char* pszFlags); +private: CUtlVector m_vecAdmins; CUtlVector m_vecInfractions; }; -extern CAdminSystem* g_pAdminSystem; +extern CAdminSystem *g_pAdminSystem; diff --git a/src/cdetour.h b/src/cdetour.h index fa203904..27edfbf9 100644 --- a/src/cdetour.h +++ b/src/cdetour.h @@ -86,12 +86,14 @@ bool CDetour::CreateDetour(CGameConfig *gameConfig) if (!m_pfnFunc) return false; + T *pFunc = m_pfnFunc; + m_hook = funchook_create(); funchook_prepare(m_hook, (void**)&m_pfnFunc, (void*)m_pfnDetour); g_vecDetours.AddToTail(this); - Message("Successfully initialized detour for %s!\n", m_pszName); + Message("Detoured %s at 0x%p\n", m_pszName, pFunc); return true; } diff --git a/src/commands.cpp b/src/commands.cpp index 1a413fb8..65cea991 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -28,34 +28,248 @@ #include "entity/ccsplayercontroller.h" #include "entity/ccsplayerpawn.h" #include "entity/cbasemodelentity.h" +#include "entity/ccsweaponbase.h" +#include "entity/cparticlesystem.h" +#include "entity/lights.h" #include "playermanager.h" #include "adminsystem.h" #include "ctimer.h" +#undef snprintf +#include "vendor/nlohmann/json.hpp" + #include "tier0/memdbgon.h" -extern CEntitySystem *g_pEntitySystem; +using json = nlohmann::json; + +extern CGameEntitySystem *g_pEntitySystem; extern IVEngineServer2* g_pEngineServer2; -extern int g_targetPawn; -extern int g_targetController; extern bool practiceMode; +extern bool no_flash_mode; + +WeaponMapEntry_t WeaponMap[] = { + {{"bizon"}, "weapon_bizon", "PP-Bizon", 1400, 26, GEAR_SLOT_RIFLE}, + {{"mac10", "mac"}, "weapon_mac10", "MAC-10", 1050, 27, GEAR_SLOT_RIFLE}, + {{"mp5sd", "mp5"}, "weapon_mp5sd", "MP5-SD", 1500, 23, GEAR_SLOT_RIFLE}, + {{"mp7"}, "weapon_mp7", "MP7", 1500, 23, GEAR_SLOT_RIFLE}, + {{"mp9"}, "weapon_mp9", "MP9", 1250, 34, GEAR_SLOT_RIFLE}, + {{"p90"}, "weapon_p90", "P90", 2350, 19, GEAR_SLOT_RIFLE}, + {{"ump45", "ump"}, "weapon_ump45", "UMP-45", 1200, 24, GEAR_SLOT_RIFLE}, + {{"ak47", "ak"}, "weapon_ak47", "AK-47", 2700, 7, GEAR_SLOT_RIFLE}, + {{"aug"}, "weapon_aug", "AUG", 3300, 8, GEAR_SLOT_RIFLE}, + {{"famas"}, "weapon_famas", "FAMAS", 2050, 10, GEAR_SLOT_RIFLE}, + {{"galilar", "galil"}, "weapon_galilar", "Galil AR", 1800, 13, GEAR_SLOT_RIFLE}, + {{"m4a4"}, "weapon_m4a1", "M4A4", 3100, 16, GEAR_SLOT_RIFLE}, + {{"m4a1-s", "m4a1"}, "weapon_m4a1_silencer", "M4A1-S", 2900, 60, GEAR_SLOT_RIFLE}, + {{"sg553"}, "weapon_sg556", "SG 553", 3000, 39, GEAR_SLOT_RIFLE}, + {{"awp"}, "weapon_awp", "AWP", 4750, 9, GEAR_SLOT_RIFLE}, + {{"g3sg1"}, "weapon_g3sg1", "G3SG1", 5000, 11, GEAR_SLOT_RIFLE}, + {{"scar20", "scar"}, "weapon_scar20", "SCAR-20", 5000, 38, GEAR_SLOT_RIFLE}, + {{"ssg08", "ssg"}, "weapon_ssg08", "SSG 08", 1700, 40, GEAR_SLOT_RIFLE}, + {{"mag7", "mag"}, "weapon_mag7", "MAG-7", 1300, 29, GEAR_SLOT_RIFLE}, + {{"nova"}, "weapon_nova", "Nova", 1050, 35, GEAR_SLOT_RIFLE}, + {{"sawedoff"}, "weapon_sawedoff", "Sawed-Off", 1100, 29, GEAR_SLOT_RIFLE}, + {{"xm1014", "xm"}, "weapon_xm1014", "XM1014", 2000, 25, GEAR_SLOT_RIFLE}, + {{"m249"}, "weapon_m249", "M249", 5200, 14, GEAR_SLOT_RIFLE}, + {{"negev"}, "weapon_negev", "Negev", 1700, 28, GEAR_SLOT_RIFLE}, + {{"deagle"}, "weapon_deagle", "Desert Eagle", 700, 1, GEAR_SLOT_PISTOL}, + {{"dualberettas", "elite"}, "weapon_elite", "Dual Berettas", 300, 2, GEAR_SLOT_PISTOL}, + {{"fiveseven"}, "weapon_fiveseven", "Five-SeveN", 500, 3, GEAR_SLOT_PISTOL}, + {{"glock18", "glock"}, "weapon_glock", "Glock-18", 200, 4, GEAR_SLOT_PISTOL}, + {{"p2000"}, "weapon_hkp2000", "P2000", 200, 32, GEAR_SLOT_PISTOL}, + {{"p250"}, "weapon_p250", "P250", 300, 36, GEAR_SLOT_PISTOL}, + {{"tec9"}, "weapon_tec9", "Tec-9", 500, 30, GEAR_SLOT_PISTOL}, + {{"usp-s", "usp"}, "weapon_usp_silencer", "USP-S", 200, 61, GEAR_SLOT_PISTOL}, + {{"cz75-auto", "cs75a", "cz"}, "weapon_cz75a", "CZ75-Auto", 500, 63, GEAR_SLOT_PISTOL}, + {{"r8revolver", "revolver", "r8"}, "weapon_revolver", "R8 Revolver", 600, 64, GEAR_SLOT_PISTOL}, + {{"hegrenade", "he"}, "weapon_hegrenade", "HE Grenade", 300, 44, GEAR_SLOT_GRENADES, 1}, + {{"molotov"}, "weapon_molotov", "Molotov", 400, 46, GEAR_SLOT_GRENADES, 1}, + {{"kevlar"}, "item_kevlar", "Kevlar Vest", 650, 50, GEAR_SLOT_UTILITY}, +}; + +bool g_bEnableWeapons = false; + +FAKE_BOOL_CVAR(cs2f_weapons_enable, "Whether to enable weapon commands", g_bEnableWeapons, false, false) + +void ParseWeaponCommand(const CCommand& args, CCSPlayerController* player) +{ + if (!g_bEnableWeapons || !player || !player->m_hPawn()) + return; + + CCSPlayerPawn* pPawn = (CCSPlayerPawn*)player->GetPawn(); + WeaponMapEntry_t weaponEntry; + bool foundWeapon = false; + + for (int i = 0; i < sizeof(WeaponMap) / sizeof(*WeaponMap); i++) + { + if (foundWeapon) + break; + + weaponEntry = WeaponMap[i]; + const char* command = args[0]; + + if (!V_strncmp("c_", command, 2)) + command = command + 2; + + for (std::string alias : weaponEntry.aliases) + { + if (!V_stricmp(command, alias.c_str())) + { + foundWeapon = true; + break; + } + } + } + + if (!foundWeapon) + return; + + if (pPawn->m_iHealth() <= 0 || pPawn->m_iTeamNum != CS_TEAM_CT) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You can only buy weapons when human."); + return; + } + + CCSPlayer_ItemServices* pItemServices = pPawn->m_pItemServices; + CPlayer_WeaponServices* pWeaponServices = pPawn->m_pWeaponServices; + + // it can sometimes be null when player joined on the very first round? + if (!pItemServices || !pWeaponServices) + return; + + int money = player->m_pInGameMoneyServices->m_iAccount; + + if (money < weaponEntry.iPrice) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You can't afford %s! It costs $%i, you only have $%i", weaponEntry.szWeaponName, weaponEntry.iPrice, money); + return; + } + + if (weaponEntry.maxAmount) + { + CUtlVector* weaponPurchases = pPawn->m_pActionTrackingServices->m_weaponPurchasesThisRound().m_weaponPurchases; + bool found = false; + FOR_EACH_VEC(*weaponPurchases, i) + { + WeaponPurchaseCount_t& purchase = (*weaponPurchases)[i]; + if (purchase.m_nItemDefIndex == weaponEntry.iItemDefIndex) + { + if (purchase.m_nCount >= weaponEntry.maxAmount) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You cannot buy any more %s (Max %i)", weaponEntry.szWeaponName, weaponEntry.maxAmount); + return; + } + purchase.m_nCount += 1; + found = true; + break; + } + } + + if (!found) + { + WeaponPurchaseCount_t purchase = {}; + + purchase.m_nCount = 1; + purchase.m_nItemDefIndex = weaponEntry.iItemDefIndex; + + weaponPurchases->AddToTail(purchase); + } + } + + CUtlVector>* weapons = pWeaponServices->m_hMyWeapons(); + + FOR_EACH_VEC(*weapons, i) + { + CHandle& weaponHandle = (*weapons)[i]; + + if (!weaponHandle.IsValid()) + continue; + + CBasePlayerWeapon* weapon = weaponHandle.Get(); + + if (!weapon) + continue; + + if (weapon->GetWeaponVData()->m_GearSlot() == weaponEntry.iGearSlot && (weaponEntry.iGearSlot == GEAR_SLOT_RIFLE || weaponEntry.iGearSlot == GEAR_SLOT_PISTOL)) + { + // Despite having to pass a weapon into DropPlayerWeapon, it only drops the weapon if it's also the players active weapon + pWeaponServices->m_hActiveWeapon = weaponHandle; + pItemServices->DropPlayerWeapon(weapon); + + break; + } + } + + player->m_pInGameMoneyServices->m_iAccount = money - weaponEntry.iPrice; + pItemServices->GiveNamedItem(weaponEntry.szClassName); + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You have purchased %s for $%i", weaponEntry.szWeaponName, weaponEntry.iPrice); +} + +void WeaponCommandCallback(const CCommandContext& context, const CCommand& args) +{ + CCSPlayerController* pController = nullptr; + if (context.GetPlayerSlot().Get() != -1) + pController = (CCSPlayerController*)g_pEntitySystem->GetBaseEntity((CEntityIndex)(context.GetPlayerSlot().Get() + 1)); + + // Only allow connected players to run chat commands + if (pController && !pController->IsConnected()) + return; + + ParseWeaponCommand(args, pController); +} + +void RegisterWeaponCommands() +{ + for (int i = 0; i < sizeof(WeaponMap) / sizeof(*WeaponMap); i++) + { + WeaponMapEntry_t weaponEntry = WeaponMap[i]; + + for (std::string alias : weaponEntry.aliases) + { + new CChatCommand(alias.c_str(), ParseWeaponCommand, "- Buys this weapon", ADMFLAG_NONE, CMDFLAG_NOHELP); + ConCommandRefAbstract ref; + + char cmdName[64]; + V_snprintf(cmdName, sizeof(cmdName), "%s%s", COMMAND_PREFIX, alias.c_str()); + + ConCommand command(&ref, cmdName, WeaponCommandCallback, "Buys this weapon", FCVAR_CLIENT_CAN_EXECUTE | FCVAR_LINKED_CONCOMMAND); + } + } +} void ParseChatCommand(const char *pMessage, CCSPlayerController *pController) { - if (!pController) + if (!pController || !pController->IsConnected()) return; CCommand args; - args.Tokenize(pMessage + 1); + args.Tokenize(pMessage); uint16 index = g_CommandList.Find(hash_32_fnv1a_const(args[0])); if (g_CommandList.IsValidIndex(index)) { - g_CommandList[index](args, pController); + (*g_CommandList[index])(args, pController); + } +} + +bool CChatCommand::CheckCommandAccess(CBasePlayerController *pPlayer, uint64 flags) +{ + if (!pPlayer) + return false; + + int slot = pPlayer->GetPlayerSlot(); + + ZEPlayer *pZEPlayer = g_playerManager->GetPlayer(slot); + + if (!pZEPlayer->IsAdminFlagSet(flags)) + { + ClientPrint(pPlayer, HUD_PRINTTALK, CHAT_PREFIX "You don't have access to this command."); + return false; } + return true; } void ClientPrintAll(int hud_dest, const char *msg, ...) @@ -69,6 +283,7 @@ void ClientPrintAll(int hud_dest, const char *msg, ...) va_end(args); addresses::UTIL_ClientPrintAll(hud_dest, buf, nullptr, nullptr, nullptr, nullptr); + ConMsg("%s\n", buf); } void ClientPrint(CBasePlayerController *player, int hud_dest, const char *msg, ...) @@ -81,9 +296,90 @@ void ClientPrint(CBasePlayerController *player, int hud_dest, const char *msg, . va_end(args); - addresses::ClientPrint(player, hud_dest, buf, nullptr, nullptr, nullptr, nullptr); + if (player) + addresses::ClientPrint(player, hud_dest, buf, nullptr, nullptr, nullptr, nullptr); + else + ConMsg("%s\n", buf); +} + +bool g_bEnableHide = false; +static int g_iDefaultHideDistance = 250; +static int g_iMaxHideDistance = 2000; + +FAKE_BOOL_CVAR(cs2f_hide_enable, "Whether to enable hide", g_bEnableHide, false, false) +FAKE_INT_CVAR(cs2f_hide_distance_default, "The default distance for hide", g_iDefaultHideDistance, 250, false) +FAKE_INT_CVAR(cs2f_hide_distance_max, "The max distance for hide", g_iMaxHideDistance, 2000, false) + + +CON_COMMAND_CHAT(help, "- Display list of commands in console") +{ + if (!player) + { + ClientPrint(player, HUD_PRINTCONSOLE, "The list of all commands is:"); + + FOR_EACH_VEC(g_CommandList, i) + { + CChatCommand *cmd = g_CommandList[i]; + + if (!cmd->IsCommandFlagSet(CMDFLAG_NOHELP)) + ClientPrint(player, HUD_PRINTCONSOLE, "c_%s %s", cmd->GetName(), cmd->GetDescription()); + } + + return; + } + + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "The list of all available commands will be shown in console."); + ClientPrint(player, HUD_PRINTCONSOLE, "The list of all commands you can use is:"); + + int iSlot = player->GetPlayerSlot(); + + ZEPlayer *pZEPlayer = g_playerManager->GetPlayer(iSlot); + + FOR_EACH_VEC(g_CommandList, i) + { + CChatCommand *cmd = g_CommandList[i]; + uint64 flags = cmd->GetAdminFlags(); + + if (pZEPlayer->IsAdminFlagSet(flags) && !cmd->IsCommandFlagSet(CMDFLAG_NOHELP)) + ClientPrint(player, HUD_PRINTCONSOLE, "!%s %s", cmd->GetName(), cmd->GetDescription()); + } + + ClientPrint(player, HUD_PRINTCONSOLE, "! can be replaced with / for a silent chat command, or c_ for console usage"); } +/* CVARS */ +// CONVAR_TODO +bool g_bEnableCoach = true; +bool g_bEnableRecord = true; +bool g_bEnableBan = true; +bool g_bEnableGag = true; +bool g_bEnableKick = true; +bool g_bEnablePause = true; +bool g_bEnablePraccSpawn = true; +bool g_bEnablePractice = true; +bool g_bEnableRcon = true; +bool g_bEnableRestore = true; +bool g_bEnableScrim = true; +bool g_bEnableSlay = true; +bool g_bEnableTeamControl = true; +bool g_bEnableTeleport = true; + +FAKE_BOOL_CVAR(cs2scrim_coach, "Whether to enable coach", g_bEnableCoach, true, false) +FAKE_BOOL_CVAR(cs2scrim_admin_ban, "Whether to enable ban", g_bEnableBan, true, false) +FAKE_BOOL_CVAR(cs2scrim_admin_gag, "Whether to enable gag", g_bEnableGag, true, false) +FAKE_BOOL_CVAR(cs2scrim_admin_kick, "Whether to enable kick", g_bEnableKick, true, false) +FAKE_BOOL_CVAR(cs2scrim_admin_slay, "Whether to enable slay", g_bEnableSlay, true, false) +FAKE_BOOL_CVAR(cs2scrim_pause, "Whether to enable pause", g_bEnablePause, true, false) +FAKE_BOOL_CVAR(cs2scrim_practice_spawn, "Whether to enable practice spawns", g_bEnablePraccSpawn, true, false) +FAKE_BOOL_CVAR(cs2scrim_pracc, "Whether to enable practice mode", g_bEnablePractice, true, false) +FAKE_BOOL_CVAR(cs2scrim_rcon, "Whether to enable rcon functionality", g_bEnableRcon, true, false) +FAKE_BOOL_CVAR(cs2scrim_demo, "Whether to enable demo recording", g_bEnableRecord, true, false) +FAKE_BOOL_CVAR(cs2scrim_restore, "Whether to enable round backup command", g_bEnableRestore, true, false) +FAKE_BOOL_CVAR(cs2scrim_scrim, "Whether to enable scrim command", g_bEnableScrim, true, false) +FAKE_BOOL_CVAR(cs2scrim_admin_team, "Whether to enable setteam by admin", g_bEnableTeamControl, true, false) +FAKE_BOOL_CVAR(cs2scrim_admin_teleport, "Whether to enable admin teleport", g_bEnableTeleport, true, false) + +/* Player commands */ CON_COMMAND_CHAT(myuid, "test") { if (!player) @@ -94,13 +390,15 @@ CON_COMMAND_CHAT(myuid, "test") ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Your userid is %i, slot: %i, retrieved slot: %i", g_pEngineServer2->GetPlayerUserId(iPlayer).Get(), iPlayer, g_playerManager->GetSlotFromUserId(g_pEngineServer2->GetPlayerUserId(iPlayer).Get())); } - bool match_paused = false; bool ct_ready = true; bool t_ready = true; CON_COMMAND_CHAT(pause, "Request pause") { + if(!g_bEnablePause) + return; + if (!player) return; @@ -110,7 +408,7 @@ CON_COMMAND_CHAT(pause, "Request pause") g_pEngineServer2->ServerCommand("mp_pause_match"); - ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"%s requested a pause", player->GetPlayerName()); + ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"\4%s \1requested a pause", player->GetPlayerName()); match_paused = true; ct_ready = false; @@ -119,6 +417,9 @@ CON_COMMAND_CHAT(pause, "Request pause") CON_COMMAND_CHAT(unpause, "Request unpause") { + if(!g_bEnablePause) + return; + if (!player) return; @@ -135,20 +436,38 @@ CON_COMMAND_CHAT(unpause, "Request unpause") } if(ct_ready && !t_ready){ - ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"CT ready, type .unpause"); + ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"CT \5ready\1, type \4.unpause"); return; }else if(!ct_ready && t_ready){ - ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"T ready, type .unpause"); + ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"T \5ready\1, type \4.unpause"); return; } match_paused = false; - ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"Match \2unpaused"); + ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"Match \4unpaused"); g_pEngineServer2->ServerCommand("mp_unpause_match"); } +CON_COMMAND_CHAT(noflash, "noflash"){ + + if (!player || !g_bEnablePractice) + return; + + if (!practiceMode){ + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Only available on practice mode"); + return; + } + + no_flash_mode = !no_flash_mode; + + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Flash mode set to \04%i", no_flash_mode); +} + CON_COMMAND_CHAT(spawn, "teleport to desired spawn") { + if (!g_bEnablePraccSpawn) + return; + if (!player) return; @@ -164,14 +483,36 @@ CON_COMMAND_CHAT(spawn, "teleport to desired spawn") } char teamName[256]; - if(player->m_iTeamNum == CS_TEAM_T){ - V_snprintf(teamName, sizeof(teamName), "info_player_terrorist"); - }else if(player->m_iTeamNum == CS_TEAM_CT){ - V_snprintf(teamName, sizeof(teamName), "info_player_counterterrorist"); + int target_team_number = CS_TEAM_NONE; + + if(args.ArgC() > 2){ + char team_id_input[256]; + V_snprintf(team_id_input, sizeof(team_id_input), "%s", args[2]); + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"%s ", args[2]); + if((std::string)team_id_input == "t"){ + target_team_number = CS_TEAM_T; + }else if((std::string)team_id_input == "ct"){ + target_team_number = CS_TEAM_CT; + }else{ + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Usage: !spawn "); + } }else{ + target_team_number = player->m_iTeamNum; + } + + if(target_team_number == CS_TEAM_SPECTATOR){ ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You cannot teleport in spectator!"); return; } + if(target_team_number == CS_TEAM_SPECTATOR){ + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You cannot teleport in spectator!"); + return; + } + if(target_team_number == CS_TEAM_T){ + V_snprintf(teamName, sizeof(teamName), "info_player_terrorist"); + }else{ + V_snprintf(teamName, sizeof(teamName), "info_player_counterterrorist"); + } //Count spawnpoints (info_player_counterterrorist & info_player_terrorist) SpawnPoint* spawn = nullptr; @@ -219,25 +560,31 @@ CON_COMMAND_CHAT(spawn, "teleport to desired spawn") } int totalSpawns = spawns.Count(); + + //ClientPrint(player, HUD_PRINTTALK, "Spawn: %f / %f / %f", spawnpos.x, spawnpos.y, spawnpos.z); + player->GetPawn()->Teleport(&spawnpos, nullptr, nullptr); - pPawn->SetAbsOrigin(spawnpos); - - ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You have been teleported to spawn. %i/%i priority:%i", spawnIndex +1, totalSpawns, spawn_priority); + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You have been teleported to spawn. %i/%i", spawnIndex +1, totalSpawns); } CUtlVector coaches; void print_coaches(){ + if (!g_bEnableCoach) + return; if (coaches.Count() < 1) return; ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"\5%i \1active \5coaches", coaches.Count()); FOR_EACH_VEC(coaches,i){ - ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"Coach %i: \5%s", i+1, coaches[i]->GetPlayerName()); + ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX"Coach %i: \4%s", i+1, coaches[i]->GetPlayerName()); } } CON_COMMAND_CHAT(coach, "Request slot coach") { + if(!g_bEnableCoach) + return; + if (!player) return; @@ -255,28 +602,48 @@ CON_COMMAND_CHAT(coach, "Request slot coach") coaches.AddToTail(player); - ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Coach enabled, type \4.uncoach \1to cancel"); - print_coaches(); + int target_team_number = CS_TEAM_SPECTATOR; + if(args.ArgC() > 1){ + char team_id_input[256]; + V_snprintf(team_id_input, sizeof(team_id_input), "%s", args[1]); + + if((std::string)team_id_input == "t"){ + target_team_number = CS_TEAM_T; + }else if((std::string)team_id_input == "ct"){ + target_team_number = CS_TEAM_CT; + }else{ + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Usage: .coach "); + } + }else{ + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Coach enabled, type \4.uncoach \1to cancel"); + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "You are on spectator mode, choose \4.ct \1or \4.t"); + } + + print_coaches(); CHandle hController = player->GetHandle(); // Gotta do this on the next frame... - new CTimer(0.0f, false, false, [hController]() + new CTimer(0.0f, false, [hController, target_team_number]() { CCSPlayerController *pController = hController.Get(); if (!pController) - return; - + return -1.0f; + + pController->ChangeTeam(target_team_number); pController->m_szClan = "Coaching:"; - return; + return -1.0f; }); } //Todo, unify different aliases CON_COMMAND_CHAT(uncoach, "Undo slot coach") { + if(!g_bEnableCoach) + return; + if (!player) return; @@ -298,4 +665,81 @@ CON_COMMAND_CHAT(uncoach, "Undo slot coach") } } ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "You haven't set as \4coach\1 yet"); +} + +CON_COMMAND_CHAT(ct, "Switch to CT side") +{ + if (!player || !g_bEnablePractice) + return; + + if (!practiceMode && player->m_iTeamNum != CS_TEAM_SPECTATOR) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Switch teams only available on .pracc mode"); + return; + } + + player->ChangeTeam(CS_TEAM_CT); +} + +CON_COMMAND_CHAT(t, "Switch to T side") +{ + if (!player || !g_bEnablePractice) + return; + + if (!practiceMode && player->m_iTeamNum != CS_TEAM_SPECTATOR) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Switch teams only available on .pracc mode"); + return; + } + + player->ChangeTeam(CS_TEAM_T); +} + +CON_COMMAND_CHAT(spec, "Switch to Spectator") +{ + if (!player || !g_bEnablePractice) + return; + + if (!practiceMode) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Switch teams only available on .pracc mode"); + return; + } + + player->ChangeTeam(CS_TEAM_SPECTATOR); +} + +CON_COMMAND_CHAT(side, "Switch to team selector") +{ + if (!player || !g_bEnablePractice) + return; + + if (!practiceMode) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Switch teams only available on .pracc mode"); + return; + } + + player->ChangeTeam(CS_TEAM_NONE); +} + +CON_COMMAND_CHAT(last, "Teleport to the last thrown grenade") +{ + if (!player || !g_bEnablePractice) + return; + + if (!practiceMode) + { + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Last grenade teleport only available on .pracc mode"); + return; + } + + ZEPlayer *pPlayer = g_playerManager->GetPlayer(player->GetPlayerSlot()); + + if(pPlayer->lastThrow_position.x == 0.0f && pPlayer->lastThrow_position.y == 0.0f && pPlayer->lastThrow_position.z == 0.0f){ + ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "No lineup saved"); + return; + } + + player->GetPawn()->Teleport(&pPlayer->lastThrow_position, &pPlayer->lastThrow_rotation, nullptr); } \ No newline at end of file diff --git a/src/commands.h b/src/commands.h index 3a31db32..68cb7b6c 100644 --- a/src/commands.h +++ b/src/commands.h @@ -20,13 +20,23 @@ #pragma once #include "entity/ccsplayercontroller.h" #include "convar.h" +#include "adminsystem.h" +#include + +#define CMDFLAG_NONE (0) +#define CMDFLAG_NOHELP (1 << 0) // Don't show in !help menu #define COMMAND_PREFIX "c_" #define CHAT_PREFIX " \3[CS2Scrim]\1 " typedef void (*FnChatCommandCallback_t)(const CCommand &args, CCSPlayerController *player); -extern CUtlMap g_CommandList; +class CChatCommand; + +extern CUtlMap g_CommandList; + +extern bool g_bEnableHide; +extern bool g_bEnableStopSound; void ClientPrintAll(int destination, const char *msg, ...); void ClientPrint(CBasePlayerController *player, int destination, const char *msg, ...); @@ -35,31 +45,71 @@ void ClientPrint(CBasePlayerController *player, int destination, const char *msg class CChatCommand { public: - CChatCommand(const char *cmd, FnChatCommandCallback_t callback) + CChatCommand(const char *cmd, FnChatCommandCallback_t callback, const char *description, uint64 adminFlags = ADMFLAG_NONE, uint64 cmdFlags = CMDFLAG_NONE) : + m_pfnCallback(callback), m_sName(cmd), m_sDescription(description), m_nAdminFlags(adminFlags), m_nCmdFlags(cmdFlags) + { + g_CommandList.Insert(hash_32_fnv1a_const(cmd), this); + } + + void operator()(const CCommand &args, CCSPlayerController *player) + { + // Only allow connected players to run chat commands + if (player && !player->IsConnected()) + return; + + // If the command is run from server console, ignore admin flags + if (player && !CheckCommandAccess(player, m_nAdminFlags)) + return; + + m_pfnCallback(args, player); + } + + static bool CheckCommandAccess(CBasePlayerController *pPlayer, uint64 flags); + + const char* GetName() { return m_sName.c_str(); } + const char* GetDescription() { return m_sDescription.c_str(); } + uint64 GetAdminFlags() { return m_nAdminFlags; } + bool IsCommandFlagSet(uint64 iFlag) { - g_CommandList.Insert(hash_32_fnv1a_const(cmd), callback); + return !iFlag || (m_nCmdFlags & iFlag); } + +private: + FnChatCommandCallback_t m_pfnCallback; + uint64 m_nAdminFlags; + uint64 m_nCmdFlags; + std::string m_sName; + std::string m_sDescription; }; struct WeaponMapEntry_t { - const char *command; - const char *szWeaponName; + std::vector aliases; + const char* szClassName; + const char* szWeaponName; int iPrice; uint16 iItemDefIndex; + gear_slot_t iGearSlot; int maxAmount = 0; }; +void RegisterWeaponCommands(); void ParseChatCommand(const char *, CCSPlayerController *); -#define CON_COMMAND_CHAT(name, description) \ - void name##_callback(const CCommand &args, CCSPlayerController *player); \ - static void name##_con_callback(const CCommandContext &context, const CCommand &args) \ - { \ - name##_callback(args, (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(context.GetPlayerSlot().Get() + 1))); \ - } \ - static CChatCommand name##_chat_command(#name, name##_callback); \ - static ConCommandRefAbstract name##_ref; \ - static ConCommand name##_command(&name##_ref, COMMAND_PREFIX #name, name##_con_callback, \ - description, FCVAR_CLIENT_CAN_EXECUTE | FCVAR_LINKED_CONCOMMAND); \ +#define CON_COMMAND_CHAT_FLAGS(name, description, flags) \ + void name##_callback(const CCommand &args, CCSPlayerController *player); \ + static CChatCommand name##_chat_command(#name, name##_callback, description, flags); \ + static void name##_con_callback(const CCommandContext &context, const CCommand &args) \ + { \ + CCSPlayerController *pController = nullptr; \ + if (context.GetPlayerSlot().Get() != -1) \ + pController = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(context.GetPlayerSlot().Get() + 1)); \ + \ + name##_chat_command(args, pController); \ + } \ + static ConCommandRefAbstract name##_ref; \ + static ConCommand name##_command(&name##_ref, COMMAND_PREFIX #name, name##_con_callback, \ + description, FCVAR_CLIENT_CAN_EXECUTE | FCVAR_LINKED_CONCOMMAND); \ void name##_callback(const CCommand &args, CCSPlayerController *player) + +#define CON_COMMAND_CHAT(name, description) CON_COMMAND_CHAT_FLAGS(name, description, ADMFLAG_NONE) diff --git a/src/common.h b/src/common.h index fc585160..4cda0418 100644 --- a/src/common.h +++ b/src/common.h @@ -45,7 +45,36 @@ void UnlockConVars(); void UnlockConCommands(); -void ToggleLogs(); void Message(const char *, ...); void Panic(const char *, ...); + +// CONVAR_TODO +// Need to replace with actual cvars once available in SDK +#define FAKE_CVAR(name, description, variable_name, variable_type, variable_type_format, variable_default, protect) \ + CON_COMMAND_F(name, description, FCVAR_LINKED_CONCOMMAND | FCVAR_SPONLY | (protect ? FCVAR_PROTECTED : FCVAR_NONE)) \ + { \ + if (args.ArgC() < 2) \ + Msg("%s " #variable_type_format "\n", args[0], variable_name); \ + else \ + variable_name = V_StringTo##variable_type(args[1], variable_default); \ + } + +#define FAKE_INT_CVAR(name, description, variable_name, variable_default, protect) \ + FAKE_CVAR(name, description, variable_name, Int32, %i, variable_default, protect) + +#define FAKE_BOOL_CVAR(name, description, variable_name, variable_default, protect) \ + FAKE_CVAR(name, description, variable_name, Bool, %i, variable_default, protect) + +#define FAKE_FLOAT_CVAR(name, description, variable_name, variable_default, protect) \ + FAKE_CVAR(name, description, variable_name, Float32, %f, variable_default, protect) + +// assumes std::string variable +#define FAKE_STRING_CVAR(name, description, variable_name, protect) \ + CON_COMMAND_F(name, description, FCVAR_LINKED_CONCOMMAND | FCVAR_SPONLY | (protect ? FCVAR_PROTECTED : FCVAR_NONE)) \ + { \ + if (args.ArgC() < 2) \ + Msg("%s %s\n", args[0], variable_name.c_str()); \ + else \ + variable_name = args[1]; \ + } \ No newline at end of file diff --git a/src/cs2_sdk/cschemasystem.h b/src/cs2_sdk/cschemasystem.h new file mode 100644 index 00000000..f51407cb --- /dev/null +++ b/src/cs2_sdk/cschemasystem.h @@ -0,0 +1,379 @@ +// Copyright (C) 2023 neverlosecc +// See end of file for extended copyright information. +/** + * ============================================================================= + * Source2Gen + * Copyright (C) 2023 neverlose (https://github.com/neverlosecc/source2gen) + * ============================================================================= + **/ + +#pragma once +#include "../utils/virtual.h" + +class CSchemaType; +class CSchemaSystemTypeScope; +class ISaveRestoreOps; + +enum SchemaClassFlags_t +{ + SCHEMA_CF1_HAS_VIRTUAL_MEMBERS = 1, + SCHEMA_CF1_IS_ABSTRACT = 2, + SCHEMA_CF1_HAS_TRIVIAL_CONSTRUCTOR = 4, + SCHEMA_CF1_HAS_TRIVIAL_DESTRUCTOR = 8, + SCHEMA_CF1_HAS_NOSCHEMA_MEMBERS = 16, + SCHEMA_CF1_IS_PARENT_CLASSES_PARSED = 32, + SCHEMA_CF1_IS_LOCAL_TYPE_SCOPE = 64, + SCHEMA_CF1_IS_GLOBAL_TYPE_SCOPE = 128, + SCHEMA_CF1_IS_SCHEMA_VALIDATED = 2048, + +}; + +enum ETypeCategory +{ + Schema_Builtin = 0, + Schema_Ptr = 1, + Schema_Bitfield = 2, + Schema_FixedArray = 3, + Schema_Atomic = 4, + Schema_DeclaredClass = 5, + Schema_DeclaredEnum = 6, + Schema_None = 7 +}; + +enum class schemafieldtype_t : uint8_t +{ + FIELD_VOID = 0x0, + FIELD_FLOAT32 = 0x1, + FIELD_STRING = 0x2, + FIELD_VECTOR = 0x3, + FIELD_QUATERNION = 0x4, + FIELD_INT32 = 0x5, + FIELD_BOOLEAN = 0x6, + FIELD_INT16 = 0x7, + FIELD_CHARACTER = 0x8, + FIELD_COLOR32 = 0x9, + FIELD_EMBEDDED = 0xa, + FIELD_CUSTOM = 0xb, + FIELD_CLASSPTR = 0xc, + FIELD_EHANDLE = 0xd, + FIELD_POSITION_VECTOR = 0xe, + FIELD_TIME = 0xf, + FIELD_TICK = 0x10, + FIELD_SOUNDNAME = 0x11, + FIELD_INPUT = 0x12, + FIELD_FUNCTION = 0x13, + FIELD_VMATRIX = 0x14, + FIELD_VMATRIX_WORLDSPACE = 0x15, + FIELD_MATRIX3X4_WORLDSPACE = 0x16, + FIELD_INTERVAL = 0x17, + FIELD_UNUSED = 0x18, + FIELD_VECTOR2D = 0x19, + FIELD_INT64 = 0x1a, + FIELD_VECTOR4D = 0x1b, + FIELD_RESOURCE = 0x1c, + FIELD_TYPEUNKNOWN = 0x1d, + FIELD_CSTRING = 0x1e, + FIELD_HSCRIPT = 0x1f, + FIELD_VARIANT = 0x20, + FIELD_UINT64 = 0x21, + FIELD_FLOAT64 = 0x22, + FIELD_POSITIVEINTEGER_OR_NULL = 0x23, + FIELD_HSCRIPT_NEW_INSTANCE = 0x24, + FIELD_UINT32 = 0x25, + FIELD_UTLSTRINGTOKEN = 0x26, + FIELD_QANGLE = 0x27, + FIELD_NETWORK_ORIGIN_CELL_QUANTIZED_VECTOR = 0x28, + FIELD_HMATERIAL = 0x29, + FIELD_HMODEL = 0x2a, + FIELD_NETWORK_QUANTIZED_VECTOR = 0x2b, + FIELD_NETWORK_QUANTIZED_FLOAT = 0x2c, + FIELD_DIRECTION_VECTOR_WORLDSPACE = 0x2d, + FIELD_QANGLE_WORLDSPACE = 0x2e, + FIELD_QUATERNION_WORLDSPACE = 0x2f, + FIELD_HSCRIPT_LIGHTBINDING = 0x30, + FIELD_V8_VALUE = 0x31, + FIELD_V8_OBJECT = 0x32, + FIELD_V8_ARRAY = 0x33, + FIELD_V8_CALLBACK_INFO = 0x34, + FIELD_UTLSTRING = 0x35, + FIELD_NETWORK_ORIGIN_CELL_QUANTIZED_POSITION_VECTOR = 0x36, + FIELD_HRENDERTEXTURE = 0x37, + FIELD_HPARTICLESYSTEMDEFINITION = 0x38, + FIELD_UINT8 = 0x39, + FIELD_UINT16 = 0x3a, + FIELD_CTRANSFORM = 0x3b, + FIELD_CTRANSFORM_WORLDSPACE = 0x3c, + FIELD_HPOSTPROCESSING = 0x3d, + FIELD_MATRIX3X4 = 0x3e, + FIELD_SHIM = 0x3f, + FIELD_CMOTIONTRANSFORM = 0x40, + FIELD_CMOTIONTRANSFORM_WORLDSPACE = 0x41, + FIELD_ATTACHMENT_HANDLE = 0x42, + FIELD_AMMO_INDEX = 0x43, + FIELD_CONDITION_ID = 0x44, + FIELD_AI_SCHEDULE_BITS = 0x45, + FIELD_MODIFIER_HANDLE = 0x46, + FIELD_ROTATION_VECTOR = 0x47, + FIELD_ROTATION_VECTOR_WORLDSPACE = 0x48, + FIELD_HVDATA = 0x49, + FIELD_SCALE32 = 0x4a, + FIELD_STRING_AND_TOKEN = 0x4b, + FIELD_ENGINE_TIME = 0x4c, + FIELD_ENGINE_TICK = 0x4d, + FIELD_WORLD_GROUP_ID = 0x4e, + FIELD_TYPECOUNT = 0x4f, +}; + +struct CSchemaVarName +{ + const char *m_name; + const char *m_type; +}; + +struct CSchemaNetworkValue +{ + union + { + const char *m_p_sz_value; + int m_n_value; + float m_f_value; + uintptr_t m_p_value; + CSchemaVarName m_var_value; + char m_sz_value[32]; + }; +}; + +struct SchemaMetadataEntryData_t +{ + const char *m_name; + CSchemaNetworkValue *m_value; +}; + +struct SchemaFieldMetadataOverrideData_t +{ + schemafieldtype_t m_field_type; // 0x0000 + char pad_0001[7]; // 0x0001 + const char *m_field_name; // 0x0008 + uint32_t m_single_inheritance_offset; // 0x0010 + int32_t m_field_count; // 0x0014 // @note: @og: if its array or smth like this it will point to count of array + int32_t m_i_unk_1; // 0x0018 + char pad_001C[12]; // 0x001C + ISaveRestoreOps *m_def_save_restore_ops; // 0x0028 + char pad_0030[16]; // 0x0030 + uint32_t m_align; // 0x0040 + char pad_0044[36]; // 0x0044 +}; // Size: 0x0068 + +struct SchemaFieldMetadataOverrideSetData_t +{ + SchemaFieldMetadataOverrideData_t *m_metadata_override_data; // 0x0008 + int32_t m_size; // 0x0008 +}; + +struct SchemaStaticFieldData_t +{ + const char *name; // 0x0000 + CSchemaType *m_type; // 0x0008 + void *m_instance; // 0x0010 + char pad_0x0018[0x10]; // 0x0018 +}; + +struct SchemaClassFieldData_t +{ + const char *m_name; // 0x0000 + void *m_type; // 0x0008 + int32 m_single_inheritance_offset; // 0x0010 + int32 m_metadata_size; // 0x0014 + SchemaMetadataEntryData_t *m_metadata; // 0x0018 +}; + +class SchemaEnumInfoData_t +{ +public: + SchemaEnumInfoData_t *m_self; // 0x0000 + const char *m_name; // 0x0008 + const char *m_module; // 0x0010 + int8_t m_align; // 0x0018 + char pad_0x0019[0x3]; // 0x0019 + int16_t m_size; // 0x001C + int16_t m_static_metadata_size; // 0x001E + void *m_enum_info; + SchemaMetadataEntryData_t *m_static_metadata; + CSchemaSystemTypeScope *m_type_scope; // 0x0030 + char pad_0x0038[0x8]; // 0x0038 + int32_t m_i_unk1; // 0x0040 +}; + +class SchemaClassInfoData_t; + +struct SchemaBaseClassInfoData_t +{ + unsigned int m_offset; + SchemaClassInfoData_t *m_class; +}; + +class SchemaClassInfoData_t +{ +public: + auto GetName() + { + return m_name; + } + + auto GetFieldsSize() + { + return m_fields_size; + } + + auto GetFields() + { + return m_fields; + } + + SchemaClassInfoData_t *GetParent() + { + if (!m_base_classes) + return nullptr; + + return m_base_classes->m_class; + } + +private: + SchemaClassInfoData_t *m_self; // 0x0000 + const char *m_name; // 0x0008 + const char *m_module; // 0x0010 + + int m_size; // 0x0018 + int16_t m_fields_size; // 0x001C + int16_t m_static_fields_size; // 0x001E + int16_t m_static_metadata_size; // 0x0020 + uint8_t m_align_of; // 0x0022 + uint8_t m_has_base_class; // 0x0023 + int16_t m_total_class_size; // 0x0024 // @note: @og: if there no derived or base class then it will be 1 otherwise derived class size + 1. + int16_t m_derived_class_size; // 0x0026 + SchemaClassFieldData_t *m_fields; // 0x0028 + SchemaStaticFieldData_t *m_static_fields; // 0x0030 + SchemaBaseClassInfoData_t *m_base_classes; // 0x0038 + SchemaFieldMetadataOverrideSetData_t *m_field_metadata_overrides; // 0x0040 + SchemaMetadataEntryData_t *m_static_metadata; // 0x0048 + CSchemaSystemTypeScope *m_type_scope; // 0x0050 + CSchemaType *m_schema_type; // 0x0058 + SchemaClassFlags_t m_class_flags : 8; // 0x0060 + uint32_t m_sequence; // 0x0064 // @note: @og: idk + void *m_fn; // 0x0068 +}; + +class CSchemaType +{ +public: + bool GetSizes(int *out_size1, uint8_t *unk_probably_not_size) + { + return reinterpret_cast(vftable_[3])(this, out_size1, unk_probably_not_size); + } + +public: + bool GetSize(int *out_size) + { + uint8_t smh = 0; + return GetSizes(out_size, &smh); + } + +public: + uintptr_t *vftable_; // 0x0000 + const char *m_name_; // 0x0008 + + CSchemaSystemTypeScope *m_type_scope_; // 0x0010 + uint8_t type_category; // ETypeCategory 0x0018 + uint8_t atomic_category; // EAtomicCategory 0x0019 + + // find out to what class pointer points. + CSchemaType *GetRefClass() const + { + if (type_category != Schema_Ptr) + return nullptr; + + auto ptr = m_schema_type_; + while (ptr && ptr->type_category == ETypeCategory::Schema_Ptr) + ptr = ptr->m_schema_type_; + + return ptr; + } + + struct array_t + { + uint32_t array_size; + uint32_t unknown; + CSchemaType *element_type_; + }; + + struct atomic_t + { // same goes for CollectionOfT + uint64_t gap[2]; + CSchemaType *template_typename; + }; + + struct atomic_tt + { + uint64_t gap[2]; + CSchemaType *templates[2]; + }; + + struct atomic_i + { + uint64_t gap[2]; + uint64_t integer; + }; + + // this union depends on CSchema implementation, all members above + // is from base class ( CSchemaType ) + union // 0x020 + { + CSchemaType *m_schema_type_; + SchemaClassInfoData_t *m_class_info; + SchemaEnumInfoData_t *m_enum_binding_; + array_t m_array_; + atomic_t m_atomic_t_; + atomic_tt m_atomic_tt_; + atomic_i m_atomic_i_; + }; +}; + +class CSchemaSystemTypeScope +{ +public: + SchemaClassInfoData_t *FindDeclaredClass(const char *pClass) + { +#ifdef _WIN32 + SchemaClassInfoData_t *rv = nullptr; + CALL_VIRTUAL(void, 2, this, &rv, pClass); + return rv; +#else + return CALL_VIRTUAL(SchemaClassInfoData_t*, 2, this, pClass); +#endif + } +}; + +class CSchemaSystem +{ +public: + auto FindTypeScopeForModule(const char *module) + { + return CALL_VIRTUAL(CSchemaSystemTypeScope *, 13, this, module, nullptr); + } +}; + +// source2gen - Source2 games SDK generator +// Copyright 2023 neverlosecc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// diff --git a/src/cs2_sdk/entity/cbaseentity.h b/src/cs2_sdk/entity/cbaseentity.h index dd5130d0..3dc2380b 100644 --- a/src/cs2_sdk/entity/cbaseentity.h +++ b/src/cs2_sdk/entity/cbaseentity.h @@ -19,38 +19,17 @@ #pragma once -#include "../schema.h" +#include "schema.h" #include "ccollisionproperty.h" +#include "globaltypes.h" +#include "ctakedamageinfo.h" #include "mathlib/vector.h" #include "ehandle.h" +#include "entitykeyvalues.h" #include "../../gameconfig.h" -CGlobalVars* GetGameGlobals(); - extern CGameConfig *g_GameConfig; -class CNetworkTransmitComponent -{ -public: - DECLARE_SCHEMA_CLASS_INLINE(CNetworkTransmitComponent) -}; - -class CNetworkOriginCellCoordQuantizedVector -{ -public: - DECLARE_SCHEMA_CLASS_INLINE(CNetworkOriginCellCoordQuantizedVector) - - SCHEMA_FIELD(uint16, m_cellX) - SCHEMA_FIELD(uint16, m_cellY) - SCHEMA_FIELD(uint16, m_cellZ) - SCHEMA_FIELD(uint16, m_nOutsideWorld) - - // These are actually CNetworkedQuantizedFloat but we don't have the definition for it... - SCHEMA_FIELD(float, m_vecX) - SCHEMA_FIELD(float, m_vecY) - SCHEMA_FIELD(float, m_vecZ) -}; - class CGameSceneNode { public: @@ -112,6 +91,12 @@ class CBodyComponent SCHEMA_FIELD(CGameSceneNode *, m_pSceneNode) }; +class CEntitySubclassVDataBase +{ +public: + DECLARE_SCHEMA_CLASS(CEntitySubclassVDataBase) +}; + class Z_CBaseEntity : public CBaseEntity { public: @@ -125,20 +110,42 @@ class Z_CBaseEntity : public CBaseEntity SCHEMA_FIELD(float, m_lastNetworkChange) SCHEMA_FIELD_POINTER(CNetworkTransmitComponent, m_NetworkTransmitComponent) SCHEMA_FIELD(int, m_iHealth) + SCHEMA_FIELD(int, m_iMaxHealth) SCHEMA_FIELD(int, m_iTeamNum) + SCHEMA_FIELD(bool, m_bLagCompensate) + SCHEMA_FIELD(Vector, m_vecAbsVelocity) SCHEMA_FIELD(Vector, m_vecBaseVelocity) SCHEMA_FIELD(CCollisionProperty*, m_pCollision) SCHEMA_FIELD(MoveType_t, m_MoveType) + SCHEMA_FIELD(MoveType_t, m_nActualMoveType) SCHEMA_FIELD(uint32, m_spawnflags) SCHEMA_FIELD(uint32, m_fFlags) SCHEMA_FIELD(LifeState_t, m_lifeState) + SCHEMA_FIELD_POINTER(CUtlStringToken, m_nSubclassID) + SCHEMA_FIELD(float, m_flGravityScale) + SCHEMA_FIELD(float, m_flSpeed) + SCHEMA_FIELD(CUtlString, m_sUniqueHammerID); int entindex() { return m_pEntity->m_EHandle.GetEntryIndex(); } Vector GetAbsOrigin() { return m_CBodyComponent->m_pSceneNode->m_vecAbsOrigin; } + QAngle GetAbsRotation() { return m_CBodyComponent->m_pSceneNode->m_angAbsRotation; } void SetAbsOrigin(Vector vecOrigin) { m_CBodyComponent->m_pSceneNode->m_vecAbsOrigin = vecOrigin; } + void SetAbsRotation(QAngle angAbsRotation) { m_CBodyComponent->m_pSceneNode->m_angAbsRotation = angAbsRotation; } + + void SetAbsVelocity(Vector vecVelocity) { m_vecAbsVelocity = vecVelocity; } + void SetBaseVelocity(Vector vecVelocity) { m_vecBaseVelocity = vecVelocity; } - void Teleport(Vector *position, QAngle *angles, Vector *velocity) { static int offset = g_GameConfig->GetOffset("Teleport"); CALL_VIRTUAL(void, offset, this, position, angles, velocity); } + void TakeDamage(int iDamage) + { + m_iHealth = m_iHealth() - iDamage; + } + + void Teleport(Vector *position, QAngle *angles, Vector *velocity) + { + static int offset = g_GameConfig->GetOffset("Teleport"); + CALL_VIRTUAL(void, offset, this, position, angles, velocity); + } void CollisionRulesChanged() { @@ -149,29 +156,53 @@ class Z_CBaseEntity : public CBaseEntity bool IsPawn() { static int offset = g_GameConfig->GetOffset("IsEntityPawn"); - CALL_VIRTUAL(bool, offset, this); + return CALL_VIRTUAL(bool, offset, this); } bool IsController() { static int offset = g_GameConfig->GetOffset("IsEntityController"); - CALL_VIRTUAL(bool, offset, this); + return CALL_VIRTUAL(bool, offset, this); + } + + void AcceptInput(const char *pInputName, variant_t value = variant_t(""), CEntityInstance *pActivator = nullptr, CEntityInstance *pCaller = nullptr) + { + //addresses::CEntityInstance_AcceptInput(this, pInputName, pActivator, pCaller, &value, 0); } bool IsAlive() { return m_lifeState == LifeState_t::LIFE_ALIVE; } CHandle GetHandle() { return m_pEntity->m_EHandle; } - static Z_CBaseEntity* EntityFromHandle(CHandle handle) { - if (!handle.IsValid()) - return nullptr; + // A double pointer to entity VData is available 4 bytes past m_nSubclassID, if applicable + CEntitySubclassVDataBase* GetVData() { return *(CEntitySubclassVDataBase**)((uint8*)(m_nSubclassID()) + 4); } - auto entity = handle.Get(); + void DispatchSpawn(CEntityKeyValues *pEntityKeyValues = nullptr) + { + //addresses::DispatchSpawn(this, pEntityKeyValues); + } - if (entity && entity->m_pEntity->m_EHandle == handle) - return (Z_CBaseEntity*) entity; + // Emit a sound event + void EmitSound(const char *pszSound, int nPitch = 100, float flVolume = 1.0, float flDelay = 0.0) + { + addresses::CBaseEntity_EmitSoundParams(this, pszSound, nPitch, flVolume, flDelay); + } + + // This was needed so we can parent to nameless entities using pointers + void SetParent(Z_CBaseEntity *pNewParent) + { + addresses::CBaseEntity_SetParent(this, pNewParent, 0, nullptr); + } - return nullptr; + void Remove() + { + addresses::UTIL_Remove(this); + } + + void SetMoveType(MoveType_t nMoveType) + { + m_MoveType = nMoveType; // necessary to maintain client prediction + m_nActualMoveType = nMoveType; } }; diff --git a/src/cs2_sdk/entity/cbasemodelentity.h b/src/cs2_sdk/entity/cbasemodelentity.h index de2e1b4b..2eff494e 100644 --- a/src/cs2_sdk/entity/cbasemodelentity.h +++ b/src/cs2_sdk/entity/cbasemodelentity.h @@ -20,7 +20,7 @@ #pragma once #include "cbaseentity.h" -#include "cglowproperty.h" +#include "globaltypes.h" class CBaseModelEntity : public Z_CBaseEntity { @@ -29,4 +29,10 @@ class CBaseModelEntity : public Z_CBaseEntity SCHEMA_FIELD(CCollisionProperty , m_Collision) SCHEMA_FIELD(CGlowProperty, m_Glow) + SCHEMA_FIELD(Color, m_clrRender) + + void SetModel(const char *szModel) + { + //addresses::CBaseModelEntity_SetModel(this, szModel); + } }; \ No newline at end of file diff --git a/src/cs2_sdk/entity/cbaseplayercontroller.h b/src/cs2_sdk/entity/cbaseplayercontroller.h index ef431379..7b102c93 100644 --- a/src/cs2_sdk/entity/cbaseplayercontroller.h +++ b/src/cs2_sdk/entity/cbaseplayercontroller.h @@ -47,4 +47,9 @@ class CBasePlayerController : public Z_CBaseEntity CBasePlayerPawn *GetPawn() { return m_hPawn.Get(); } const char *GetPlayerName() { return m_iszPlayerName(); } int GetPlayerSlot() { return entindex() - 1; } + bool IsConnected() { return m_iConnected() == PlayerConnectedState::PlayerConnected; } + void SetPawn(CCSPlayerPawn* pawn) + { + addresses::CBasePlayerController_SetPawn(this, pawn, true, false); + } }; \ No newline at end of file diff --git a/src/cs2_sdk/entity/cbaseplayerpawn.h b/src/cs2_sdk/entity/cbaseplayerpawn.h index 7e039879..4d6c15f6 100644 --- a/src/cs2_sdk/entity/cbaseplayerpawn.h +++ b/src/cs2_sdk/entity/cbaseplayerpawn.h @@ -29,13 +29,23 @@ class CBasePlayerPawn : public CBaseModelEntity DECLARE_SCHEMA_CLASS(CBasePlayerPawn); SCHEMA_FIELD(CPlayer_MovementServices*, m_pMovementServices) - SCHEMA_FIELD(uint8*, m_pWeaponServices) + SCHEMA_FIELD(CPlayer_WeaponServices*, m_pWeaponServices) SCHEMA_FIELD(CCSPlayer_ItemServices*, m_pItemServices) SCHEMA_FIELD(CHandle, m_hController) + void TakeDamage(int iDamage) + { + if (m_iHealth() - iDamage <= 0) + CommitSuicide(false, true); + else + Z_CBaseEntity::TakeDamage(iDamage); + } + void CommitSuicide(bool bExplode, bool bForce) { static int offset = g_GameConfig->GetOffset("CBasePlayerPawn_CommitSuicide"); CALL_VIRTUAL(void, offset, this, bExplode, bForce); } + + CBasePlayerController *GetController() { return m_hController.Get(); } }; \ No newline at end of file diff --git a/src/cs2_sdk/entity/ccollisionproperty.h b/src/cs2_sdk/entity/ccollisionproperty.h index 5fa4c43e..040c6e9f 100644 --- a/src/cs2_sdk/entity/ccollisionproperty.h +++ b/src/cs2_sdk/entity/ccollisionproperty.h @@ -19,7 +19,7 @@ #pragma once -#include "../schema.h" +#include "cbaseentity.h" struct VPhysicsCollisionAttribute_t { diff --git a/src/cs2_sdk/entity/ccsplayercontroller.h b/src/cs2_sdk/entity/ccsplayercontroller.h index da9e86a5..8f71f256 100644 --- a/src/cs2_sdk/entity/ccsplayercontroller.h +++ b/src/cs2_sdk/entity/ccsplayercontroller.h @@ -21,9 +21,9 @@ #include "cbaseplayercontroller.h" #include "services.h" -#include "tier1/utlmap.h" +#include "../playermanager.h" -extern CEntitySystem* g_pEntitySystem; +extern CGameEntitySystem* g_pEntitySystem; class CCSPlayerController : public CBasePlayerController { @@ -33,15 +33,23 @@ class CCSPlayerController : public CBasePlayerController SCHEMA_FIELD(CCSPlayerController_InGameMoneyServices*, m_pInGameMoneyServices) SCHEMA_FIELD(CCSPlayerController_ActionTrackingServices*, m_pActionTrackingServices) SCHEMA_FIELD(CUtlSymbolLarge, m_szClan) + SCHEMA_FIELD(bool, m_bPawnIsAlive); + SCHEMA_FIELD(CHandle, m_hPlayerPawn); - static CCSPlayerController* FromPawn(CCSPlayerPawn* pawn) { return (CCSPlayerController*)pawn->m_hController().Get(); } + static CCSPlayerController* FromPawn(CCSPlayerPawn* pawn) { + return (CCSPlayerController*)pawn->m_hController().Get(); + } - static CCSPlayerController* FromSlot(CPlayerSlot slot) { return (CCSPlayerController*)g_pEntitySystem->GetBaseEntity(CEntityIndex(slot.Get() + 1)); } + ZEPlayer* GetZEPlayer() + { + return g_playerManager->GetPlayer(GetPlayerSlot()); + } + void ChangeTeam(int iTeam) { static int offset = g_GameConfig->GetOffset("CCSPlayerController_ChangeTeam"); @@ -62,4 +70,15 @@ class CCSPlayerController : public CBasePlayerController addresses::CCSPlayerController_SwitchTeam(this, iTeam); } } + + void Respawn() + { + CCSPlayerPawn *pPawn = m_hPlayerPawn.Get(); + if (!pPawn || pPawn->IsAlive()) + return; + + SetPawn(pPawn); + static int offset = g_GameConfig->GetOffset("CCSPlayerController_Respawn"); + CALL_VIRTUAL(void, offset, this); + } }; \ No newline at end of file diff --git a/src/cs2_sdk/entity/ccsplayerpawn.h b/src/cs2_sdk/entity/ccsplayerpawn.h index 84c3aa7b..ce34e6f6 100644 --- a/src/cs2_sdk/entity/ccsplayerpawn.h +++ b/src/cs2_sdk/entity/ccsplayerpawn.h @@ -21,7 +21,16 @@ #include "cbaseplayerpawn.h" -class CCSPlayerPawn : public CBasePlayerPawn +class CCSPlayerPawnBase : public CBasePlayerPawn +{ +public: + DECLARE_SCHEMA_CLASS(CCSPlayerPawnBase); + SCHEMA_FIELD(QAngle, m_angEyeAngles) + SCHEMA_FIELD(float, m_flVelocityModifier) + SCHEMA_FIELD(float, m_flFlashMaxAlpha) +}; + +class CCSPlayerPawn : public CCSPlayerPawnBase { public: DECLARE_SCHEMA_CLASS(CCSPlayerPawn); diff --git a/src/cs2_sdk/entity/ccsweaponbase.h b/src/cs2_sdk/entity/ccsweaponbase.h index 82194f11..80417df6 100644 --- a/src/cs2_sdk/entity/ccsweaponbase.h +++ b/src/cs2_sdk/entity/ccsweaponbase.h @@ -19,7 +19,28 @@ #pragma once -#include "schema.h" +#include "cbaseentity.h" + +enum gear_slot_t : uint32_t +{ + GEAR_SLOT_INVALID = 0xffffffff, + GEAR_SLOT_RIFLE = 0x0, + GEAR_SLOT_PISTOL = 0x1, + GEAR_SLOT_KNIFE = 0x2, + GEAR_SLOT_GRENADES = 0x3, + GEAR_SLOT_C4 = 0x4, + GEAR_SLOT_RESERVED_SLOT6 = 0x5, + GEAR_SLOT_RESERVED_SLOT7 = 0x6, + GEAR_SLOT_RESERVED_SLOT8 = 0x7, + GEAR_SLOT_RESERVED_SLOT9 = 0x8, + GEAR_SLOT_RESERVED_SLOT10 = 0x9, + GEAR_SLOT_RESERVED_SLOT11 = 0xa, + GEAR_SLOT_BOOSTS = 0xb, + GEAR_SLOT_UTILITY = 0xc, + GEAR_SLOT_COUNT = 0xd, + GEAR_SLOT_FIRST = 0x0, + GEAR_SLOT_LAST = 0xc, +}; class CEconItemView { @@ -46,9 +67,33 @@ class CEconEntity : public Z_CBaseEntity SCHEMA_FIELD(CAttributeContainer, m_AttributeManager) }; -class CCSWeaponBase : public CEconEntity +class CBasePlayerWeaponVData : public CEntitySubclassVDataBase { public: - DECLARE_SCHEMA_CLASS(CCSWeaponBase) + DECLARE_SCHEMA_CLASS(CBasePlayerWeaponVData) + SCHEMA_FIELD(int, m_iMaxClip1) +}; + +class CCSWeaponBaseVData : public CBasePlayerWeaponVData +{ +public: + DECLARE_SCHEMA_CLASS(CCSWeaponBaseVData) + + SCHEMA_FIELD(gear_slot_t, m_GearSlot) + SCHEMA_FIELD(int, m_nPrice) + SCHEMA_FIELD(int, m_nPrimaryReserveAmmoMax); }; +class CBasePlayerWeapon : public CEconEntity +{ +public: + DECLARE_SCHEMA_CLASS(CBasePlayerWeapon) + + CCSWeaponBaseVData* GetWeaponVData() { return (CCSWeaponBaseVData*)GetVData(); } +}; + +class CCSWeaponBase : public CBasePlayerWeapon +{ +public: + DECLARE_SCHEMA_CLASS(CCSWeaponBase) +}; diff --git a/src/cs2_sdk/entity/cgamerules.h b/src/cs2_sdk/entity/cgamerules.h new file mode 100644 index 00000000..dea3f571 --- /dev/null +++ b/src/cs2_sdk/entity/cgamerules.h @@ -0,0 +1,85 @@ +/** + * ============================================================================= + * CS2Fixes + * Copyright (C) 2023 Source2ZE + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once +#include +#include "globaltypes.h" +#include "cbaseentity.h" + +enum CSRoundEndReason +{ + TargetBombed = 1, /**< Target Successfully Bombed! */ + VIPEscaped, /**< The VIP has escaped! - Doesn't exist on CS:GO */ + VIPKilled, /**< VIP has been assassinated! - Doesn't exist on CS:GO */ + TerroristsEscaped, /**< The terrorists have escaped! */ + CTStoppedEscape, /**< The CTs have prevented most of the terrorists from escaping! */ + TerroristsStopped, /**< Escaping terrorists have all been neutralized! */ + BombDefused, /**< The bomb has been defused! */ + CTWin, /**< Counter-Terrorists Win! */ + TerroristWin, /**< Terrorists Win! */ + Draw, /**< Round Draw! */ + HostagesRescued, /**< All Hostages have been rescued! */ + TargetSaved, /**< Target has been saved! */ + HostagesNotRescued, /**< Hostages have not been rescued! */ + TerroristsNotEscaped, /**< Terrorists have not escaped! */ + VIPNotEscaped, /**< VIP has not escaped! - Doesn't exist on CS:GO */ + GameStart, /**< Game Commencing! */ + TerroristsSurrender, /**< Terrorists Surrender */ + CTSurrender, /**< CTs Surrender */ + TerroristsPlanted, /**< Terrorists Planted the bomb */ + CTsReachedHostage, /**< CTs Reached the hostage */ + SurvivalWin, + SurvivalDraw +}; + +class CGameRules +{ +public: + DECLARE_SCHEMA_CLASS(CGameRules) +}; + +class CCSGameRules : public CGameRules +{ +public: + DECLARE_SCHEMA_CLASS(CCSGameRules) + + SCHEMA_FIELD(float, m_fMatchStartTime) + SCHEMA_FIELD(float, m_flGameStartTime) + SCHEMA_FIELD(int, m_totalRoundsPlayed) + SCHEMA_FIELD(GameTime_t, m_fRoundStartTime) + SCHEMA_FIELD(GameTime_t, m_flRestartRoundTime) + SCHEMA_FIELD_POINTER(int, m_nEndMatchMapGroupVoteOptions) + SCHEMA_FIELD(int, m_nEndMatchMapVoteWinner) + SCHEMA_FIELD(int, m_iRoundTime) + SCHEMA_FIELD_POINTER(CUtlVector, m_CTSpawnPoints) + SCHEMA_FIELD_POINTER(CUtlVector, m_TerroristSpawnPoints) +/* + void TerminateRound(float flDelay, CSRoundEndReason reason) + { + addresses::CGameRules_TerminateRound(this, flDelay, reason, 0, 0); + }*/ +}; + +class CCSGameRulesProxy : public Z_CBaseEntity +{ +public: + DECLARE_SCHEMA_CLASS(CCSGameRulesProxy) + + SCHEMA_FIELD(CCSGameRules *, m_pGameRules) +}; \ No newline at end of file diff --git a/src/cs2_sdk/entity/centityidentity.h b/src/cs2_sdk/entity/cparticlesystem.h similarity index 71% rename from src/cs2_sdk/entity/centityidentity.h rename to src/cs2_sdk/entity/cparticlesystem.h index 992afa32..27e7c6b7 100644 --- a/src/cs2_sdk/entity/centityidentity.h +++ b/src/cs2_sdk/entity/cparticlesystem.h @@ -18,15 +18,18 @@ */ #pragma once -#include -class IHandleEntity; -class CEntityClass; +#include "cbasemodelentity.h" -class CEntityIdentity +class CParticleSystem : public CBaseModelEntity { public: - IHandleEntity* m_pInstance; - CEntityClass* m_pClass; - CHandle m_EHandle; + DECLARE_SCHEMA_CLASS(CParticleSystem); + + SCHEMA_FIELD(bool, m_bActive) + SCHEMA_FIELD(bool, m_bStartActive) + SCHEMA_FIELD(bool, m_bFrozen) + SCHEMA_FIELD(CUtlSymbolLarge, m_iszEffectName) + SCHEMA_FIELD(int, m_nTintCP) + SCHEMA_FIELD_POINTER(Color, m_clrTint) }; \ No newline at end of file diff --git a/src/cs2_sdk/entity/ctakedamageinfo.h b/src/cs2_sdk/entity/ctakedamageinfo.h new file mode 100644 index 00000000..449cdfff --- /dev/null +++ b/src/cs2_sdk/entity/ctakedamageinfo.h @@ -0,0 +1,109 @@ +/** + * ============================================================================= + * CS2Fixes + * Copyright (C) 2023 Source2ZE + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once +#include +#include "ehandle.h" + +enum DamageTypes_t : uint32_t +{ + DMG_GENERIC = 0x0, + DMG_CRUSH = 0x1, + DMG_BULLET = 0x2, + DMG_SLASH = 0x4, + DMG_BURN = 0x8, + DMG_VEHICLE = 0x10, + DMG_FALL = 0x20, + DMG_BLAST = 0x40, + DMG_CLUB = 0x80, + DMG_SHOCK = 0x100, + DMG_SONIC = 0x200, + DMG_ENERGYBEAM = 0x400, + DMG_DROWN = 0x4000, + DMG_POISON = 0x8000, + DMG_RADIATION = 0x10000, + DMG_DROWNRECOVER = 0x20000, + DMG_ACID = 0x40000, + DMG_PHYSGUN = 0x100000, + DMG_DISSOLVE = 0x200000, + DMG_BLAST_SURFACE = 0x400000, + DMG_BUCKSHOT = 0x1000000, + DMG_LASTGENERICFLAG = 0x1000000, + DMG_HEADSHOT = 0x2000000, + DMG_DANGERZONE = 0x4000000, +}; + +enum TakeDamageFlags_t : uint32_t +{ + DFLAG_NONE = 0x0, + DFLAG_SUPPRESS_HEALTH_CHANGES = 0x1, + DFLAG_SUPPRESS_PHYSICS_FORCE = 0x2, + DFLAG_SUPPRESS_EFFECTS = 0x4, + DFLAG_PREVENT_DEATH = 0x8, + DFLAG_FORCE_DEATH = 0x10, + DFLAG_ALWAYS_GIB = 0x20, + DFLAG_NEVER_GIB = 0x40, + DFLAG_REMOVE_NO_RAGDOLL = 0x80, + DFLAG_SUPPRESS_DAMAGE_MODIFICATION = 0x100, + DFLAG_ALWAYS_FIRE_DAMAGE_EVENTS = 0x200, + DFLAG_RADIUS_DMG = 0x400, + DMG_LASTDFLAG = 0x400, + DFLAG_IGNORE_ARMOR = 0x800, +}; + +class CTakeDamageInfo +{ +private: + [[maybe_unused]] uint8_t __pad0000[0x8]; + +public: + Vector m_vecDamageForce; + Vector m_vecDamagePosition; + Vector m_vecReportedPosition; + Vector m_vecDamageDirection; + CHandle m_hInflictor; + CHandle m_hAttacker; + CHandle m_hAbility; + float m_flDamage; + DamageTypes_t m_bitsDamageType; + int32_t m_iDamageCustom; + uint8_t m_iAmmoType; + +private: + [[maybe_unused]] uint8_t __pad0051[0xf]; + +public: + float m_flOriginalDamage; + bool m_bShouldBleed; + bool m_bShouldSpark; + +private: + [[maybe_unused]] uint8_t __pad0066[0xa]; + +public: + TakeDamageFlags_t m_nDamageFlags; + int32_t m_nNumObjectsPenetrated; + uint64_t m_hScriptInstance; + +private: + [[maybe_unused]] uint8_t __pad0080[0x14]; + +public: + bool m_bInTakeDamageFlow; +}; diff --git a/src/cs2_sdk/entity/cglowproperty.h b/src/cs2_sdk/entity/cteam.h similarity index 72% rename from src/cs2_sdk/entity/cglowproperty.h rename to src/cs2_sdk/entity/cteam.h index c6d20d1a..022274e4 100644 --- a/src/cs2_sdk/entity/cglowproperty.h +++ b/src/cs2_sdk/entity/cteam.h @@ -17,18 +17,19 @@ * this program. If not, see . */ + #pragma once #include "cbaseentity.h" +#include "cbaseplayercontroller.h" +#include "cbaseplayerpawn.h" -class CGlowProperty +class CTeam : public Z_CBaseEntity { public: - DECLARE_SCHEMA_CLASS_INLINE(CGlowProperty) + DECLARE_SCHEMA_CLASS(CTeam); + + SCHEMA_FIELD_POINTER(CUtlVector>, m_aPlayerControllers) + SCHEMA_FIELD_POINTER(CUtlVector>, m_aPlayers) - SCHEMA_FIELD(Vector, m_fGlowColor) - SCHEMA_FIELD(int, m_iGlowType) - SCHEMA_FIELD(int, m_nGlowRange) - SCHEMA_FIELD(Color, m_glowColorOverride) - SCHEMA_FIELD(bool, m_bFlashing) - SCHEMA_FIELD(bool, m_bGlowing) -}; \ No newline at end of file + SCHEMA_FIELD(int32_t, m_iScore) +}; diff --git a/src/cs2_sdk/entity/ctriggerpush.h b/src/cs2_sdk/entity/ctriggerpush.h index 2d420dda..79da0ea7 100644 --- a/src/cs2_sdk/entity/ctriggerpush.h +++ b/src/cs2_sdk/entity/ctriggerpush.h @@ -1,264 +1,21 @@ #pragma once -#include "cbaseentity.h" +#include "cbasemodelentity.h" #include"../schema.h" #define SF_TRIG_PUSH_ONCE 0x80 -class CTriggerPush +class CTriggerPush : public CBaseModelEntity { public: DECLARE_SCHEMA_CLASS(CTriggerPush); SCHEMA_FIELD(Vector, m_vecPushDirEntitySpace) - SCHEMA_FIELD(float, m_flPushSpeed) + SCHEMA_FIELD(bool, m_bTriggerOnStartTouch) - virtual ~CTriggerPush() = 0; - -private: - virtual void unk_01() = 0; - virtual void unk_02() = 0; - virtual void unk_03() = 0; - virtual void unk_04() = 0; - virtual void unk_05() = 0; - virtual void unk_06() = 0; - virtual void unk_07() = 0; - virtual void unk_08() = 0; - virtual void unk_09() = 0; - virtual void unk_10() = 0; - virtual void unk_11() = 0; - virtual void unk_12() = 0; - virtual void unk_13() = 0; - virtual void unk_14() = 0; - virtual void unk_15() = 0; - virtual void unk_16() = 0; - virtual void unk_17() = 0; - virtual void unk_18() = 0; - virtual void unk_19() = 0; - virtual void unk_20() = 0; - virtual void unk_21() = 0; - virtual void unk_22() = 0; - virtual void unk_23() = 0; - virtual void unk_24() = 0; - virtual void unk_25() = 0; - virtual void unk_26() = 0; - virtual void unk_27() = 0; - virtual void unk_28() = 0; - virtual void unk_29() = 0; - virtual void unk_30() = 0; - virtual void unk_31() = 0; - virtual void unk_32() = 0; - virtual void unk_33() = 0; - virtual void unk_34() = 0; - virtual void unk_35() = 0; - virtual void unk_36() = 0; - virtual void unk_37() = 0; - virtual void unk_38() = 0; - virtual void unk_39() = 0; - virtual void unk_40() = 0; - virtual void unk_41() = 0; - virtual void unk_42() = 0; - virtual void unk_43() = 0; - virtual void unk_44() = 0; - virtual void unk_45() = 0; - virtual void unk_46() = 0; - virtual void unk_47() = 0; - virtual void unk_48() = 0; - virtual void unk_49() = 0; - virtual void unk_50() = 0; - virtual void unk_51() = 0; - virtual void unk_52() = 0; - virtual void unk_53() = 0; - virtual void unk_54() = 0; - virtual void unk_55() = 0; - virtual void unk_56() = 0; - virtual void unk_57() = 0; - virtual void unk_58() = 0; - virtual void unk_59() = 0; - virtual void unk_60() = 0; - virtual void unk_61() = 0; - virtual void unk_62() = 0; - virtual void unk_63() = 0; - virtual void unk_64() = 0; - virtual void unk_65() = 0; - virtual void unk_66() = 0; - virtual void unk_67() = 0; - virtual void unk_68() = 0; - virtual void unk_69() = 0; - virtual void unk_70() = 0; - virtual void unk_71() = 0; - virtual void unk_72() = 0; - virtual void unk_73() = 0; - virtual void unk_74() = 0; - virtual void unk_75() = 0; - virtual void unk_76() = 0; - virtual void unk_77() = 0; - virtual void unk_78() = 0; - virtual void unk_79() = 0; - virtual void unk_80() = 0; - virtual void unk_81() = 0; - virtual void unk_82() = 0; - virtual void unk_83() = 0; - virtual void unk_84() = 0; - virtual void unk_85() = 0; - virtual void unk_86() = 0; - virtual void unk_87() = 0; - virtual void unk_88() = 0; - virtual void unk_89() = 0; - virtual void unk_90() = 0; - virtual void unk_91() = 0; - virtual void unk_92() = 0; - virtual void unk_93() = 0; - virtual void unk_94() = 0; - virtual void unk_95() = 0; - virtual void unk_96() = 0; - virtual void unk_97() = 0; - virtual void unk_98() = 0; - virtual void unk_99() = 0; - virtual void unk_100() = 0; - virtual void unk_101() = 0; - virtual void unk_102() = 0; - virtual void unk_103() = 0; - virtual void unk_104() = 0; - virtual void unk_105() = 0; - virtual void unk_106() = 0; - virtual void unk_107() = 0; - virtual void unk_108() = 0; - virtual void unk_109() = 0; - virtual void unk_110() = 0; - virtual void unk_111() = 0; - virtual void unk_112() = 0; - virtual void unk_113() = 0; - virtual void unk_114() = 0; - virtual void unk_115() = 0; - virtual void unk_116() = 0; - virtual void unk_117() = 0; - virtual void unk_118() = 0; - virtual void unk_119() = 0; - virtual void unk_120() = 0; - virtual void unk_121() = 0; - virtual void unk_122() = 0; - virtual void unk_123() = 0; - virtual void unk_124() = 0; - virtual void unk_125() = 0; - virtual void unk_126() = 0; - virtual void unk_127() = 0; - virtual void unk_128() = 0; - virtual void unk_129() = 0; - virtual void unk_130() = 0; - virtual void unk_131() = 0; - virtual void unk_132() = 0; - virtual void unk_133() = 0; - virtual void unk_134() = 0; - virtual void unk_135() = 0; - virtual void unk_136() = 0; - virtual void unk_137() = 0; - virtual void unk_138() = 0; - virtual void unk_139() = 0; - virtual void unk_140() = 0; - virtual void unk_141() = 0; - virtual void unk_142() = 0; - virtual void unk_143() = 0; - virtual void unk_144() = 0; - virtual void unk_145() = 0; - virtual void unk_146() = 0; - virtual void unk_147() = 0; - virtual void unk_148() = 0; - virtual void unk_149() = 0; - virtual void unk_150() = 0; - virtual void unk_151() = 0; - virtual void unk_152() = 0; - virtual void unk_153() = 0; - virtual void unk_154() = 0; - virtual void unk_155() = 0; - virtual void unk_156() = 0; - virtual void unk_157() = 0; - virtual void unk_158() = 0; - virtual void unk_159() = 0; - virtual void unk_160() = 0; - virtual void unk_161() = 0; - virtual void unk_162() = 0; - virtual void unk_163() = 0; - virtual void unk_164() = 0; - virtual void unk_165() = 0; - virtual void unk_166() = 0; - virtual void unk_167() = 0; - virtual void unk_168() = 0; - virtual void unk_169() = 0; - virtual void unk_170() = 0; - virtual void unk_171() = 0; - virtual void unk_172() = 0; - virtual void unk_173() = 0; - virtual void unk_174() = 0; - virtual void unk_175() = 0; - virtual void unk_176() = 0; - virtual void unk_177() = 0; - virtual void unk_178() = 0; - virtual void unk_179() = 0; - virtual void unk_180() = 0; - virtual void unk_181() = 0; - virtual void unk_182() = 0; - virtual void unk_183() = 0; - virtual void unk_184() = 0; - virtual void unk_185() = 0; - virtual void unk_186() = 0; - virtual void unk_187() = 0; - virtual void unk_188() = 0; - virtual void unk_189() = 0; - virtual void unk_190() = 0; - virtual void unk_191() = 0; - virtual void unk_192() = 0; - virtual void unk_193() = 0; - virtual void unk_194() = 0; - virtual void unk_195() = 0; - virtual void unk_196() = 0; - virtual void unk_197() = 0; - virtual void unk_198() = 0; - virtual void unk_199() = 0; - virtual void unk_200() = 0; - virtual void unk_201() = 0; - virtual void unk_202() = 0; - virtual void unk_203() = 0; - virtual void unk_204() = 0; - virtual void unk_205() = 0; - virtual void unk_206() = 0; - virtual void unk_207() = 0; - virtual void unk_208() = 0; - virtual void unk_209() = 0; - virtual void unk_210() = 0; - virtual void unk_211() = 0; - virtual void unk_212() = 0; - virtual void unk_213() = 0; - virtual void unk_214() = 0; - virtual void unk_215() = 0; - virtual void unk_216() = 0; - virtual void unk_217() = 0; - virtual void unk_218() = 0; - virtual void unk_219() = 0; - virtual void unk_220() = 0; - virtual void unk_221() = 0; - virtual void unk_222() = 0; - virtual void unk_223() = 0; - virtual void unk_224() = 0; - virtual void unk_225() = 0; - virtual void unk_226() = 0; - virtual void unk_227() = 0; - virtual void unk_228() = 0; - virtual void unk_229() = 0; - virtual void unk_230() = 0; - virtual void unk_231() = 0; - virtual void unk_232() = 0; - virtual void unk_233() = 0; - virtual void unk_234() = 0; - virtual void unk_235() = 0; - virtual void unk_236() = 0; - virtual void unk_237() = 0; - virtual void unk_238() = 0; - virtual void unk_239() = 0; - virtual void unk_240() = 0; - virtual void unk_241() = 0; - virtual void unk_242() = 0; - virtual void unk_243() = 0; -public: - virtual bool PassesTriggerFilters(Z_CBaseEntity* pOther) = 0; + bool PassesTriggerFilters(Z_CBaseEntity *pOther) + { + static int offset = g_GameConfig->GetOffset("PassesTriggerFilters"); + return CALL_VIRTUAL(bool, offset, this, pOther); + } }; diff --git a/src/cs2_sdk/entity/globaltypes.h b/src/cs2_sdk/entity/globaltypes.h new file mode 100644 index 00000000..bf5b40aa --- /dev/null +++ b/src/cs2_sdk/entity/globaltypes.h @@ -0,0 +1,128 @@ +/** + * ============================================================================= + * CS2Fixes + * Copyright (C) 2023 Source2ZE + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once +#include +#include "schema.h" + +enum InputBitMask_t : uint64_t +{ + // MEnumeratorIsNotAFlag + IN_NONE = 0x0, + // MEnumeratorIsNotAFlag + IN_ALL = 0xffffffffffffffff, + IN_ATTACK = 0x1, + IN_JUMP = 0x2, + IN_DUCK = 0x4, + IN_FORWARD = 0x8, + IN_BACK = 0x10, + IN_USE = 0x20, + IN_TURNLEFT = 0x80, + IN_TURNRIGHT = 0x100, + IN_MOVELEFT = 0x200, + IN_MOVERIGHT = 0x400, + IN_ATTACK2 = 0x800, + IN_RELOAD = 0x2000, + IN_SPEED = 0x10000, + IN_JOYAUTOSPRINT = 0x20000, + // MEnumeratorIsNotAFlag + IN_FIRST_MOD_SPECIFIC_BIT = 0x100000000, + IN_USEORRELOAD = 0x100000000, + IN_SCORE = 0x200000000, + IN_ZOOM = 0x400000000, + IN_LOOK_AT_WEAPON = 0x800000000, +}; + +enum EInButtonState : uint32_t +{ + IN_BUTTON_UP = 0x0, + IN_BUTTON_DOWN = 0x1, + IN_BUTTON_DOWN_UP = 0x2, + IN_BUTTON_UP_DOWN = 0x3, + IN_BUTTON_UP_DOWN_UP = 0x4, + IN_BUTTON_DOWN_UP_DOWN = 0x5, + IN_BUTTON_DOWN_UP_DOWN_UP = 0x6, + IN_BUTTON_UP_DOWN_UP_DOWN = 0x7, + IN_BUTTON_STATE_COUNT = 0x8, +}; + +struct GameTime_t +{ +public: + DECLARE_SCHEMA_CLASS_INLINE(GameTime_t) + + SCHEMA_FIELD(float, m_Value) +}; + +class CNetworkTransmitComponent +{ +public: + DECLARE_SCHEMA_CLASS_INLINE(CNetworkTransmitComponent) +}; + +class CNetworkVelocityVector +{ +public: + DECLARE_SCHEMA_CLASS_INLINE(CNetworkVelocityVector) + + SCHEMA_FIELD(float, m_vecX) + SCHEMA_FIELD(float, m_vecY) + SCHEMA_FIELD(float, m_vecZ) +}; + +class CNetworkOriginCellCoordQuantizedVector +{ +public: + DECLARE_SCHEMA_CLASS_INLINE(CNetworkOriginCellCoordQuantizedVector) + + SCHEMA_FIELD(uint16, m_cellX) + SCHEMA_FIELD(uint16, m_cellY) + SCHEMA_FIELD(uint16, m_cellZ) + SCHEMA_FIELD(uint16, m_nOutsideWorld) + + // These are actually CNetworkedQuantizedFloat but we don't have the definition for it... + SCHEMA_FIELD(float, m_vecX) + SCHEMA_FIELD(float, m_vecY) + SCHEMA_FIELD(float, m_vecZ) +}; + +class CInButtonState +{ +public: + DECLARE_SCHEMA_CLASS_INLINE(CInButtonState) + + // m_pButtonStates[3] + + // m_pButtonStates[0] is the mask of currently pressed buttons + // m_pButtonStates[1] is the mask of buttons that changed in the current frame + SCHEMA_FIELD_POINTER(uint64, m_pButtonStates) +}; + +class CGlowProperty +{ +public: + DECLARE_SCHEMA_CLASS_INLINE(CGlowProperty) + + SCHEMA_FIELD(Vector, m_fGlowColor) + SCHEMA_FIELD(int, m_iGlowType) + SCHEMA_FIELD(int, m_nGlowRange) + SCHEMA_FIELD(Color, m_glowColorOverride) + SCHEMA_FIELD(bool, m_bFlashing) + SCHEMA_FIELD(bool, m_bGlowing) +}; \ No newline at end of file diff --git a/src/cs2_sdk/entity/lights.h b/src/cs2_sdk/entity/lights.h new file mode 100644 index 00000000..d89b2ae5 --- /dev/null +++ b/src/cs2_sdk/entity/lights.h @@ -0,0 +1,74 @@ +/** + * ============================================================================= + * CS2Fixes + * Copyright (C) 2023 Source2ZE + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include "cbasemodelentity.h" +#include "globaltypes.h" + +class CLightComponent +{ +public: + DECLARE_SCHEMA_CLASS(CLightComponent) +}; + +class CLightEntity : public CBaseModelEntity +{ +public: + DECLARE_SCHEMA_CLASS(CLightEntity) + + SCHEMA_FIELD(CLightComponent*, m_CLightComponent) +}; + +class CBarnLight : public CBaseModelEntity +{ +public: + DECLARE_SCHEMA_CLASS(CBarnLight) + + SCHEMA_FIELD(bool, m_bEnabled) + SCHEMA_FIELD(int, m_nColorMode) // 0 = color, 1 = color temperature + SCHEMA_FIELD_POINTER(Color, m_Color) + SCHEMA_FIELD(float, m_flColorTemperature) // default 6500 + SCHEMA_FIELD(float, m_flBrightness) + SCHEMA_FIELD(float, m_flBrightnessScale) + SCHEMA_FIELD(int, m_nDirectLight) // Always set to 2 for dynamic + SCHEMA_FIELD(int, m_nCastShadows) // 0 = no, 1 = dynamic (and baked but pointless here) + SCHEMA_FIELD(int, m_nShadowMapSize) // Shadowmap size in pixels (512 is a good starting value) + SCHEMA_FIELD(int, m_nShadowPriority) + SCHEMA_FIELD(bool, m_bContactShadow) + SCHEMA_FIELD(float, m_flRange) + SCHEMA_FIELD(float, m_flSkirt) // Falloff over the range + SCHEMA_FIELD(float, m_flSkirtNear) // Falloff from the source + SCHEMA_FIELD(float, m_flSoftX) + SCHEMA_FIELD(float, m_flSoftY) + SCHEMA_FIELD_POINTER(Vector, m_vSizeParams) + + // Artificially softens direct specular (0.0 to 1.0) + SCHEMA_FIELD(float, m_flMinRoughness) +}; + +class COmniLight : public CBarnLight +{ +public: + DECLARE_SCHEMA_CLASS(COmniLight) + + SCHEMA_FIELD(float, m_flInnerAngle) + SCHEMA_FIELD(float, m_flOuterAngle) + SCHEMA_FIELD(bool, m_bShowLight) +}; \ No newline at end of file diff --git a/src/cs2_sdk/entity/services.h b/src/cs2_sdk/entity/services.h index 203afb68..72989e9c 100644 --- a/src/cs2_sdk/entity/services.h +++ b/src/cs2_sdk/entity/services.h @@ -19,8 +19,9 @@ #pragma once #include - -#include "../schema.h" +#include "globaltypes.h" +#include +#include class CBaseEntity; @@ -39,6 +40,8 @@ struct CSMatchStats_t : public CSPerRoundStats_t { public: DECLARE_SCHEMA_CLASS_INLINE(CSMatchStats_t) + + SCHEMA_FIELD(int32_t, m_iEntryWins); }; class CCSPlayerController_ActionTrackingServices @@ -53,6 +56,65 @@ class CPlayer_MovementServices { public: DECLARE_SCHEMA_CLASS(CPlayer_MovementServices); + + SCHEMA_FIELD(CInButtonState, m_nButtons) + SCHEMA_FIELD(uint64_t, m_nQueuedButtonDownMask) + SCHEMA_FIELD(uint64_t, m_nQueuedButtonChangeMask) + SCHEMA_FIELD(uint64_t, m_nButtonDoublePressed) + + // m_pButtonPressedCmdNumber[64] + SCHEMA_FIELD_POINTER(uint32_t, m_pButtonPressedCmdNumber) + SCHEMA_FIELD(uint32_t, m_nLastCommandNumberProcessed) + SCHEMA_FIELD(uint64_t, m_nToggleButtonDownMask) + SCHEMA_FIELD(float, m_flMaxspeed) +}; + +class CPlayerPawnComponent +{ +public: + DECLARE_SCHEMA_CLASS(CPlayerPawnComponent); + + SCHEMA_FIELD(CCSPlayerPawn*, __m_pChainEntity) +}; + +class CPlayer_WeaponServices : public CPlayerPawnComponent +{ +public: + DECLARE_SCHEMA_CLASS(CPlayer_WeaponServices); + + SCHEMA_FIELD_POINTER(CUtlVector>, m_hMyWeapons) + SCHEMA_FIELD(CHandle, m_hActiveWeapon) +}; + +class CCSPlayer_WeaponServices : public CPlayer_WeaponServices +{ +public: + DECLARE_SCHEMA_CLASS(CCSPlayer_WeaponServices); + + SCHEMA_FIELD(GameTime_t, m_flNextAttack) + SCHEMA_FIELD(bool, m_bIsLookingAtWeapon) + SCHEMA_FIELD(bool, m_bIsHoldingLookAtWeapon) + + SCHEMA_FIELD(CHandle, m_hSavedWeapon) + SCHEMA_FIELD(int32_t, m_nTimeToMelee) + SCHEMA_FIELD(int32_t, m_nTimeToSecondary) + SCHEMA_FIELD(int32_t, m_nTimeToPrimary) + SCHEMA_FIELD(int32_t, m_nTimeToSniperRifle) + SCHEMA_FIELD(bool, m_bIsBeingGivenItem) + SCHEMA_FIELD(bool, m_bIsPickingUpItemWithUse) + SCHEMA_FIELD(bool, m_bPickedUpWeapon) +}; + +class CPlayer_MovementServices_Humanoid : CPlayer_MovementServices +{ +public: + DECLARE_SCHEMA_CLASS(CPlayer_MovementServices_Humanoid); +}; + +class CCSPlayer_MovementServices : CPlayer_MovementServices_Humanoid +{ +public: + DECLARE_SCHEMA_CLASS(CCSPlayer_MovementServices); }; class CCSPlayerController_InGameMoneyServices @@ -88,6 +150,8 @@ class CCSPlayer_ItemServices public: virtual bool GiveNamedItemBool(const char* pchName) = 0; virtual CBaseEntity* GiveNamedItem(const char* pchName) = 0; + virtual void DropPlayerWeapon(CBasePlayerWeapon* weapon) = 0; + virtual void StripPlayerWeapons() = 0; }; // We need an exactly sized class to be able to iterate the vector, our schema system implementation can't do this diff --git a/src/cs2_sdk/interfaces/centitysystem.cpp b/src/cs2_sdk/interfaces/centitysystem.cpp deleted file mode 100644 index 9816ebe5..00000000 --- a/src/cs2_sdk/interfaces/centitysystem.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** - * ============================================================================= - * CS2Fixes - * Copyright (C) 2023 Source2ZE - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "utlstring.h" -#include "entity2/entitysystem.h" - -#include "tier0/memdbgon.h" - -CBaseEntity* CEntitySystem::GetBaseEntity(CEntityIndex entnum) -{ - if (entnum.Get() <= -1 || entnum.Get() >= (MAX_TOTAL_ENTITIES - 1)) - return nullptr; - - CEntityIdentity* pChunkToUse = m_EntityList.m_pIdentityChunks[entnum.Get() / MAX_ENTITIES_IN_LIST]; - if (!pChunkToUse) - return nullptr; - - CEntityIdentity* pIdentity = &pChunkToUse[entnum.Get() % MAX_ENTITIES_IN_LIST]; - if (!pIdentity) - return nullptr; - - if (pIdentity->m_EHandle.GetEntryIndex() != entnum.Get()) - return nullptr; - - return dynamic_cast(pIdentity->m_pInstance); -} - -CBaseEntity* CEntitySystem::GetBaseEntity(const CEntityHandle& hEnt) -{ - if (!hEnt.IsValid()) - return nullptr; - - CEntityIdentity* pChunkToUse = m_EntityList.m_pIdentityChunks[hEnt.GetEntryIndex() / MAX_ENTITIES_IN_LIST]; - if (!pChunkToUse) - return nullptr; - - CEntityIdentity* pIdentity = &pChunkToUse[hEnt.GetEntryIndex() % MAX_ENTITIES_IN_LIST]; - if (!pIdentity) - return nullptr; - - if (pIdentity->m_EHandle != hEnt) - return nullptr; - - return dynamic_cast(pIdentity->m_pInstance); -} \ No newline at end of file diff --git a/src/cs2_sdk/interfaces/cgameresourceserviceserver.h b/src/cs2_sdk/interfaces/cgameresourceserviceserver.h deleted file mode 100644 index c5cc30b3..00000000 --- a/src/cs2_sdk/interfaces/cgameresourceserviceserver.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * ============================================================================= - * CS2Fixes - * Copyright (C) 2023 Source2ZE - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#pragma once -#include -#include "interfaces/interfaces.h" -#include "../../gameconfig.h" - -class CGameEntitySystem; - -extern CGameConfig *g_GameConfig; - -class CGameResourceService -{ -public: - CGameEntitySystem *GetGameEntitySystem() - { - static int offset = g_GameConfig->GetOffset("GameEntitySystem"); - return *reinterpret_cast((uintptr_t)(this) + offset); - } -}; diff --git a/src/cs2_sdk/interfaces/cs2_interfaces.cpp b/src/cs2_sdk/interfaces/cs2_interfaces.cpp deleted file mode 100644 index 6d8691f2..00000000 --- a/src/cs2_sdk/interfaces/cs2_interfaces.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/** - * ============================================================================= - * CS2Fixes - * Copyright (C) 2023 Source2ZE - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "interface.h" -#include "cs2_interfaces.h" -#include "strtools.h" -#include "../../common.h" -#include "tier0/dbg.h" -#include "interfaces/interfaces.h" -#include "../../utils/module.h" -#include "../addresses.h" - -#include "tier0/memdbgon.h" - -void interfaces::Initialize() -{ - pGameResourceServiceServer = (CGameResourceService*)modules::engine->FindInterface(GAMERESOURCESERVICESERVER_INTERFACE_VERSION); - g_pCVar = (ICvar*)modules::tier0->FindInterface(CVAR_INTERFACE_VERSION); - g_pSource2GameEntities = (ISource2GameEntities*)modules::server->FindInterface(SOURCE2GAMEENTITIES_INTERFACE_VERSION); - pSchemaSystem = (CSchemaSystem*)modules::schemasystem->FindInterface(SCHEMASYSTEM_INTERFACE_VERSION); -} diff --git a/src/cs2_sdk/interfaces/cschemasystem.h b/src/cs2_sdk/interfaces/cschemasystem.h deleted file mode 100644 index 5d83a550..00000000 --- a/src/cs2_sdk/interfaces/cschemasystem.h +++ /dev/null @@ -1,127 +0,0 @@ -/** - * ============================================================================= - * CS2Fixes - * Copyright (C) 2023 Source2ZE - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#pragma once -#include "../../utils/virtual.h" -#include - -struct CSchemaNetworkValue { - union { - const char* m_sz_value; - int m_n_value; - float m_f_value; - std::uintptr_t m_p_value; - }; -}; - -struct SchemaMetadataEntryData_t { - const char *m_name; - CSchemaNetworkValue* m_value; -}; - - -struct SchemaClassFieldData_t -{ - const char *m_name; - char pad0[0x8]; - short m_offset; - int32_t m_metadata_size; - SchemaMetadataEntryData_t* m_metadata; -}; - -class SchemaClassInfoData_t; - -struct SchemaBaseClassInfoData_t -{ - unsigned int m_offset; - SchemaClassInfoData_t *m_class; -}; - -class SchemaClassInfoData_t -{ -public: - auto GetName() - { - return m_name; - } - - auto GetFieldsSize() - { - return m_align; - } - - auto GetFields() - { - return m_fields; - } - - SchemaClassInfoData_t* GetParent() - { - if (!m_schema_parent) - return nullptr; - - return m_schema_parent->m_class; - } - -private: - char pad_0x0000[0x8]; // 0x0000 - - const char *m_name; // 0x0008 - char *m_module; // 0x0010 - - int m_size; // 0x0018 - int16_t m_align; // 0x001C - - int16_t m_static_size; // 0x001E - int16_t m_metadata_size; // 0x0020 - int16_t m_i_unk1; // 0x0022 - int16_t m_i_unk2; // 0x0024 - int16_t m_i_unk3; // 0x0026 - - SchemaClassFieldData_t *m_fields; // 0x0028 - - char pad_0x0030[0x8]; // 0x0030 - SchemaBaseClassInfoData_t *m_schema_parent; // 0x0038 - - char pad_0x0038[0x10]; // 0x0038 -}; - -class CSchemaSystemTypeScope -{ -public: - SchemaClassInfoData_t* FindDeclaredClass(const char *pClass) - { -#ifdef _WIN32 - SchemaClassInfoData_t *rv = nullptr; - CALL_VIRTUAL(void, 2, this, &rv, pClass); - return rv; -#else - return CALL_VIRTUAL(SchemaClassInfoData_t*, 2, this, pClass); -#endif - } -}; - -class CSchemaSystem -{ -public: - auto FindTypeScopeForModule(const char *module) - { - return CALL_VIRTUAL(CSchemaSystemTypeScope *, 13, this, module, nullptr); - } -}; \ No newline at end of file diff --git a/src/cs2_sdk/schema.cpp b/src/cs2_sdk/schema.cpp index a1e3e6d3..b004aad2 100644 --- a/src/cs2_sdk/schema.cpp +++ b/src/cs2_sdk/schema.cpp @@ -20,12 +20,15 @@ #include "schema.h" #include "../common.h" -#include "interfaces/cs2_interfaces.h" +#include "cschemasystem.h" #include "tier1/utlmap.h" #include "tier0/memdbgon.h" #include "plat.h" #include "entity/cbaseentity.h" +extern CSchemaSystem *g_pSchemaSystem2; +extern CGlobalVars *gpGlobals; + using SchemaKeyValueMap_t = CUtlMap; using SchemaTableMap_t = CUtlMap; @@ -44,7 +47,7 @@ static bool IsFieldNetworked(SchemaClassFieldData_t& field) static bool InitSchemaFieldsForClass(SchemaTableMap_t *tableMap, const char* className, uint32_t classKey) { - CSchemaSystemTypeScope* pType = interfaces::pSchemaSystem->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT); + CSchemaSystemTypeScope* pType = g_pSchemaSystem2->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT); if (!pType) return false; @@ -72,10 +75,10 @@ static bool InitSchemaFieldsForClass(SchemaTableMap_t *tableMap, const char* cla SchemaClassFieldData_t& field = pFields[i]; #ifdef _DEBUG - Message("%s::%s found at -> 0x%X - %llx\n", className, field.m_name, field.m_offset, &field); + Message("%s::%s found at -> 0x%X - %llx\n", className, field.m_name, field.m_single_inheritance_offset, &field); #endif - keyValueMap->Insert(hash_32_fnv1a_const(field.m_name), { field.m_offset, IsFieldNetworked(field) }); + keyValueMap->Insert(hash_32_fnv1a_const(field.m_name), {field.m_single_inheritance_offset, IsFieldNetworked(field)}); } return true; @@ -83,7 +86,7 @@ static bool InitSchemaFieldsForClass(SchemaTableMap_t *tableMap, const char* cla int16_t schema::FindChainOffset(const char* className) { - CSchemaSystemTypeScope* pType = interfaces::pSchemaSystem->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT); + CSchemaSystemTypeScope* pType = g_pSchemaSystem2->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT); if (!pType) return false; @@ -100,7 +103,7 @@ int16_t schema::FindChainOffset(const char* className) if (V_strcmp(field.m_name, "__m_pChainEntity") == 0) { - return field.m_offset; + return field.m_single_inheritance_offset; } } } while ((pClassInfo = pClassInfo->GetParent()) != nullptr); @@ -133,11 +136,8 @@ SchemaKey schema::GetOffset(const char* className, uint32_t classKey, const char void SetStateChanged(Z_CBaseEntity* pEntity, int offset) { - addresses::StateChanged(pEntity->m_NetworkTransmitComponent(), pEntity, offset, -1, -1); - auto vars = GetGameGlobals(); - - if (vars) - pEntity->m_lastNetworkChange = vars->curtime; - - pEntity->m_isSteadyState().ClearAll(); + addresses::StateChanged(pEntity->m_NetworkTransmitComponent(), pEntity, offset, -1, -1); + + pEntity->m_lastNetworkChange = gpGlobals->curtime; + pEntity->m_isSteadyState().ClearAll(); }; diff --git a/src/cs2_sdk/schema.h b/src/cs2_sdk/schema.h index 5bb0cfb8..dd5a2a47 100644 --- a/src/cs2_sdk/schema.h +++ b/src/cs2_sdk/schema.h @@ -39,8 +39,9 @@ #include "stdint.h" #undef schema -struct SchemaKey { - int16_t offset; +struct SchemaKey +{ + int32 offset; bool networked; }; diff --git a/src/cs2fixes.cpp b/src/cs2fixes.cpp index 078dbbf8..303c42ce 100644 --- a/src/cs2fixes.cpp +++ b/src/cs2fixes.cpp @@ -30,31 +30,40 @@ #include "common.h" #include "commands.h" #include "detours.h" -#include "patches.h" #include "icvar.h" #include "interface.h" #include "tier0/dbg.h" -#include "interfaces/cs2_interfaces.h" +#include "cschemasystem.h" #include "plat.h" #include "entitysystem.h" #include "engine/igameeventsystem.h" +#include "gamesystem.h" #include "ctimer.h" #include "playermanager.h" #include #include "adminsystem.h" +#include "commands.h" #include "eventlistener.h" #include "gameconfig.h" + + + +#include "entity/cgamerules.h" +#include "entity/ccsplayercontroller.h" +#include "entitylistener.h" + +#define VPROF_ENABLED +#include "tier0/vprof.h" + #include "tier0/memdbgon.h" -CEntitySystem* g_pEntitySystem = nullptr; +extern CUtlVector coaches; -float g_flUniversalTime; +double g_flUniversalTime; float g_flLastTickedTime; bool g_bHasTicked; -extern CUtlVector coaches; - void Message(const char *msg, ...) { va_list args; @@ -89,8 +98,10 @@ void Panic(const char *msg, ...) class GameSessionConfiguration_t { }; SH_DECL_HOOK3_void(IServerGameDLL, GameFrame, SH_NOATTRIB, 0, bool, bool, bool); +SH_DECL_HOOK0_void(IServerGameDLL, GameServerSteamAPIActivated, SH_NOATTRIB, 0); +SH_DECL_HOOK0_void(IServerGameDLL, GameServerSteamAPIDeactivated, SH_NOATTRIB, 0); SH_DECL_HOOK4_void(IServerGameClients, ClientActive, SH_NOATTRIB, 0, CPlayerSlot, bool, const char *, uint64); -SH_DECL_HOOK5_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, CPlayerSlot, int, const char *, uint64, const char *); +SH_DECL_HOOK5_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, CPlayerSlot, ENetworkDisconnectionReason, const char *, uint64, const char *); SH_DECL_HOOK4_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, CPlayerSlot, char const *, int, uint64); SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, CPlayerSlot ); SH_DECL_HOOK6_void(IServerGameClients, OnClientConnected, SH_NOATTRIB, 0, CPlayerSlot, const char*, uint64, const char *, const char *, bool); @@ -98,77 +109,68 @@ SH_DECL_HOOK6(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, CPlayerSl SH_DECL_HOOK8_void(IGameEventSystem, PostEventAbstract, SH_NOATTRIB, 0, CSplitScreenSlot, bool, int, const uint64*, INetworkSerializable*, const void*, unsigned long, NetChannelBufType_t) SH_DECL_HOOK3_void(INetworkServerService, StartupServer, SH_NOATTRIB, 0, const GameSessionConfiguration_t&, ISource2WorldSession*, const char*); -SH_DECL_HOOK6_void(ISource2GameEntities, CheckTransmit, SH_NOATTRIB, 0, CCheckTransmitInfo **, int, CBitVec<16384> &, const Entity2Networkable_t **, const uint16 *, int); -SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, CPlayerSlot, const CCommand &); -CS2Scrim g_CS2Scrim; - -// Should only be called within the active game loop (i e map should be loaded and active) -// otherwise that'll be nullptr! -CGlobalVars *GetGameGlobals() -{ - INetworkGameServer *server = g_pNetworkServerService->GetIGameServer(); - - if (!server) - return nullptr; - - return server->GetGlobals(); -} - -#if 0 -// Currently unavailable, requires hl2sdk work! -ConVar sample_cvar("sample_cvar", "42", 0); -#endif +SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, CPlayerSlot, const CCommand &); +SH_DECL_HOOK3_void(ICvar, DispatchConCommand, SH_NOATTRIB, 0, ConCommandHandle, const CCommandContext&, const CCommand&); + +CS2Fixes g_CS2Fixes; + +IGameEventSystem *g_gameEventSystem = nullptr; +IGameEventManager2 *g_gameEventManager = nullptr; +INetworkGameServer *g_pNetworkGameServer = nullptr; +CGameEntitySystem *g_pEntitySystem = nullptr; +CEntityListener *g_pEntityListener = nullptr; +CSchemaSystem *g_pSchemaSystem2 = nullptr; +CGlobalVars *gpGlobals = nullptr; +CPlayerManager *g_playerManager = nullptr; +IVEngineServer2 *g_pEngineServer2 = nullptr; +CGameConfig *g_GameConfig = nullptr; -CON_COMMAND_F(sample_command, "Sample command", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND) -{ - Message( "Sample command called by %d. Command: %s\n", context.GetPlayerSlot(), args.GetCommandString() ); -} +//CSteamGameServerAPIContext g_steamAPI; +CCSGameRules *g_pGameRules = nullptr; -CON_COMMAND_F(toggle_logs, "Toggle printing most logs and warnings", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND) +CGameEntitySystem *GameEntitySystem() { - ToggleLogs(); + static int offset = g_GameConfig->GetOffset("GameEntitySystem"); + return *reinterpret_cast((uintptr_t)(g_pGameResourceServiceServer) + offset); } -IGameEventSystem* g_gameEventSystem; -IGameEventManager2* g_gameEventManager = nullptr; -INetworkGameServer* g_networkGameServer; -CGlobalVars* gpGlobals = nullptr; -CPlayerManager* g_playerManager = nullptr; -IVEngineServer2* g_pEngineServer2; -CGameConfig *g_GameConfig = nullptr; - -PLUGIN_EXPOSE(CS2Scrim, g_CS2Scrim); -bool CS2Scrim::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) +PLUGIN_EXPOSE(CS2Fixes, g_CS2Fixes); +bool CS2Fixes::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) { PLUGIN_SAVEVARS(); GET_V_IFACE_CURRENT(GetEngineFactory, g_pEngineServer2, IVEngineServer2, SOURCE2ENGINETOSERVER_INTERFACE_VERSION); + GET_V_IFACE_CURRENT(GetEngineFactory, g_pGameResourceServiceServer, IGameResourceServiceServer, GAMERESOURCESERVICESERVER_INTERFACE_VERSION); GET_V_IFACE_CURRENT(GetEngineFactory, g_pCVar, ICvar, CVAR_INTERFACE_VERSION); + GET_V_IFACE_CURRENT(GetEngineFactory, g_pSchemaSystem2, CSchemaSystem, SCHEMASYSTEM_INTERFACE_VERSION); GET_V_IFACE_ANY(GetServerFactory, g_pSource2Server, ISource2Server, SOURCE2SERVER_INTERFACE_VERSION); + GET_V_IFACE_ANY(GetServerFactory, g_pSource2ServerConfig, ISource2ServerConfig, SOURCE2SERVERCONFIG_INTERFACE_VERSION); GET_V_IFACE_ANY(GetServerFactory, g_pSource2GameEntities, ISource2GameEntities, SOURCE2GAMEENTITIES_INTERFACE_VERSION); GET_V_IFACE_ANY(GetServerFactory, g_pSource2GameClients, IServerGameClients, SOURCE2GAMECLIENTS_INTERFACE_VERSION); GET_V_IFACE_ANY(GetEngineFactory, g_pNetworkServerService, INetworkServerService, NETWORKSERVERSERVICE_INTERFACE_VERSION); GET_V_IFACE_ANY(GetEngineFactory, g_gameEventSystem, IGameEventSystem, GAMEEVENTSYSTEM_INTERFACE_VERSION); GET_V_IFACE_ANY(GetFileSystemFactory, g_pFullFileSystem, IFileSystem, FILESYSTEM_INTERFACE_VERSION); - // Currently doesn't work from within mm side, use GetGameGlobals() in the mean time instead - // this needs to run in case of a late load - gpGlobals = GetGameGlobals(); + // Required to get the IMetamodListener events + g_SMAPI->AddListener(this, this); Message( "Starting plugin.\n" ); - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, g_pSource2Server, this, &CS2Scrim::Hook_GameFrame, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientActive, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientActive, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientDisconnect, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientPutInServer, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientSettingsChanged, false); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, OnClientConnected, g_pSource2GameClients, this, &CS2Scrim::Hook_OnClientConnected, false); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientConnect, false ); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientCommand, false); - SH_ADD_HOOK_MEMFUNC(IGameEventSystem, PostEventAbstract, g_gameEventSystem, this, &CS2Scrim::Hook_PostEvent, false); - SH_ADD_HOOK_MEMFUNC(INetworkServerService, StartupServer, g_pNetworkServerService, this, &CS2Scrim::Hook_StartupServer, true); - SH_ADD_HOOK_MEMFUNC(ISource2GameEntities, CheckTransmit, g_pSource2GameEntities, this, &CS2Scrim::Hook_CheckTransmit, true); + SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, g_pSource2Server, this, &CS2Fixes::Hook_GameFrame, true); + SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameServerSteamAPIActivated, g_pSource2Server, this, &CS2Fixes::Hook_GameServerSteamAPIActivated, false); + SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameServerSteamAPIDeactivated, g_pSource2Server, this, &CS2Fixes::Hook_GameServerSteamAPIDeactivated, false); + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientActive, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientActive, true); + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientDisconnect, true); + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientPutInServer, true); + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientSettingsChanged, false); + SH_ADD_HOOK_MEMFUNC(IServerGameClients, OnClientConnected, g_pSource2GameClients, this, &CS2Fixes::Hook_OnClientConnected, false); + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientConnect, false ); + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientCommand, false); + SH_ADD_HOOK_MEMFUNC(IGameEventSystem, PostEventAbstract, g_gameEventSystem, this, &CS2Fixes::Hook_PostEvent, false); + SH_ADD_HOOK_MEMFUNC(INetworkServerService, StartupServer, g_pNetworkServerService, this, &CS2Fixes::Hook_StartupServer, true); + + SH_ADD_HOOK_MEMFUNC(ICvar, DispatchConCommand, g_pCVar, this, &CS2Fixes::Hook_DispatchConCommand, false); META_CONPRINTF( "All hooks started!\n" ); @@ -189,158 +191,281 @@ bool CS2Scrim::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool return false; } - addresses::Initialize(g_GameConfig); - interfaces::Initialize(); + bool bRequiredInitLoaded = true; - Message( "All hooks started!\n" ); + if (!addresses::Initialize(g_GameConfig)) + bRequiredInitLoaded = false; - UnlockConVars(); - UnlockConCommands(); + if (!InitDetours(g_GameConfig)) + bRequiredInitLoaded = false; - g_pEntitySystem = interfaces::pGameResourceServiceServer->GetGameEntitySystem(); + int offset = g_GameConfig->GetOffset("GameEventManager"); + g_gameEventManager = (IGameEventManager2 *)(CALL_VIRTUAL(uintptr_t, offset, g_pSource2Server) - 8); - ConVar_Register(FCVAR_RELEASE | FCVAR_CLIENT_CAN_EXECUTE | FCVAR_GAMEDLL); + if (!g_gameEventManager) + { + Panic("Failed to find GameEventManager\n"); + bRequiredInitLoaded = false; + } - bool requiredInitLoaded = true; + if (!InitGameSystems()) + bRequiredInitLoaded = false; - //if (!InitPatches(g_GameConfig)) - //requiredInitLoaded = false; + if (!bRequiredInitLoaded) + { + snprintf(error, maxlen, "One or more address lookups, patches or detours failed, please refer to startup logs for more information"); + return false; + } - if (!InitDetours(g_GameConfig)) - requiredInitLoaded = false; + Message( "All hooks started!\n" ); - //if (!requiredInitLoaded) - // return false; + UnlockConVars(); + UnlockConCommands(); + ConVar_Register(FCVAR_RELEASE | FCVAR_CLIENT_CAN_EXECUTE | FCVAR_GAMEDLL); + + if (late) + { + RegisterEventListeners(); + g_pEntitySystem = GameEntitySystem(); + g_pEntitySystem->AddListenerEntity(g_pEntityListener); + g_pNetworkGameServer = g_pNetworkServerService->GetIGameServer(); + gpGlobals = g_pNetworkGameServer->GetGlobals(); + } - g_playerManager = new CPlayerManager(); g_pAdminSystem = new CAdminSystem(); + g_playerManager = new CPlayerManager(late); + //g_pDiscordBotManager = new CDiscordBotManager(); + //g_pZRPlayerClassManager = new CZRPlayerClassManager(); + //g_pMapVoteSystem = new CMapVoteSystem(); + //g_pUserPreferencesSystem = new CUserPreferencesSystem(); + //g_pUserPreferencesStorage = new CUserPreferencesREST(); + //g_pZRWeaponConfig = new ZRWeaponConfig(); + g_pEntityListener = new CEntityListener(); - coaches.Purge(); + RegisterWeaponCommands(); // Steam authentication - new CTimer(1.0f, true, true, []() + new CTimer(1.0f, true, []() { g_playerManager->TryAuthenticate(); - }); - - // Check hide distance - new CTimer(0.5f, true, true, []() - { - g_playerManager->CheckHideDistances(); + return 1.0f; }); // Check for the expiration of infractions like mutes or gags - new CTimer(30.0f, true, true, []() + new CTimer(30.0f, true, []() { g_playerManager->CheckInfractions(); + return 30.0f; }); - g_gameEventManager = (IGameEventManager2*)(CALL_VIRTUAL(uintptr_t, 91, g_pSource2Server) - 8); - - Message("g_gameEventManager - %p\n", g_gameEventManager); + // run our cfg + g_pEngineServer2->ServerCommand("exec cs2scrim/cs2scrim"); srand(time(0)); return true; } -bool CS2Scrim::Unload(char *error, size_t maxlen) +bool CS2Fixes::Unload(char *error, size_t maxlen) { FOR_EACH_VEC(coaches,i){ coaches.Remove(i); } - - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, g_pSource2Server, this, &CS2Scrim::Hook_GameFrame, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientActive, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientActive, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientDisconnect, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientPutInServer, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientSettingsChanged, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, OnClientConnected, g_pSource2GameClients, this, &CS2Scrim::Hook_OnClientConnected, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientConnect, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, g_pSource2GameClients, this, &CS2Scrim::Hook_ClientCommand, false); - SH_REMOVE_HOOK_MEMFUNC(IGameEventSystem, PostEventAbstract, g_gameEventSystem, this, &CS2Scrim::Hook_PostEvent, false); - SH_REMOVE_HOOK_MEMFUNC(INetworkServerService, StartupServer, g_pNetworkServerService, this, &CS2Scrim::Hook_StartupServer, true); - SH_REMOVE_HOOK_MEMFUNC(ISource2GameEntities, CheckTransmit, g_pSource2GameEntities, this, &CS2Scrim::Hook_CheckTransmit, true); + + SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, g_pSource2Server, this, &CS2Fixes::Hook_GameFrame, true); + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientActive, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientActive, true); + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientDisconnect, true); + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientPutInServer, true); + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientSettingsChanged, false); + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, OnClientConnected, g_pSource2GameClients, this, &CS2Fixes::Hook_OnClientConnected, false); + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientConnect, false); + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientCommand, false); + SH_REMOVE_HOOK_MEMFUNC(IGameEventSystem, PostEventAbstract, g_gameEventSystem, this, &CS2Fixes::Hook_PostEvent, false); + SH_REMOVE_HOOK_MEMFUNC(INetworkServerService, StartupServer, g_pNetworkServerService, this, &CS2Fixes::Hook_StartupServer, true); + + SH_REMOVE_HOOK_MEMFUNC(ICvar, DispatchConCommand, g_pCVar, this, &CS2Fixes::Hook_DispatchConCommand, false); ConVar_Unregister(); g_CommandList.Purge(); + coaches.Purge(); FlushAllDetours(); - //UndoPatches(); RemoveTimers(); UnregisterEventListeners(); - if (g_playerManager != NULL) + if (g_playerManager) delete g_playerManager; - if (g_pAdminSystem != NULL) + if (g_pAdminSystem) delete g_pAdminSystem; - if (g_GameConfig != NULL) + if (g_GameConfig) delete g_GameConfig; + if (g_pEntityListener) + delete g_pEntityListener; + return true; } -void CS2Scrim::Hook_StartupServer(const GameSessionConfiguration_t& config, ISource2WorldSession*, const char*) +void CS2Fixes::Hook_DispatchConCommand(ConCommandHandle cmdHandle, const CCommandContext& ctx, const CCommand& args) +{ + if (!g_pEntitySystem) + return; + + auto iCommandPlayerSlot = ctx.GetPlayerSlot(); + + bool bSay = !V_strcmp(args.Arg(0), "say"); + bool bTeamSay = !V_strcmp(args.Arg(0), "say_team"); + + if (iCommandPlayerSlot != -1 && (bSay || bTeamSay)) + { + auto pController = CCSPlayerController::FromSlot(iCommandPlayerSlot); + bool bGagged = pController && pController->GetZEPlayer()->IsGagged(); + bool bFlooding = pController && pController->GetZEPlayer()->IsFlooding(); + bool bAdminChat = bTeamSay && *args[1] == '@'; + bool bSilent = *args[1] == '/' || bAdminChat; + bool bCommand = *args[1] == '!' || *args[1] == '/' || *args[1] == '.'; + + // Chat messages should generate events regardless + if (pController) + { + IGameEvent *pEvent = g_gameEventManager->CreateEvent("player_chat"); + + if (pEvent) + { + pEvent->SetBool("teamonly", bTeamSay); + pEvent->SetInt("userid", pController->GetPlayerSlot()); + pEvent->SetString("text", args[1]); + + g_gameEventManager->FireEvent(pEvent, true); + } + } + + if (!bGagged && !bSilent && !bFlooding) + { + SH_CALL(g_pCVar, &ICvar::DispatchConCommand)(cmdHandle, ctx, args); + } + else if (bFlooding) + { + if (pController) + ClientPrint(pController, HUD_PRINTTALK, CHAT_PREFIX "You are flooding the server!"); + } + else if (bAdminChat) // Admin chat can be sent by anyone but only seen by admins, use flood protection here too + { + // HACK: At this point, we can safely modify the arg buffer as it won't be passed anywhere else + // The string here is originally ("@foo bar"), trim it to be (foo bar) + char *pszMessage = (char*)(args.ArgS() + 2); + pszMessage[V_strlen(pszMessage) - 1] = 0; + + for (int i = 0; i < gpGlobals->maxClients; i++) + { + ZEPlayer *pPlayer = g_playerManager->GetPlayer(i); + + if (!pPlayer) + continue; + + if (pPlayer->IsAdminFlagSet(ADMFLAG_GENERIC)) + ClientPrint(CCSPlayerController::FromSlot(i), HUD_PRINTTALK, " \4(ADMINS) %s:\1 %s", pController->GetPlayerName(), pszMessage); + else if (i == iCommandPlayerSlot.Get()) // Sender is not an admin + ClientPrint(pController, HUD_PRINTTALK, " \4(TO ADMINS) %s:\1 %s", pController->GetPlayerName(), pszMessage); + } + } + + // Finally, run the chat command if it is one, so anything will print after the player's message + if (bCommand) + { + // Do the same trimming as with admin chat + char *pszMessage = (char *)(args.ArgS() + 2); + + // Host_Say at some point removes the trailing " for whatever reason, so we only remove if it was never called + if (bSilent) + pszMessage[V_strlen(pszMessage) - 1] = 0; + + ParseChatCommand(pszMessage, pController); + } + + RETURN_META(MRES_SUPERCEDE); + } +} + +void CS2Fixes::Hook_StartupServer(const GameSessionConfiguration_t& config, ISource2WorldSession*, const char*) { - Message("startup server\n"); + g_pNetworkGameServer = g_pNetworkServerService->GetIGameServer(); + g_pEntitySystem = GameEntitySystem(); + g_pEntitySystem->AddListenerEntity(g_pEntityListener); + gpGlobals = g_pNetworkGameServer->GetGlobals(); + + Message("Hook_StartupServer: %s\n", gpGlobals->mapname); + + // run our cfg + g_pEngineServer2->ServerCommand("exec cs2scrim/cs2scrim"); + + // Run map cfg (if present) + /*char cmd[MAX_PATH]; + V_snprintf(cmd, sizeof(cmd), "exec cs2fixes/maps/%s", gpGlobals->mapname); + g_pEngineServer2->ServerCommand(cmd); + */ if(g_bHasTicked) RemoveMapTimers(); + FOR_EACH_VEC(coaches,i){ coaches.Remove(i); } g_bHasTicked = false; - gpGlobals = GetGameGlobals(); - if (gpGlobals == nullptr) + RegisterEventListeners(); + //g_playerManager->SetupInfiniteAmmo(); + + // Disable RTV and Extend votes after map has just started + //g_RTVState = ERTVState::MAP_START; + //g_ExtendState = EExtendState::MAP_START; + + // Allow RTV and Extend votes after 2 minutes post map start + /*new CTimer(120.0f, false, []() { - Error("Failed to lookup gpGlobals\n"); - } + if (g_RTVState != ERTVState::BLOCKED_BY_ADMIN) + g_RTVState = ERTVState::RTV_ALLOWED; - RegisterEventListeners(); + if (g_ExtendState < EExtendState::POST_EXTEND_NO_EXTENDS_LEFT) + g_ExtendState = EExtendState::EXTEND_ALLOWED; + return -1.0f; + }); - g_pEntitySystem = interfaces::pGameResourceServiceServer->GetGameEntitySystem(); + if (g_bEnableZR) + ZR_OnStartupServer(); + */ } - -void CS2Scrim::Hook_PostEvent(CSplitScreenSlot nSlot, bool bLocalOnly, int nClientCount, const uint64* clients, - INetworkSerializable* pEvent, const void* pData, unsigned long nSize, NetChannelBufType_t bufType) +void CS2Fixes::Hook_GameServerSteamAPIActivated() { - // Message( "Hook_PostEvent(%d, %d, %d, %lli)\n", nSlot, bLocalOnly, nClientCount, clients ); - NetMessageInfo_t* info = pEvent->GetNetMessageInfo(); + RETURN_META(MRES_IGNORED); +} - //CMsgTEFireBullets - if (info->m_MessageId == GE_FireBulletsId || info->m_MessageId == TE_WorldDecalId) - { - // Can later do a bit mask for players using stopsound but this will do for now - for (uint64 i = 0; i < MAXPLAYERS; i++) - { - ZEPlayer *pPlayer = g_playerManager->GetPlayer(i); +void CS2Fixes::Hook_GameServerSteamAPIDeactivated() +{ - // A client might be already excluded from the event possibly due to being too far away, so ignore them - if (!(*(uint64 *)clients & ((uint64)1 << i))) - continue; + RETURN_META(MRES_IGNORED); +} - if (!pPlayer) - continue; +void CS2Fixes::Hook_PostEvent(CSplitScreenSlot nSlot, bool bLocalOnly, int nClientCount, const uint64* clients, + INetworkSerializable* pEvent, const void* pData, unsigned long nSize, NetChannelBufType_t bufType) +{ + // Message( "Hook_PostEvent(%d, %d, %d, %lli)\n", nSlot, bLocalOnly, nClientCount, clients ); + // Need to explicitly get a pointer to the right function as it's overloaded and SH_CALL can't resolve that + static void (IGameEventSystem::*PostEventAbstract)(CSplitScreenSlot, bool, int, const uint64 *, + INetworkSerializable *, const void *, unsigned long, NetChannelBufType_t) = &IGameEventSystem::PostEventAbstract; + + NetMessageInfo_t *info = pEvent->GetNetMessageInfo(); - if ((info->m_MessageId == GE_FireBulletsId && pPlayer->IsUsingStopSound()) || - (info->m_MessageId == TE_WorldDecalId && pPlayer->IsUsingStopDecals())) - { - *(uint64*)clients &= ~((uint64)1 << i); - nClientCount--; - } - } - } } -void CS2Scrim::AllPluginsLoaded() +void CS2Fixes::AllPluginsLoaded() { /* This is where we'd do stuff that relies on the mod or other plugins * being initialized (for example, cvars added and events registered). @@ -349,26 +474,28 @@ void CS2Scrim::AllPluginsLoaded() Message( "AllPluginsLoaded\n" ); } -void CS2Scrim::Hook_ClientActive( CPlayerSlot slot, bool bLoadGame, const char *pszName, uint64 xuid ) +void CS2Fixes::Hook_ClientActive( CPlayerSlot slot, bool bLoadGame, const char *pszName, uint64 xuid ) { Message( "Hook_ClientActive(%d, %d, \"%s\", %lli)\n", slot, bLoadGame, pszName, xuid ); } -void CS2Scrim::Hook_ClientCommand( CPlayerSlot slot, const CCommand &args ) +void CS2Fixes::Hook_ClientCommand( CPlayerSlot slot, const CCommand &args ) { + #ifdef _DEBUG Message( "Hook_ClientCommand(%d, \"%s\")\n", slot, args.GetCommandString() ); #endif + } -void CS2Scrim::Hook_ClientSettingsChanged( CPlayerSlot slot ) +void CS2Fixes::Hook_ClientSettingsChanged( CPlayerSlot slot ) { #ifdef _DEBUG Message( "Hook_ClientSettingsChanged(%d)\n", slot ); #endif } -void CS2Scrim::Hook_OnClientConnected( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, const char *pszAddress, bool bFakePlayer ) +void CS2Fixes::Hook_OnClientConnected( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, const char *pszAddress, bool bFakePlayer ) { Message( "Hook_OnClientConnected(%d, \"%s\", %lli, \"%s\", \"%s\", %d)\n", slot, pszName, xuid, pszNetworkID, pszAddress, bFakePlayer ); @@ -376,30 +503,40 @@ void CS2Scrim::Hook_OnClientConnected( CPlayerSlot slot, const char *pszName, ui g_playerManager->OnBotConnected(slot); } -bool CS2Scrim::Hook_ClientConnect( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, bool unk1, CBufferString *pRejectReason ) +bool CS2Fixes::Hook_ClientConnect( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, bool unk1, CBufferString *pRejectReason ) { Message( "Hook_ClientConnect(%d, \"%s\", %lli, \"%s\", %d, \"%s\")\n", slot, pszName, xuid, pszNetworkID, unk1, pRejectReason->ToGrowable()->Get() ); - if (!g_playerManager->OnClientConnected(slot)) + if (!g_playerManager->OnClientConnected(slot, xuid, pszNetworkID)) RETURN_META_VALUE(MRES_SUPERCEDE, false); RETURN_META_VALUE(MRES_IGNORED, true); } -void CS2Scrim::Hook_ClientPutInServer( CPlayerSlot slot, char const *pszName, int type, uint64 xuid ) +void CS2Fixes::Hook_ClientPutInServer( CPlayerSlot slot, char const *pszName, int type, uint64 xuid ) { Message( "Hook_ClientPutInServer(%d, \"%s\", %d, %d, %lli)\n", slot, pszName, type, xuid ); + g_playerManager->OnClientPutInServer(slot); + } -void CS2Scrim::Hook_ClientDisconnect( CPlayerSlot slot, int reason, const char *pszName, uint64 xuid, const char *pszNetworkID ) +void CS2Fixes::Hook_ClientDisconnect( CPlayerSlot slot, ENetworkDisconnectionReason reason, const char *pszName, uint64 xuid, const char *pszNetworkID ) { Message( "Hook_ClientDisconnect(%d, %d, \"%s\", %lli, \"%s\")\n", slot, reason, pszName, xuid, pszNetworkID ); g_playerManager->OnClientDisconnect(slot); + + if (coaches.Count() < 1) return; + FOR_EACH_VEC(coaches,i){ + if(coaches[i]->GetPlayerSlot() == slot.Get()){ + coaches.Remove(i); + } + } } -void CS2Scrim::Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastTick ) +void CS2Fixes::Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastTick ) { + VPROF_ENTER_SCOPE(__FUNCTION__); /** * simulating: * *********** @@ -411,18 +548,10 @@ void CS2Scrim::Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastTick { g_flUniversalTime += gpGlobals->curtime - g_flLastTickedTime; } - else - { - g_flUniversalTime += gpGlobals->interval_per_tick; - } g_flLastTickedTime = gpGlobals->curtime; g_bHasTicked = true; - if(!g_pEntitySystem) - g_pEntitySystem = interfaces::pGameResourceServiceServer->GetGameEntitySystem(); - - for (int i = g_timers.Tail(); i != g_timers.InvalidIndex();) { auto timer = g_timers[i]; @@ -434,72 +563,25 @@ void CS2Scrim::Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastTick timer->m_flLastExecute = g_flUniversalTime; // Timer execute - if (timer->m_flLastExecute + timer->m_flTime <= g_flUniversalTime) + if (timer->m_flLastExecute + timer->m_flInterval <= g_flUniversalTime) { - timer->Execute(); - - if (!timer->m_bRepeat) + if (!timer->Execute()) { delete timer; g_timers.Remove(prevIndex); } else + { timer->m_flLastExecute = g_flUniversalTime; + } } } -} -void CS2Scrim::Hook_CheckTransmit(CCheckTransmitInfo **ppInfoList, int infoCount, CBitVec<16384> &unionTransmitEdicts, - const Entity2Networkable_t **pNetworkables, const uint16 *pEntityIndicies, int nEntities) -{ - if (!g_pEntitySystem) - return; - - for (int i = 0; i < infoCount; i++) - { - auto &pInfo = ppInfoList[i]; - - // offset 560 happens to have a player index here, - // though this is probably part of the client class that contains the CCheckTransmitInfo - int iPlayerSlot = (int)*((uint8 *)pInfo + 560); - - auto pPlayer = g_playerManager->GetPlayer(iPlayerSlot); - - if (!pPlayer) - continue; - - auto pSelfController = (CBasePlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pPlayer->GetPlayerSlot().Get() + 1)); - - if (!pSelfController) - continue; - - auto pSelfPawn = pSelfController->GetPawn(); - - if (!pSelfPawn || !pSelfPawn->IsAlive()) - continue; - - for (int i = 1; i <= MAXPLAYERS; i++) - { - if (!pPlayer->ShouldBlockTransmit(i - 1)) - continue; - - auto pController = (CBasePlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)i); - - if (!pController) - continue; - - auto pPawn = pController->GetPawn(); - - if (!pPawn) - continue; - - pInfo->m_pTransmitEntity->Clear(pPawn->entindex()); - } - } + VPROF_EXIT_SCOPE(); } // Potentially might not work -void CS2Scrim::OnLevelInit( char const *pMapName, +void CS2Fixes::OnLevelInit( char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, @@ -507,60 +589,62 @@ void CS2Scrim::OnLevelInit( char const *pMapName, bool background ) { Message("OnLevelInit(%s)\n", pMapName); + + //g_pMapVoteSystem->OnLevelInit(pMapName); } // Potentially might not work -void CS2Scrim::OnLevelShutdown() +void CS2Fixes::OnLevelShutdown() { Message("OnLevelShutdown()\n"); } -bool CS2Scrim::Pause(char *error, size_t maxlen) +bool CS2Fixes::Pause(char *error, size_t maxlen) { return true; } -bool CS2Scrim::Unpause(char *error, size_t maxlen) +bool CS2Fixes::Unpause(char *error, size_t maxlen) { return true; } -const char *CS2Scrim::GetLicense() +const char *CS2Fixes::GetLicense() { - return "MIT License"; + return "GPL v3 License"; } -const char *CS2Scrim::GetVersion() +const char *CS2Fixes::GetVersion() { - return "1.0.2.0"; + return "1.1.0"; } -const char *CS2Scrim::GetDate() +const char *CS2Fixes::GetDate() { return __DATE__; } -const char *CS2Scrim::GetLogTag() +const char *CS2Fixes::GetLogTag() { - return "cs2scrim"; + return "CS2Scrim"; } -const char *CS2Scrim::GetAuthor() +const char *CS2Fixes::GetAuthor() { - return "marqdevx tweak over xen & poggu"; + return "marqdevx (ρλd)"; } -const char *CS2Scrim::GetDescription() +const char *CS2Fixes::GetDescription() { - return "A bunch of experiments thrown together into one big mess of a plugin."; + return "CS2Fixes plugin port, focused on team scrims and practice and not to impact the server performance"; } -const char *CS2Scrim::GetName() +const char *CS2Fixes::GetName() { - return "cs2scrim"; + return "CS2Scrim"; } -const char *CS2Scrim::GetURL() +const char *CS2Fixes::GetURL() { return "https://github.com/marqdevx/mm-cs2-scrim"; -} \ No newline at end of file +} diff --git a/src/cs2fixes.h b/src/cs2fixes.h index faf51daf..bb58d17a 100644 --- a/src/cs2fixes.h +++ b/src/cs2fixes.h @@ -26,18 +26,19 @@ #include "networksystem/inetworkserializer.h" #include -class CS2Scrim : public ISmmPlugin, public IMetamodListener +class CS2Fixes : public ISmmPlugin, public IMetamodListener { public: bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late); void Hook_PostEvent(CSplitScreenSlot nSlot, bool bLocalOnly, int nClientCount, const uint64* clients, INetworkSerializable* pEvent, const void* pData, unsigned long nSize, NetChannelBufType_t bufType); bool Unload(char *error, size_t maxlen); - void Hook_StartupServer(const GameSessionConfiguration_t& config, ISource2WorldSession*, const char*); bool Pause(char *error, size_t maxlen); bool Unpause(char *error, size_t maxlen); void AllPluginsLoaded(); public: //hooks + void Hook_GameServerSteamAPIActivated(); + void Hook_GameServerSteamAPIDeactivated(); void OnLevelInit( char const *pMapName, char const *pMapEntities, char const *pOldLevel, @@ -47,14 +48,15 @@ class CS2Scrim : public ISmmPlugin, public IMetamodListener void OnLevelShutdown(); void Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastTick ); void Hook_ClientActive( CPlayerSlot slot, bool bLoadGame, const char *pszName, uint64 xuid ); - void Hook_ClientDisconnect( CPlayerSlot slot, int reason, const char *pszName, uint64 xuid, const char *pszNetworkID ); + void Hook_ClientDisconnect( CPlayerSlot slot, ENetworkDisconnectionReason reason, const char *pszName, uint64 xuid, const char *pszNetworkID ); void Hook_ClientPutInServer( CPlayerSlot slot, char const *pszName, int type, uint64 xuid ); void Hook_ClientSettingsChanged( CPlayerSlot slot ); void Hook_OnClientConnected( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, const char *pszAddress, bool bFakePlayer ); bool Hook_ClientConnect( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, bool unk1, CBufferString *pRejectReason ); void Hook_ClientCommand( CPlayerSlot nSlot, const CCommand &_cmd ); - void Hook_CheckTransmit(CCheckTransmitInfo **ppInfoList, int infoCount, CBitVec<16384> &unionTransmitEdicts, - const Entity2Networkable_t **pNetworkables, const uint16 *pEntityIndicies, int nEntities); + + void Hook_DispatchConCommand(ConCommandHandle cmd, const CCommandContext& ctx, const CCommand& args); + void Hook_StartupServer(const GameSessionConfiguration_t& config, ISource2WorldSession*, const char*); public: const char *GetAuthor(); @@ -67,6 +69,6 @@ class CS2Scrim : public ISmmPlugin, public IMetamodListener const char *GetLogTag(); }; -extern CS2Scrim g_CS2Scrim; +extern CS2Fixes g_CS2Fixes; PLUGIN_GLOBALVARS(); diff --git a/src/ctimer.cpp b/src/ctimer.cpp index a3e6be91..8ef4b9dd 100644 --- a/src/ctimer.cpp +++ b/src/ctimer.cpp @@ -23,15 +23,9 @@ CUtlLinkedList g_timers; void RemoveTimers() { - FOR_EACH_LL(g_timers, i) - { - delete g_timers[i]; - } - - g_timers.RemoveAll(); + g_timers.PurgeAndDeleteElements(); } - void RemoveMapTimers() { for (int i = g_timers.Tail(); i != g_timers.InvalidIndex();) diff --git a/src/ctimer.h b/src/ctimer.h index 46b24448..cf0668a2 100644 --- a/src/ctimer.h +++ b/src/ctimer.h @@ -23,35 +23,37 @@ class CTimerBase { public: - CTimerBase(float time, bool repeat, bool preserveMapChange) : - m_flTime(time), m_bRepeat(repeat), m_bPreserveMapChange(preserveMapChange) {}; + CTimerBase(float flInitialInterval, bool bPreserveMapChange) : + m_flInterval(flInitialInterval), m_bPreserveMapChange(bPreserveMapChange) {}; - virtual void Execute() = 0; + virtual bool Execute() = 0; - float m_flTime; + float m_flInterval; float m_flLastExecute = -1; - bool m_bRepeat; bool m_bPreserveMapChange; }; extern CUtlLinkedList g_timers; - +// Timer functions should return the time until next execution, or a negative value like -1.0f to stop +// Having an interval of 0 is fine, in this case it will run on every game frame class CTimer : public CTimerBase { public: - CTimer(float time, bool repeat, bool preserveMapChange, std::function func) : - CTimerBase(time, repeat, preserveMapChange), m_func(func) + CTimer(float flInitialInterval, bool bPreserveMapChange, std::function func) : + CTimerBase(flInitialInterval, bPreserveMapChange), m_func(func) { g_timers.AddToTail(this); }; - virtual void Execute() override + inline bool Execute() override { - m_func(); + m_flInterval = m_func(); + + return m_flInterval >= 0; } - std::function m_func; + std::function m_func; }; diff --git a/src/cvars.cpp b/src/cvars.cpp index 86a5f1c7..f2bb9150 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -24,6 +24,8 @@ static uint64 g_iFlagsToRemove = (FCVAR_HIDDEN | FCVAR_DEVELOPMENTONLY | FCVAR_MISSING0 | FCVAR_MISSING1 | FCVAR_MISSING2 | FCVAR_MISSING3); +static constexpr const char *pUnCheatCvars[] = { "bot_stop", "bot_freeze", "bot_zombie" }; + void UnlockConVars() { if (!g_pCVar) @@ -42,7 +44,16 @@ void UnlockConVars() hCvarHandle.Set(hCvarHandle.Get() + 1); - if (!pCvar || !(pCvar->flags & g_iFlagsToRemove)) + if (!pCvar) + continue; + + for (int i = 0; i < sizeof(pUnCheatCvars) / sizeof(*pUnCheatCvars); i++) + { + if (!V_strcmp(pCvar->m_pszName, pUnCheatCvars[i])) + pCvar->flags &= ~FCVAR_CHEAT; + } + + if (!(pCvar->flags & g_iFlagsToRemove)) continue; pCvar->flags &= ~g_iFlagsToRemove; @@ -57,8 +68,6 @@ void UnlockConCommands() if (!g_pCVar) return; - ConCommand *say = g_pCVar->GetCommand(g_pCVar->FindCommand("say")); - int iUnhiddenConCommands = 0; ConCommand *pConCommand = nullptr; @@ -81,3 +90,89 @@ void UnlockConCommands() Message("Removed hidden flags from %d commands\n", iUnhiddenConCommands); } + +CON_COMMAND_F(c_dump_cvars, "dump all cvars", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND) +{ + ConVar *pCvar = nullptr; + ConVarHandle hCvarHandle; + hCvarHandle.Set(0); + + do + { + pCvar = g_pCVar->GetConVar(hCvarHandle); + + hCvarHandle.Set(hCvarHandle.Get() + 1); + + if (pCvar) + { + switch (pCvar->m_eVarType) + { + case EConVarType_Bool: + Message("%s : bool : %s\n", pCvar->m_pszName, (bool)pCvar->values ? "true" : "false"); + break; + case EConVarType_Int16: + Message("%s : int16 : %i\n", pCvar->m_pszName, *(int16*)&pCvar->values); + break; + case EConVarType_Int32: + Message("%s : int32 : %i\n", pCvar->m_pszName, *(int32*)&pCvar->values); + break; + case EConVarType_Int64: + Message("%s : int64 : %lli\n", pCvar->m_pszName, (int64)pCvar->values); + break; + case EConVarType_UInt16: + Message("%s : uint16 : %i\n", pCvar->m_pszName, *(uint16*)&pCvar->values); + break; + case EConVarType_UInt32: + Message("%s : uint32 : %i\n", pCvar->m_pszName, *(uint32*)&pCvar->values); + break; + case EConVarType_UInt64: + Message("%s : uint64 : %lli\n", pCvar->m_pszName, (uint64)pCvar->values); + break; + case EConVarType_Float32: + Message("%s : float32 : %.2f\n", pCvar->m_pszName, *(float32 *)&pCvar->values); + break; + case EConVarType_Float64: + Message("%s : float64 : %.2f\n", pCvar->m_pszName, *(float64 *)&pCvar->values); + break; + case EConVarType_String: + Message("%s : string : %s\n", pCvar->m_pszName, (char *)pCvar->values); + break; + + case EConVarType_Color: + int color[4]; + V_memcpy(&color, &pCvar->values, sizeof(color)); + Message("%s : color : %.2f %.2f %.2f %.2f\n", pCvar->m_pszName, color[0], color[1], color[2], color[3]); + break; + + case EConVarType_Vector2: + float vec2[2]; + V_memcpy(&vec2, &pCvar->values, sizeof(vec2)); + Message("%s : vector2 : %.2f %.2f\n", pCvar->m_pszName, vec2[0], vec2[1]); + break; + + case EConVarType_Vector3: + float vec3[3]; + V_memcpy(&vec3, &pCvar->values, sizeof(vec3)); + Message("%s : vector3 : %.2f %.2f %.2f\n", pCvar->m_pszName, vec3[0], vec3[1], vec3[2]); + break; + + case EConVarType_Vector4: + float vec4[4]; + V_memcpy(&vec4, &pCvar->values, sizeof(vec4)); + Message("%s : vector4 : %.2f %.2f %.2f %.2f\n", pCvar->m_pszName, vec4[0], vec4[1], vec4[2], vec4[3]); + break; + + case EConVarType_Qangle: + float angle[3]; + V_memcpy(&vec3, &pCvar->values, sizeof(angle)); + Message("%s : qangle : %.2f %.2f %.2f\n", pCvar->m_pszName, angle[0], angle[1], angle[2]); + break; + + default: + Message("%s : unknown type : %p\n", pCvar->m_pszName, (void*)pCvar->values); + break; + }; + } + + } while (pCvar); +} diff --git a/src/detours.cpp b/src/detours.cpp index aa4e9127..5992d981 100644 --- a/src/detours.cpp +++ b/src/detours.cpp @@ -22,7 +22,6 @@ #include "module.h" #include "addresses.h" #include "commands.h" -#include "interfaces/cs2_interfaces.h" #include "detours.h" #include "ctimer.h" #include "irecipientfilter.h" @@ -31,127 +30,161 @@ #include "entity/cbasemodelentity.h" #include "entity/ccsweaponbase.h" #include "entity/ctriggerpush.h" +#include "entity/cgamerules.h" +#include "entity/ctakedamageinfo.h" +#include "entity/services.h" #include "playermanager.h" #include "igameevents.h" #include "gameconfig.h" + +#define VPROF_ENABLED +#include "tier0/vprof.h" + #include "tier0/memdbgon.h" extern CGlobalVars *gpGlobals; -extern CEntitySystem *g_pEntitySystem; +extern CGameEntitySystem *g_pEntitySystem; extern IGameEventManager2 *g_gameEventManager; +extern CCSGameRules *g_pGameRules; -DECLARE_DETOUR(Host_Say, Detour_Host_Say); DECLARE_DETOUR(UTIL_SayTextFilter, Detour_UTIL_SayTextFilter); DECLARE_DETOUR(UTIL_SayText2Filter, Detour_UTIL_SayText2Filter); -DECLARE_DETOUR(IsHearingClient, Detour_IsHearingClient); +//DECLARE_DETOUR(IsHearingClient, Detour_IsHearingClient); DECLARE_DETOUR(CSoundEmitterSystem_EmitSound, Detour_CSoundEmitterSystem_EmitSound); -DECLARE_DETOUR(CCSWeaponBase_Spawn, Detour_CCSWeaponBase_Spawn); -DECLARE_DETOUR(TriggerPush_Touch, Detour_TriggerPush_Touch); - -void FASTCALL Detour_TriggerPush_Touch(CTriggerPush* pPush, Z_CBaseEntity* pOther) +//DECLARE_DETOUR(TriggerPush_Touch, Detour_TriggerPush_Touch); +DECLARE_DETOUR(CGameRules_Constructor, Detour_CGameRules_Constructor); +//DECLARE_DETOUR(CBaseEntity_TakeDamageOld, Detour_CBaseEntity_TakeDamageOld); +DECLARE_DETOUR(CCSPlayer_WeaponServices_CanUse, Detour_CCSPlayer_WeaponServices_CanUse); +//DECLARE_DETOUR(CEntityIdentity_AcceptInput, Detour_CEntityIdentity_AcceptInput); +//DECLARE_DETOUR(CNavMesh_GetNearestNavArea, Detour_CNavMesh_GetNearestNavArea); +//DECLARE_DETOUR(FixLagCompEntityRelationship, Detour_FixLagCompEntityRelationship); + +void FASTCALL Detour_CGameRules_Constructor(CGameRules *pThis) { - MoveType_t movetype = pOther->m_MoveType(); + g_pGameRules = (CCSGameRules*)pThis; + CGameRules_Constructor(pThis); +} - // VPhysics handling doesn't need any changes - if (movetype == MOVETYPE_VPHYSICS) - { - TriggerPush_Touch(pPush, pOther); - return; - } +static bool g_bBlockMolotovSelfDmg = false; +static bool g_bBlockAllDamage = false; - Z_CBaseEntity* pPushEnt = (Z_CBaseEntity*)pPush; +FAKE_BOOL_CVAR(cs2f_block_molotov_self_dmg, "Whether to block self-damage from molotovs", g_bBlockMolotovSelfDmg, false, false) +FAKE_BOOL_CVAR(cs2f_block_all_dmg, "Whether to block all damage to players", g_bBlockAllDamage, false, false) - // SF_TRIG_PUSH_ONCE is handled fine already - if (pPushEnt->m_spawnflags() & SF_TRIG_PUSH_ONCE) - { - TriggerPush_Touch(pPush, pOther); - return; - } +void FASTCALL Detour_CSoundEmitterSystem_EmitSound(ISoundEmitterSystemBase *pSoundEmitterSystem, CEntityIndex *a2, IRecipientFilter &filter, uint32 a4, void *a5) +{ + //ConMsg("Detour_CSoundEmitterSystem_EmitSound\n"); + CSoundEmitterSystem_EmitSound(pSoundEmitterSystem, a2, filter, a4, a5); +} - if (movetype == MOVETYPE_NONE || movetype == MOVETYPE_PUSH || movetype == MOVETYPE_NOCLIP) - return; - CCollisionProperty* collisionProp = pOther->m_pCollision(); - if (!IsSolid(collisionProp->m_nSolidType(), collisionProp->m_usSolidFlags())) - return; +void SayChatMessageWithTimer(IRecipientFilter &filter, const char *pText, CCSPlayerController *pPlayer, uint64 eMessageType) +{ + char buf[256]; - if (!pPush->PassesTriggerFilters(pOther)) - return; + // Filter console message - remove non-alphanumeric chars and convert to lowercase + uint32 uiTextLength = strlen(pText); + uint32 uiFilteredTextLength = 0; + char filteredText[256]; - if (pOther->m_CBodyComponent()->m_pSceneNode()->m_pParent()) - return; + for (uint32 i = 0; i < uiTextLength; i++) + { + if (pText[i] >= 'A' && pText[i] <= 'Z') + filteredText[uiFilteredTextLength++] = pText[i] + 32; + if (pText[i] == ' ' || (pText[i] >= '0' && pText[i] <= '9') || (pText[i] >= 'a' && pText[i] <= 'z')) + filteredText[uiFilteredTextLength++] = pText[i]; + } + filteredText[uiFilteredTextLength] = '\0'; - Vector vecAbsDir; + // Split console message into words seperated by the space character + CUtlVector> words; + V_SplitString(filteredText, " ", words); - matrix3x4_t mat = pPushEnt->m_CBodyComponent()->m_pSceneNode()->EntityToWorldTransform(); - - Vector pushDir = pPush->m_vecPushDirEntitySpace(); + //Word count includes the first word "Console:" at index 0, first relevant word is at index 1 + int iWordCount = words.Count(); + uint32 uiTriggerTimerLength = 0; - // i had issues with vectorrotate on linux so i did it here - vecAbsDir.x = pushDir.x * mat[0][0] + pushDir.y * mat[0][1] + pushDir.z * mat[0][2]; - vecAbsDir.y = pushDir.x * mat[1][0] + pushDir.y * mat[1][1] + pushDir.z * mat[1][2]; - vecAbsDir.z = pushDir.x * mat[2][0] + pushDir.y * mat[2][1] + pushDir.z * mat[2][2]; + if (iWordCount == 2) + uiTriggerTimerLength = V_StringToUint32(words.Element(1), 0, NULL, NULL, PARSING_FLAG_SKIP_WARNING); - Vector vecPush = vecAbsDir * pPush->m_flPushSpeed(); + for (int i = 1; i < iWordCount && uiTriggerTimerLength == 0; i++) + { + uint32 uiCurrentValue = V_StringToUint32(words.Element(i), 0, NULL, NULL, PARSING_FLAG_SKIP_WARNING); + uint32 uiNextWordLength = 0; + char* pNextWord = NULL; - uint32 flags = pOther->m_fFlags(); + if (i + 1 < iWordCount) + { + pNextWord = words.Element(i + 1); + uiNextWordLength = strlen(pNextWord); + } - if (flags & (FL_BASEVELOCITY)) - { - vecPush = vecPush + pOther->m_vecBaseVelocity(); - } + // Case: ... X sec(onds) ... or ... X min(utes) ... + if (pNextWord != NULL && uiNextWordLength > 2 && uiCurrentValue > 0) + { + if (pNextWord[0] == 's' && pNextWord[1] == 'e' && pNextWord[2] == 'c') + uiTriggerTimerLength = uiCurrentValue; + if (pNextWord[0] == 'm' && pNextWord[1] == 'i' && pNextWord[2] == 'n') + uiTriggerTimerLength = uiCurrentValue * 60; + } - if (vecPush.z > 0 && (flags & FL_ONGROUND)) - { - addresses::SetGroundEntity(pOther, nullptr); - Vector origin = pOther->GetAbsOrigin(); - origin.z += 1.0f; + // Case: ... Xs - only support up to 3 digit numbers (in seconds) for this timer parse method + if (uiCurrentValue == 0) + { + char* pCurrentWord = words.Element(i); + uint32 uiCurrentScanLength = MIN(strlen(pCurrentWord), 4); - pOther->Teleport(&origin, nullptr, nullptr); + for (uint32 j = 0; j < uiCurrentScanLength; j++) + { + if (pCurrentWord[j] >= '0' && pCurrentWord[j] <= '9') + continue; + + if (pCurrentWord[j] == 's') + { + pCurrentWord[j] = '\0'; + uiTriggerTimerLength = V_StringToUint32(pCurrentWord, 0, NULL, NULL, PARSING_FLAG_SKIP_WARNING); + } + break; + } + } } + words.PurgeAndDeleteElements(); - pOther->m_vecBaseVelocity(vecPush); + float fCurrentRoundClock = g_pGameRules->m_iRoundTime - (gpGlobals->curtime - g_pGameRules->m_fRoundStartTime.Get().m_Value); - flags |= (FL_BASEVELOCITY); - pOther->m_fFlags(flags); -} - -void FASTCALL Detour_CCSWeaponBase_Spawn(CBaseEntity *pThis, void *a2) -{ - const char *pszClassName = pThis->m_pEntity->m_designerName.String(); + // Only display trigger time if the timer is greater than 4 seconds, and time expires within the round + if ((uiTriggerTimerLength > 4) && (fCurrentRoundClock > uiTriggerTimerLength)) + { + int iTriggerTime = fCurrentRoundClock - uiTriggerTimerLength; -#ifdef _DEBUG - Message("Weapon spawn: %s\n", pszClassName); -#endif + // Round timer to nearest whole second + if ((int)(fCurrentRoundClock - 0.5f) == (int)fCurrentRoundClock) + iTriggerTime++; - CCSWeaponBase_Spawn(pThis, a2); + int mins = iTriggerTime / 60; + int secs = iTriggerTime % 60; -} + V_snprintf(buf, sizeof(buf), "%s %s %s %2d:%02d", " \7CONSOLE:\4", pText + sizeof("Console:"), "\x10- @", mins, secs); + } + else + V_snprintf(buf, sizeof(buf), "%s %s", " \7CONSOLE:\4", pText + sizeof("Console:")); -void FASTCALL Detour_CSoundEmitterSystem_EmitSound(ISoundEmitterSystemBase *pSoundEmitterSystem, CEntityIndex *a2, IRecipientFilter &filter, uint32 a4, void *a5) -{ - //ConMsg("Detour_CSoundEmitterSystem_EmitSound\n"); - CSoundEmitterSystem_EmitSound(pSoundEmitterSystem, a2, filter, a4, a5); + UTIL_SayTextFilter(filter, buf, pPlayer, eMessageType); } -bool FASTCALL Detour_IsHearingClient(void* serverClient, int index) -{ - ZEPlayer* player = g_playerManager->GetPlayer(index); - if (player && player->IsMuted()) - return false; +bool g_bEnableTriggerTimer = false; - return IsHearingClient(serverClient, index); -} +FAKE_BOOL_CVAR(cs2f_trigger_timer_enable, "Whether to process countdown messages said by Console (e.g. Hold for 10 seconds) and append the round time where the countdown resolves", g_bEnableTriggerTimer, false, false) void FASTCALL Detour_UTIL_SayTextFilter(IRecipientFilter &filter, const char *pText, CCSPlayerController *pPlayer, uint64 eMessageType) { - int entindex = filter.GetRecipientIndex(0).Get(); - CCSPlayerController *target = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)entindex); - if (pPlayer) return UTIL_SayTextFilter(filter, pText, pPlayer, eMessageType); + if (g_bEnableTriggerTimer) + return SayChatMessageWithTimer(filter, pText, pPlayer, eMessageType); + char buf[256]; V_snprintf(buf, sizeof(buf), "%s %s", " \7CONSOLE:\4", pText + sizeof("Console:")); @@ -168,10 +201,10 @@ void FASTCALL Detour_UTIL_SayText2Filter( const char *param3, const char *param4) { - int entindex = filter.GetRecipientIndex(0).Get() + 1; - CCSPlayerController *target = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)entindex); - #ifdef _DEBUG + CPlayerSlot slot = filter.GetRecipientIndex(0); + CCSPlayerController* target = CCSPlayerController::FromSlot(slot); + if (target) Message("Chat from %s to %s: %s\n", param1, target->GetPlayerName(), param2); #endif @@ -179,33 +212,6 @@ void FASTCALL Detour_UTIL_SayText2Filter( UTIL_SayText2Filter(filter, pEntity, eMessageType, msg_name, param1, param2, param3, param4); } -void FASTCALL Detour_Host_Say(CCSPlayerController *pController, CCommand &args, bool teamonly, int unk1, const char *unk2) -{ - bool bGagged = pController && g_playerManager->GetPlayer(pController->GetPlayerSlot())->IsGagged(); - - if (!bGagged && *args[1] != '/') - { - Host_Say(pController, args, teamonly, unk1, unk2); - - if (pController) - { - IGameEvent *pEvent = g_gameEventManager->CreateEvent("player_chat"); - - if (pEvent) - { - pEvent->SetBool("teamonly", teamonly); - pEvent->SetInt("userid", pController->entindex()); - pEvent->SetString("text", args[1]); - - g_gameEventManager->FireEvent(pEvent, true); - } - } - } - - if (*args[1] == '!' || *args[1] == '/' || *args[1] == '.') - ParseChatCommand(args[1], pController); -} - void Detour_Log() { return; @@ -232,7 +238,7 @@ CDetour g_LoggingDetours[] = //CDetour( Detour_IsChannelEnabled, "LoggingSystem_IsChannelEnabled" ), }; -void ToggleLogs() +CON_COMMAND_F(toggle_logs, "Toggle printing most logs and warnings", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND) { static bool bBlock = false; @@ -254,6 +260,13 @@ void ToggleLogs() bBlock = !bBlock; } +bool FASTCALL Detour_CCSPlayer_WeaponServices_CanUse(CCSPlayer_WeaponServices *pWeaponServices, CBasePlayerWeapon* pPlayerWeapon) +{ + + + return CCSPlayer_WeaponServices_CanUse(pWeaponServices, pPlayerWeapon); +} + CUtlVector g_vecDetours; bool InitDetours(CGameConfig *gameConfig) @@ -276,25 +289,19 @@ bool InitDetours(CGameConfig *gameConfig) success = false; UTIL_SayText2Filter.EnableDetour(); - if (!Host_Say.CreateDetour(gameConfig)) - success = false; - Host_Say.EnableDetour(); - - if (!IsHearingClient.CreateDetour(gameConfig)) - success = false; - IsHearingClient.EnableDetour(); - if (!CSoundEmitterSystem_EmitSound.CreateDetour(gameConfig)) success = false; CSoundEmitterSystem_EmitSound.EnableDetour(); - if (!CCSWeaponBase_Spawn.CreateDetour(gameConfig)) + if (!CGameRules_Constructor.CreateDetour(gameConfig)) success = false; - CCSWeaponBase_Spawn.EnableDetour(); + CGameRules_Constructor.EnableDetour(); - if (!TriggerPush_Touch.CreateDetour(gameConfig)) + if (!CCSPlayer_WeaponServices_CanUse.CreateDetour(gameConfig)) success = false; - TriggerPush_Touch.EnableDetour(); + CCSPlayer_WeaponServices_CanUse.EnableDetour(); + + return success; } diff --git a/src/detours.h b/src/detours.h index 2b3400ba..283a7af2 100644 --- a/src/detours.h +++ b/src/detours.h @@ -19,9 +19,10 @@ #pragma once #include "cdetour.h" +#include + -class CCheckTransmitInfo; class IRecipientFilter; class ISoundEmitterSystemBase; class CBaseEntity; @@ -31,18 +32,19 @@ class CEntityIndex; class CCommand; class CTriggerPush; class CGameConfig; +class CGameRules; +class CTakeDamageInfo; +class CCSPlayer_WeaponServices; +class CBasePlayerWeapon; bool InitDetours(CGameConfig *gameConfig); void FlushAllDetours(); void FASTCALL Detour_UTIL_SayTextFilter(IRecipientFilter &, const char *, CCSPlayerController *, uint64); void FASTCALL Detour_UTIL_SayText2Filter(IRecipientFilter &, CCSPlayerController *, uint64, const char *, const char *, const char *, const char *, const char *); -void FASTCALL Detour_Host_Say(CCSPlayerController *, CCommand &, bool, int, const char *); -bool FASTCALL Detour_IsHearingClient(void*, int); + void FASTCALL Detour_CSoundEmitterSystem_EmitSound(ISoundEmitterSystemBase *, CEntityIndex *, IRecipientFilter &, uint32, void *); -//void FASTCALL Detour_CBaseEntity_Spawn(CBaseEntity *, void *); -void FASTCALL Detour_CCSWeaponBase_Spawn(CBaseEntity *, void *); -void FASTCALL Detour_TriggerPush_Touch(CTriggerPush* pPush, Z_CBaseEntity* pOther); -extern CDetour Host_Say; -extern CDetour UTIL_SayTextFilter; +void FASTCALL Detour_CGameRules_Constructor(CGameRules *pThis); + +bool FASTCALL Detour_CCSPlayer_WeaponServices_CanUse(CCSPlayer_WeaponServices *, CBasePlayerWeapon *); diff --git a/src/entitylistener.cpp b/src/entitylistener.cpp new file mode 100644 index 00000000..610ddc98 --- /dev/null +++ b/src/entitylistener.cpp @@ -0,0 +1,58 @@ +/** + * ============================================================================= + * CS2Fixes + * Copyright (C) 2023 Source2ZE + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "entitylistener.h" +#include "common.h" +#include "cs2fixes.h" +#include "gameconfig.h" +#include "cs2_sdk/entity/cbaseentity.h" +#include "plat.h" + +extern CGameConfig *g_GameConfig; + +void Patch_GetHammerUniqueId(CEntityInstance *pEntity) +{ + static int offset = g_GameConfig->GetOffset("GetHammerUniqueId"); + void **vtable = *(void ***)pEntity; + + // xor al, al -> mov al, 1 + // so it always returns true and allows hammerid to be copied into the schema prop + Plat_WriteMemory(vtable[offset], (uint8_t*)"\xB0\x01", 2); +} + +void CEntityListener::OnEntitySpawned(CEntityInstance* pEntity) +{ +#ifdef _DEBUG + const char* pszClassName = pEntity->m_pEntity->m_designerName.String(); + Message("Entity spawned: %s\n", pszClassName); +#endif +} + +void CEntityListener::OnEntityCreated(CEntityInstance* pEntity) +{ + //ExecuteOnce(Patch_GetHammerUniqueId(pEntity)); +} + +void CEntityListener::OnEntityDeleted(CEntityInstance* pEntity) +{ +} + +void CEntityListener::OnEntityParentChanged(CEntityInstance* pEntity, CEntityInstance* pNewParent) +{ +} \ No newline at end of file diff --git a/src/cs2_sdk/interfaces/cs2_interfaces.h b/src/entitylistener.h similarity index 67% rename from src/cs2_sdk/interfaces/cs2_interfaces.h rename to src/entitylistener.h index 0c43684e..e5b41b02 100644 --- a/src/cs2_sdk/interfaces/cs2_interfaces.h +++ b/src/entitylistener.h @@ -18,14 +18,14 @@ */ #pragma once +#include "entitysystem.h" -#include "cgameresourceserviceserver.h" -#include "cschemasystem.h" +extern CGameEntitySystem* g_pEntitySystem; -namespace interfaces +class CEntityListener : public IEntityListener { - void Initialize(); - - inline CGameResourceService *pGameResourceServiceServer = nullptr; - inline CSchemaSystem *pSchemaSystem = nullptr; -} \ No newline at end of file + void OnEntitySpawned(CEntityInstance* pEntity) override; + void OnEntityCreated(CEntityInstance* pEntity) override; + void OnEntityDeleted(CEntityInstance* pEntity) override; + void OnEntityParentChanged(CEntityInstance* pEntity, CEntityInstance* pNewParent) override; +}; \ No newline at end of file diff --git a/src/events.cpp b/src/events.cpp index fde04c73..f4078a4c 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -23,24 +23,40 @@ #include "ctimer.h" #include "eventlistener.h" #include "entity/cbaseplayercontroller.h" +#include "entity/cgamerules.h" #include "tier0/memdbgon.h" extern IGameEventManager2 *g_gameEventManager; extern IServerGameClients *g_pSource2GameClients; -extern CEntitySystem *g_pEntitySystem; +extern CGameEntitySystem *g_pEntitySystem; +extern CGlobalVars *gpGlobals; +extern CCSGameRules *g_pGameRules; CUtlVector g_vecEventListeners; +extern CUtlVector coaches; +extern bool practiceMode; +extern bool no_flash_mode; +bool half_last_round = false; +bool swapped_teams = false; + +extern bool g_bEnablePractice; +extern bool g_bEnableCoach; + void RegisterEventListeners() { - if (!g_gameEventManager) + static bool bRegistered = false; + + if (bRegistered || !g_gameEventManager) return; FOR_EACH_VEC(g_vecEventListeners, i) { g_gameEventManager->AddListener(g_vecEventListeners[i], g_vecEventListeners[i]->GetEventName(), true); } + + bRegistered = true; } void UnregisterEventListeners() @@ -56,32 +72,113 @@ void UnregisterEventListeners() g_vecEventListeners.Purge(); } -bool g_bBlockTeamMessages = true; -CON_COMMAND_F(c_toggle_team_messages, "toggle team messages", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND) -{ - g_bBlockTeamMessages = !g_bBlockTeamMessages; -} GAME_EVENT_F(player_team) -{ - // Remove chat message for team changes - if (g_bBlockTeamMessages) - pEvent->SetBool("silent", true); +{ + CCSPlayerController* pController = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pEvent->GetUint64("userid") + 1)); + + if (coaches.Count() < 1) return; + FOR_EACH_VEC(coaches,i){ + if(pController->GetPlayerSlot() == coaches[i]->GetPlayerSlot()) pEvent->SetBool("silent", true); return; + //ClientPrint(pController, HUD_PRINTTALK, "coach slot %i", coaches[i]->GetPlayerSlot()); + } } -extern CUtlVector coaches; +GAME_EVENT_F(player_death){ + //TODO: hide only coach death notice +} + +GAME_EVENT_F(round_announce_last_round_half){ + if(!g_bEnableCoach) return; + + half_last_round = true; +} + +GAME_EVENT_F(round_prestart) +{ + if (coaches.Count() < 1 || !g_bEnableCoach) return; + + FOR_EACH_VEC(coaches,i){ + CCSPlayerController *pTarget = CCSPlayerController::FromSlot(coaches[i]->GetPlayerSlot()); + + if(!pTarget) return; //avoid crash if coach is not connected + //ClientPrint(pTarget, HUD_PRINTTALK, "coach slot side %i", coaches[i]->m_iTeamNum()); + + int currentTeam = pTarget->m_iTeamNum; + int newTeam = CS_TEAM_SPECTATOR; + + pTarget->m_pInGameMoneyServices->m_iAccount = 0; + + pTarget->ChangeTeam(CS_TEAM_SPECTATOR); + + //pTarget->GetPawn()->CommitSuicide(false, true); + + if(half_last_round && !swapped_teams){ + if(currentTeam == CS_TEAM_CT){ + newTeam = CS_TEAM_T; + }else{ + newTeam = CS_TEAM_CT; + } + }else{ + newTeam = currentTeam; + } + + CHandle hController = pTarget->GetHandle(); + + new CTimer(0.15f, false, [hController, newTeam]() + { + CCSPlayerController *pController = hController.Get(); + + if(!pController) return -1.0f; //avoid crash if coach is not connected + + pController->m_pInGameMoneyServices->m_iAccount = 0; + + pController->ChangeTeam(newTeam); + + new CTimer(0.0f, false, [hController, newTeam]() + { + CCSPlayerController *pController = hController.Get(); + if(!pController) return -1.0f; //avoid crash if coach is not connected + pController->GetPawn()->CommitSuicide(false, true); + pController->m_pInGameMoneyServices->m_iAccount = 0; + pController->m_pActionTrackingServices->m_matchStats().m_iDeaths = 0; + return -1.0f; + }); + + return -0.15f; + }); + + if(half_last_round) half_last_round = false; + } +} GAME_EVENT_F(round_start) { if (coaches.Count() < 1) return; FOR_EACH_VEC(coaches,i){ - CCSPlayerController *pTarget = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(coaches[i]->GetPlayerSlot() + 1)); + CCSPlayerController *pTarget = CCSPlayerController::FromSlot(coaches[i]->GetPlayerSlot()); coaches[i]->m_pInGameMoneyServices->m_iAccount = 0; - coaches[i]->GetPawn()->CommitSuicide(false, true); + //coaches[i]->GetPawn()->CommitSuicide(false, true); + + coaches[i]->m_pActionTrackingServices->m_matchStats().m_iKills = 0; + coaches[i]->m_pActionTrackingServices->m_matchStats().m_iDeaths = 0; + coaches[i]->m_pActionTrackingServices->m_matchStats().m_iAssists = 0; + coaches[i]->m_pActionTrackingServices->m_matchStats().m_iDamage = 0; + } +} + +GAME_EVENT_F(round_poststart) +{ + if (coaches.Count() < 1 || !g_bEnableCoach) return; + + FOR_EACH_VEC(coaches,i){ + CCSPlayerController *pTarget = CCSPlayerController::FromSlot(coaches[i]->GetPlayerSlot()); + + coaches[i]->m_pInGameMoneyServices->m_iAccount = 0; coaches[i]->m_pActionTrackingServices->m_matchStats().m_iKills = 0; coaches[i]->m_pActionTrackingServices->m_matchStats().m_iDeaths = 0; @@ -92,22 +189,96 @@ GAME_EVENT_F(round_start) GAME_EVENT_F(round_freeze_end) { - if (coaches.Count() < 1) return; + if (coaches.Count() < 1 || !g_bEnableCoach) return; FOR_EACH_VEC(coaches,i){ - CCSPlayerController *pTarget = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(coaches[i]->GetPlayerSlot() + 1)); + CCSPlayerController *pTarget = CCSPlayerController::FromSlot(coaches[i]->GetPlayerSlot()); + + if(!pTarget) return; //avoid crash if coach is not connected + + int currentTeam = pTarget->m_iTeamNum; + pTarget->ChangeTeam(CS_TEAM_SPECTATOR); + pTarget->ChangeTeam(currentTeam); + pTarget->GetPawn()->CommitSuicide(false, true); CHandle hController = pTarget->GetHandle(); - new CTimer(2.0f, false, false, [hController]() + new CTimer(2.0f, false, [hController]() { CCSPlayerController *pController = hController.Get(); + if(!pController) return -2.0f; //avoid crash if coach is not connected + int currentTeam = pController->m_iTeamNum; pController->ChangeTeam(CS_TEAM_SPECTATOR); pController->ChangeTeam(currentTeam); - return; + return -2.0f; }); } } + +GAME_EVENT_F(player_hurt){ + if(!practiceMode || !g_bEnablePractice) return; + + CCSPlayerController* pController = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pEvent->GetUint64("attacker") + 1)); + + if (!pController) + return; + + CCSPlayerController* pHurt = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pEvent->GetUint64("userid") + 1)); + //ClientPrintAll(HUD_PRINTTALK, "Smoke end %i", pEvent->GetUint64("entityid")); + int damage = pEvent->GetFloat("dmg_health"); + int actualHealth = pEvent->GetFloat("health"); + ClientPrint(pController, HUD_PRINTTALK, CHAT_PREFIX "Damage done \04%d \01to \04%s\1[\04%d\01]", damage , pHurt->GetPlayerName(), actualHealth); + +} + +GAME_EVENT_F(player_blind){ + if(!practiceMode || !g_bEnablePractice) return; + + CCSPlayerController* pAttacker = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pEvent->GetUint64("attacker") + 1)); + CBasePlayerController *pTarget = (CBasePlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pEvent->GetUint64("userid") + 1)); + + if(!pAttacker || !pTarget) + return; + + if(pTarget->GetPlayerName() && pEvent->GetFloat("blind_duration") > 0.0f) + ClientPrint(pAttacker, HUD_PRINTTALK, CHAT_PREFIX "Flashed \04%s\1 for \x04%f\1 s", pTarget->GetPlayerName(), pEvent->GetFloat("blind_duration")); + + CCSPlayerController* pController = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pEvent->GetUint64("userid") + 1)); + CCSPlayerPawnBase* cPlayerBase = (CCSPlayerPawnBase*)pController->GetPawn(); + + if(!pController) + return; + if(!cPlayerBase) + return; + + if(no_flash_mode) cPlayerBase->m_flFlashMaxAlpha = 2; + + if(pAttacker->GetPlayerSlot() != pController->GetPlayerSlot()) + ClientPrint(pController, HUD_PRINTTALK, CHAT_PREFIX "Flashed by \04%s\1, for \x04%f\1 s", pAttacker->GetPlayerName(), pEvent->GetFloat("blind_duration")); + +} + +GAME_EVENT_F(grenade_thrown){ + if (!practiceMode || !g_bEnablePractice) + return; + + CCSPlayerController* pController = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(pEvent->GetUint64("userid") + 1)); + + if (!pController) + return; + + //CCSPlayerPawn* cPlayerBase = (CCSPlayerPawn*)pController->GetPawn(); + Vector currentPos = pController->GetPawn()->GetAbsOrigin(); + + CCSPlayerPawnBase* cPlayerBase = (CCSPlayerPawnBase*)pController->GetPawn(); + QAngle currentAngle = cPlayerBase->m_angEyeAngles; + + //ClientPrintAll( HUD_PRINTTALK, CHAT_PREFIX "Pos: %f, %f, %f", currentPos.x, currentPos.y, currentPos.z); + + ZEPlayer *pPlayer = g_playerManager->GetPlayer(pController->GetPlayerSlot()); + pPlayer->lastThrow_position = currentPos; + pPlayer->lastThrow_rotation = currentAngle; +} \ No newline at end of file diff --git a/src/gameconfig.cpp b/src/gameconfig.cpp index 92cdbb9f..31bed9d5 100644 --- a/src/gameconfig.cpp +++ b/src/gameconfig.cpp @@ -21,7 +21,7 @@ bool CGameConfig::Init(IFileSystem *filesystem, char *conf_error, int conf_error return false; } - const KeyValues* game = m_pKeyValues->FindKey(m_szGameDir.c_str()); + KeyValues* game = m_pKeyValues->FindKey(m_szGameDir.c_str(), false); if (game) { #if defined _LINUX @@ -30,7 +30,7 @@ bool CGameConfig::Init(IFileSystem *filesystem, char *conf_error, int conf_error const char* platform = "windows"; #endif - const KeyValues* offsets = game->FindKey("Offsets"); + KeyValues* offsets = game->FindKey("Offsets", false); if (offsets) { FOR_EACH_SUBKEY(offsets, it) @@ -39,7 +39,7 @@ bool CGameConfig::Init(IFileSystem *filesystem, char *conf_error, int conf_error } } - const KeyValues* signatures = game->FindKey("Signatures"); + KeyValues *signatures = game->FindKey("Signatures", false); if (signatures) { FOR_EACH_SUBKEY(signatures, it) @@ -49,7 +49,7 @@ bool CGameConfig::Init(IFileSystem *filesystem, char *conf_error, int conf_error } } - const KeyValues* patches = game->FindKey("Patches"); + KeyValues *patches = game->FindKey("Patches", false); if (patches) { FOR_EACH_SUBKEY(patches, it) @@ -114,8 +114,8 @@ const char *CGameConfig::GetLibrary(const std::string& name) CModule **CGameConfig::GetModule(const char *name) { const char *library = this->GetLibrary(name); - if (library == NULL) - return NULL; + if (!library) + return nullptr; if (strcmp(library, "engine") == 0) return &modules::engine; @@ -131,13 +131,13 @@ CModule **CGameConfig::GetModule(const char *name) else if (strcmp(library, "hammer") == 0) return &modules::hammer; #endif - return NULL; + return nullptr; } bool CGameConfig::IsSymbol(const char *name) { const char *sigOrSymbol = this->GetSignature(name); - if (sigOrSymbol == NULL || strlen(sigOrSymbol) <= 0) + if (!sigOrSymbol || strlen(sigOrSymbol) <= 0) { Panic("Missing signature or symbol\n", name); return false; @@ -149,10 +149,10 @@ const char* CGameConfig::GetSymbol(const char *name) { const char *symbol = this->GetSignature(name); - if (symbol == NULL || strlen(symbol) <= 1) + if (!symbol || strlen(symbol) <= 1) { Panic("Missing symbol\n", name); - return NULL; + return nullptr; } return symbol + 1; } @@ -163,39 +163,46 @@ void *CGameConfig::ResolveSignature(const char *name) if (!module || !(*module)) { Panic("Invalid Module %s\n", name); - return NULL; + return nullptr; } void *address = nullptr; if (this->IsSymbol(name)) { const char *symbol = this->GetSymbol(name); - if (symbol == NULL) + if (!symbol) { Panic("Invalid symbol for %s\n", name); - return NULL; + return nullptr; } address = dlsym((*module)->m_hModule, symbol); } else { const char *signature = this->GetSignature(name); - if (signature == NULL) + if (!signature) { Panic("Failed to find signature for %s\n", name); - return NULL; + return nullptr; } - byte *pSignature = CGameConfig::HexToByte(signature); - if (pSignature == NULL) - return NULL; - address = (*module)->FindSignature(pSignature); + size_t iLength = 0; + byte *pSignature = HexToByte(signature, iLength); + if (!pSignature) + return nullptr; + + int error; + + address = (*module)->FindSignature(pSignature, iLength, error); + + if (error == SIG_FOUND_MULTIPLE) + Panic("!!!!!!!!!! Signature for %s occurs multiple times! Using first match but this might end up crashing!\n", name); } - if (address == NULL) + if (!address) { Panic("Failed to find address for %s\n", name); - return NULL; + return nullptr; } return address; } @@ -215,7 +222,7 @@ std::string CGameConfig::GetDirectoryName(const std::string &directoryPathInput) int CGameConfig::HexStringToUint8Array(const char* hexString, uint8_t* byteArray, size_t maxBytes) { - if (hexString == NULL) { + if (!hexString) { printf("Invalid hex string.\n"); return -1; } @@ -240,21 +247,21 @@ int CGameConfig::HexStringToUint8Array(const char* hexString, uint8_t* byteArray return byteCount; // Return the number of bytes successfully converted. } -byte *CGameConfig::HexToByte(const char *src) +byte *CGameConfig::HexToByte(const char *src, size_t &length) { - if (src == NULL || strlen(src) <= 0) + if (!src || strlen(src) <= 0) { Panic("Invalid hex string\n"); - return NULL; + return nullptr; } - size_t maxBytes = strlen(src) / 4; - uint8_t *dest = new uint8_t[maxBytes]; - int byteCount = CGameConfig::HexStringToUint8Array(src, dest, maxBytes); + length = strlen(src) / 4; + uint8_t *dest = new uint8_t[length]; + int byteCount = HexStringToUint8Array(src, dest, length); if (byteCount <= 0) { Panic("Invalid hex format %s\n", src); - return NULL; + return nullptr; } return (byte *)dest; } diff --git a/src/gameconfig.h b/src/gameconfig.h index 80360635..1c388682 100644 --- a/src/gameconfig.h +++ b/src/gameconfig.h @@ -26,7 +26,7 @@ class CGameConfig void *ResolveSignature(const char *name); static std::string GetDirectoryName(const std::string &directoryPathInput); static int HexStringToUint8Array(const char* hexString, uint8_t* byteArray, size_t maxBytes); - static byte *HexToByte(const char *src); + static byte *HexToByte(const char *src, size_t &length); private: std::string m_szGameDir; diff --git a/src/gamesystem.cpp b/src/gamesystem.cpp new file mode 100644 index 00000000..cb31aca4 --- /dev/null +++ b/src/gamesystem.cpp @@ -0,0 +1,77 @@ +/** + * ============================================================================= + * CS2Fixes + * Copyright (C) 2023 Source2ZE + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "common.h" +#include "gameconfig.h" +#include "addresses.h" +#include "gamesystem.h" +#include "adminsystem.h" + +extern CGameConfig *g_GameConfig; + +CBaseGameSystemFactory **CBaseGameSystemFactory::sm_pFirst = nullptr; + +CGameSystem g_GameSystem; +IGameSystemFactory *CGameSystem::sm_Factory = nullptr; + +// This mess is needed to get the pointer to sm_pFirst so we can insert game systems +bool InitGameSystems() +{ + // This signature directly points to the instruction referencing sm_pFirst, and the opcode is 3 bytes so we skip those + uint8 *ptr = (uint8*)g_GameConfig->ResolveSignature("IGameSystem_InitAllSystems_pFirst") + 3; + + if (!ptr) + { + Panic("Failed to InitGameSystems, see warnings above.\n"); + return false; + } + + // Grab the offset as 4 bytes + uint32 offset = *(uint32*)ptr; + + // Go to the next instruction, which is the starting point of the relative jump + ptr += 4; + + // Now grab our pointer + CBaseGameSystemFactory::sm_pFirst = (CBaseGameSystemFactory **)(ptr + offset); + + // And insert the game system(s) + CGameSystem::sm_Factory = new CGameSystemStaticFactory("CS2Fixes_GameSystem", &g_GameSystem); + + return true; +} + +GS_EVENT_MEMBER(CGameSystem, BuildGameSessionManifest) +{ + Message("CGameSystem::BuildGameSessionManifest\n"); + + IEntityResourceManifest *pResourceManifest = msg->m_pResourceManifest; + + // This takes any resource type, model or not + // Any resource adding MUST be done here, the resource manifest is not long-lived + // pResourceManifest->AddResource("characters/models/my_character_model.vmdl"); + +} + +// Called every frame before entities think +GS_EVENT_MEMBER(CGameSystem, ServerPreEntityThink) +{ + // This could've gone into CS2Fixes::Hook_GameFrame but I've kept it here as an example + //g_playerManager->FlashLightThink(); +} diff --git a/src/gamesystem.h b/src/gamesystem.h new file mode 100644 index 00000000..f89d1ced --- /dev/null +++ b/src/gamesystem.h @@ -0,0 +1,69 @@ +/** + * ============================================================================= + * CS2Fixes + * Copyright (C) 2023 Source2ZE + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +#pragma once + +#include "common.h" +#include "entitysystem.h" +#include "igamesystemfactory.h" + +bool InitGameSystems(); + +class CGameSystem : public CBaseGameSystem +{ +public: + GS_EVENT(BuildGameSessionManifest); + GS_EVENT(ServerPreEntityThink); + + void Shutdown() override + { + Message("CGameSystem::Shutdown\n"); + delete sm_Factory; + } + + void SetGameSystemGlobalPtrs(void *pValue) override + { + if (sm_Factory) + sm_Factory->SetGlobalPtr(pValue); + } + + bool DoesGameSystemReallocate() override + { + return sm_Factory->ShouldAutoAdd(); + } + + static IGameSystemFactory *sm_Factory; +}; + +// Quick and dirty definition +// MSVC for whatever reason flips overload ordering, and this has three of them +// So this is based on the linux bin which is correct, and MSVC will flip it to match the windows bin, fun +class IEntityResourceManifest +{ +public: + virtual void AddResource(const char*) = 0; + virtual void AddResource(const char*, void*) = 0; + virtual void AddResource(const char*, void*, void*, void*) = 0; + virtual void unk_04() = 0; + virtual void unk_05() = 0; + virtual void unk_06() = 0; + virtual void unk_07() = 0; + virtual void unk_08() = 0; + virtual void unk_09() = 0; + virtual void unk_10() = 0; +}; diff --git a/src/mempatch.cpp b/src/mempatch.cpp index a74c47ed..52d4e8ec 100644 --- a/src/mempatch.cpp +++ b/src/mempatch.cpp @@ -27,27 +27,31 @@ bool CMemPatch::PerformPatch(CGameConfig *gameConfig) { - m_pPatchAddress = gameConfig->ResolveSignature(m_pSignatureName); - if (m_pPatchAddress == NULL) - return false; + // If we already have an address, no need to look for it again + if (!m_pPatchAddress) + { + m_pPatchAddress = gameConfig->ResolveSignature(m_pSignatureName); + + if (!m_pPatchAddress) + return false; + } const char *patch = gameConfig->GetPatch(m_pszName); - if (patch == NULL) + if (!patch) { Panic("Failed to find patch for %s\n", m_pszName); return false; } - m_pPatch = gameConfig->HexToByte(patch); - if (m_pPatch == NULL) + m_pPatch = gameConfig->HexToByte(patch, m_iPatchLength); + if (!m_pPatch) return false; - m_iPatchLength = V_strlen((char*)m_pPatch); m_pOriginalBytes = new byte[m_iPatchLength]; V_memcpy(m_pOriginalBytes, m_pPatchAddress, m_iPatchLength); Plat_WriteMemory(m_pPatchAddress, (byte*)m_pPatch, m_iPatchLength); - Message("Successfully patched %s at %p\n", m_pszName, m_pPatchAddress); + Message("Patched %s at %p\n", m_pszName, m_pPatchAddress); return true; } diff --git a/src/mempatch.h b/src/mempatch.h index 7524fd4d..83e2f741 100644 --- a/src/mempatch.h +++ b/src/mempatch.h @@ -26,8 +26,8 @@ class CMemPatch { public: - CMemPatch(const char *pSignatureName, const char *pszName, int iRepeat = 1) : - m_pSignatureName(pSignatureName), m_pszName(pszName), m_iRepeat(iRepeat) + CMemPatch(const char *pSignatureName, const char *pszName) : + m_pSignatureName(pSignatureName), m_pszName(pszName) { m_pModule = nullptr; m_pPatchAddress = nullptr; @@ -49,7 +49,6 @@ class CMemPatch byte *m_pOriginalBytes; const char *m_pSignatureName; const char *m_pszName; - int m_iRepeat; - int m_iPatchLength; + size_t m_iPatchLength; void *m_pPatchAddress; }; diff --git a/src/patches.cpp b/src/patches.cpp index 510745b6..8b137891 100644 --- a/src/patches.cpp +++ b/src/patches.cpp @@ -1,105 +1 @@ -/** - * ============================================================================= - * CS2Fixes - * Copyright (C) 2023 Source2ZE - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ -#include "common.h" -#include "mempatch.h" -#include "icvar.h" -#include "irecipientfilter.h" -#include "interfaces/cs2_interfaces.h" -#include "entity/ccsplayercontroller.h" -#include "entity/ccsplayerpawn.h" -#include "entity/cbasemodelentity.h" -#include "addresses.h" -#include "patches.h" - -#include "tier0/memdbgon.h" - -CMemPatch g_CommonPatches[] = -{ - CMemPatch("ServerMovementUnlock", "ServerMovementUnlock"), - CMemPatch("VScriptEnable", "VScriptEnable"), - CMemPatch("CategorizeUnderwater", "CategorizeUnderwater"), - CMemPatch("WaterLevelGravity", "WaterLevelGravity"), -}; - -CMemPatch g_ClientPatches[] = -{ - CMemPatch("ClientMovementUnlock", "ClientMovementUnlock"), -}; - -#ifdef _WIN32 -CMemPatch g_ToolsPatches[] = -{ - // Remove some -nocustomermachine checks without needing -nocustomermachine itself as it can break stuff, mainly to enable device selection in compiles - CMemPatch("HammerNoCustomerMachine", "HammerNoCustomerMachine", 4), -}; -#endif - -bool InitPatches(CGameConfig *g_GameConfig) -{ - bool success = true; - for (int i = 0; i < sizeof(g_CommonPatches) / sizeof(*g_CommonPatches); i++) - { - if (!g_CommonPatches[i].PerformPatch(g_GameConfig)) - success = false; - } - - // Dedicated servers don't load client - if (!CommandLine()->HasParm("-dedicated")) - { - for (int i = 0; i < sizeof(g_ClientPatches) / sizeof(*g_ClientPatches); i++) - { - if (!g_ClientPatches[i].PerformPatch(g_GameConfig)) - success = false; - } - } - -#ifdef _WIN32 - // None of the tools are loaded without, well, -tools - if (CommandLine()->HasParm("-tools")) - { - for (int i = 0; i < sizeof(g_ToolsPatches) / sizeof(*g_ToolsPatches); i++) - { - if (!g_ToolsPatches[i].PerformPatch(g_GameConfig)) - success = false; - } - } -#endif - return success; -} - -void UndoPatches() -{ - for (int i = 0; i < sizeof(g_CommonPatches) / sizeof(*g_CommonPatches); i++) - g_CommonPatches[i].UndoPatch(); - - if (!CommandLine()->HasParm("-dedicated")) - { - for (int i = 0; i < sizeof(g_ClientPatches) / sizeof(*g_ClientPatches); i++) - g_ClientPatches[i].UndoPatch(); - } - -#ifdef _WIN32 - if (CommandLine()->HasParm("-tools")) - { - for (int i = 0; i < sizeof(g_ToolsPatches) / sizeof(*g_ToolsPatches); i++) - g_ToolsPatches[i].UndoPatch(); - } -#endif -} diff --git a/src/playermanager.cpp b/src/playermanager.cpp index f44431b5..c9113032 100644 --- a/src/playermanager.cpp +++ b/src/playermanager.cpp @@ -21,17 +21,27 @@ #include "utlstring.h" #include "playermanager.h" #include "adminsystem.h" + #include "entity/ccsplayercontroller.h" +#include "utils/entity.h" +#include "ctimer.h" #include "ctime" +#define VPROF_ENABLED +#include "tier0/vprof.h" + +#include "tier0/memdbgon.h" + extern IVEngineServer2 *g_pEngineServer2; -extern CEntitySystem *g_pEntitySystem; +extern CGameEntitySystem *g_pEntitySystem; +extern CGlobalVars *gpGlobals; void ZEPlayer::OnAuthenticated() { CheckAdmin(); CheckInfractions(); + //g_pUserPreferencesSystem->PullPreferences(GetPlayerSlot().Get()); } void ZEPlayer::CheckInfractions() @@ -58,22 +68,75 @@ void ZEPlayer::CheckAdmin() bool ZEPlayer::IsAdminFlagSet(uint64 iFlag) { - return m_iAdminFlags & iFlag; + return !iFlag || (m_iAdminFlags & iFlag); +} + + + +static float g_flFloodInterval = 0.75f; +static int g_iMaxFloodTokens = 3; +static float g_flFloodCooldown = 3.0f; + +FAKE_FLOAT_CVAR(cs2f_flood_interval, "Amount of time allowed between chat messages acquiring flood tokens", g_flFloodInterval, 0.75f, false) +FAKE_INT_CVAR(cs2f_max_flood_tokens, "Maximum number of flood tokens allowed before chat messages are blocked", g_iMaxFloodTokens, 3, false) +FAKE_FLOAT_CVAR(cs2f_flood_cooldown, "Amount of time to block messages for when a player floods", g_flFloodCooldown, 3.0f, false) + +bool ZEPlayer::IsFlooding() +{ + if (m_bGagged) return false; + + float time = gpGlobals->curtime; + float newTime = time + g_flFloodInterval; + + if (m_flLastTalkTime >= time) + { + if (m_iFloodTokens >= g_iMaxFloodTokens) + { + m_flLastTalkTime = newTime + g_flFloodCooldown; + return true; + } + else + { + m_iFloodTokens++; + } + } + else if(m_iFloodTokens > 0) + { + // Remove one flood token when player chats within time limit (slow decay) + m_iFloodTokens--; + } + + m_flLastTalkTime = newTime; + return false; } void CPlayerManager::OnBotConnected(CPlayerSlot slot) { m_vecPlayers[slot.Get()] = new ZEPlayer(slot, true); - m_UserIdLookup[g_pEngineServer2->GetPlayerUserId(slot).Get()] = slot.Get(); } -bool CPlayerManager::OnClientConnected(CPlayerSlot slot) +bool CPlayerManager::OnClientConnected(CPlayerSlot slot, uint64 xuid, const char* pszNetworkID) { Assert(m_vecPlayers[slot.Get()] == nullptr); Message("%d connected\n", slot.Get()); ZEPlayer *pPlayer = new ZEPlayer(slot); + pPlayer->SetUnauthenticatedSteamId(new CSteamID(xuid)); + + std::string ip(pszNetworkID); + + // Remove port + for (int i = 0; i < ip.length(); i++) + { + if (ip[i] == ':') + { + ip = ip.substr(0, i); + break; + } + } + + pPlayer->SetIpAddress(ip); if (!g_pAdminSystem->ApplyInfractions(pPlayer)) { @@ -84,7 +147,10 @@ bool CPlayerManager::OnClientConnected(CPlayerSlot slot) pPlayer->SetConnected(); m_vecPlayers[slot.Get()] = pPlayer; - m_UserIdLookup[g_pEngineServer2->GetPlayerUserId(slot).Get()] = slot.Get(); + + ResetPlayerFlags(slot.Get()); + + //g_pMapVoteSystem->ClearPlayerInfo(slot.Get()); return true; } @@ -93,16 +159,42 @@ void CPlayerManager::OnClientDisconnect(CPlayerSlot slot) { Message("%d disconnected\n", slot.Get()); + //g_pUserPreferencesSystem->PushPreferences(slot.Get()); + //g_pUserPreferencesSystem->ClearPreferences(slot.Get()); + delete m_vecPlayers[slot.Get()]; m_vecPlayers[slot.Get()] = nullptr; - m_UserIdLookup[g_pEngineServer2->GetPlayerUserId(slot).Get()] = -1; + + ResetPlayerFlags(slot.Get()); + + //g_pMapVoteSystem->ClearPlayerInfo(slot.Get()); +} + +void CPlayerManager::OnClientPutInServer(CPlayerSlot slot) +{ + ZEPlayer* pPlayer = m_vecPlayers[slot.Get()]; + + pPlayer->SetInGame(true); +} + +void CPlayerManager::OnLateLoad() +{ + for (int i = 0; i < gpGlobals->maxClients; i++) + { + CCSPlayerController* pController = CCSPlayerController::FromSlot(i); + + if (!pController || !pController->IsController() || !pController->IsConnected()) + continue; + + OnClientConnected(i, pController->m_steamID(), "0.0.0.0:0"); + } } void CPlayerManager::TryAuthenticate() { - for (int i = 0; i < sizeof(m_vecPlayers) / sizeof(*m_vecPlayers); i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { - if (m_vecPlayers[i] == nullptr) + if (m_vecPlayers[i] == nullptr || !m_vecPlayers[i]->IsConnected()) continue; if (m_vecPlayers[i]->IsAuthenticated() || m_vecPlayers[i]->IsFakeClient()) @@ -111,8 +203,8 @@ void CPlayerManager::TryAuthenticate() if (g_pEngineServer2->IsClientFullyAuthenticated(i)) { m_vecPlayers[i]->SetAuthenticated(); - m_vecPlayers[i]->SetSteamId(g_pEngineServer2->GetClientSteamID(i)); - Message("%lli authenticated %d\n", m_vecPlayers[i]->GetSteamId()->ConvertToUint64(), i); + m_vecPlayers[i]->SetSteamId(m_vecPlayers[i]->GetUnauthenticatedSteamId()); + Message("%lli authenticated %d\n", m_vecPlayers[i]->GetSteamId64(), i); m_vecPlayers[i]->OnAuthenticated(); } } @@ -120,7 +212,7 @@ void CPlayerManager::TryAuthenticate() void CPlayerManager::CheckInfractions() { - for (int i = 0; i < sizeof(m_vecPlayers) / sizeof(*m_vecPlayers); i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { if (m_vecPlayers[i] == nullptr || m_vecPlayers[i]->IsFakeClient()) continue; @@ -131,55 +223,55 @@ void CPlayerManager::CheckInfractions() g_pAdminSystem->SaveInfractions(); } -void CPlayerManager::CheckHideDistances() -{ - if (!g_pEntitySystem) - return; - for (int i = 0; i < MAXPLAYERS; i++) - { - auto player = GetPlayer(i); +static bool g_bHideTeammatesOnly = false; - if (!player) - continue; +FAKE_BOOL_CVAR(cs2f_hide_teammates_only, "Whether to hide teammates only", g_bHideTeammatesOnly, false, false) - player->ClearTransmit(); - auto hideDistance = player->GetHideDistance(); +static bool g_bInfiniteAmmo = false; +FAKE_BOOL_CVAR(cs2f_infinite_reserve_ammo, "Whether to enable infinite reserve ammo on weapons", g_bInfiniteAmmo, false, false) - if (!hideDistance) - continue; +void CPlayerManager::SetupInfiniteAmmo() +{ + new CTimer(5.0f, false, []() + { + if (!g_bInfiniteAmmo) + return 5.0f; - auto pController = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)(i + 1)); + for (int i = 0; i < gpGlobals->maxClients; i++) + { + CCSPlayerController* pController = CCSPlayerController::FromSlot(i); - if (!pController) - continue; + if (!pController) + continue; - auto pPawn = pController->GetPawn(); + auto pPawn = pController->GetPawn(); - if (!pPawn || !pPawn->IsAlive()) - continue; + if (!pPawn) + continue; - auto vecPosition = pPawn->GetAbsOrigin(); - int team = pController->m_iTeamNum; + CPlayer_WeaponServices* pWeaponServices = pPawn->m_pWeaponServices; - for (int j = 1; j < MAXPLAYERS + 1; j++) - { - if (j - 1 == i) + // it can sometimes be null when player joined on the very first round? + if (!pWeaponServices) continue; - auto pTargetController = (CCSPlayerController *)g_pEntitySystem->GetBaseEntity((CEntityIndex)j); + CUtlVector>* weapons = pWeaponServices->m_hMyWeapons(); - if (pTargetController) + FOR_EACH_VEC(*weapons, i) { - auto pTargetPawn = pTargetController->GetPawn(); + CBasePlayerWeapon* weapon = (*weapons)[i].Get(); - if (pTargetPawn && pTargetPawn->IsAlive() && pTargetController->m_iTeamNum == team) - { - player->SetTransmit(j - 1, pTargetPawn->GetAbsOrigin().DistToSqr(vecPosition) <= hideDistance * hideDistance); - } + if (!weapon) + continue; + + if (weapon->GetWeaponVData()->m_GearSlot() == GEAR_SLOT_RIFLE || weapon->GetWeaponVData()->m_GearSlot() == GEAR_SLOT_PISTOL) + weapon->AcceptInput("SetReserveAmmoAmount", "999"); // 999 will be automatically clamped to the weapons m_nPrimaryReserveAmmoMax } } - } + + return 5.0f; + }); } ETargetType CPlayerManager::TargetPlayerString(int iCommandClient, const char* target, int& iNumClients, int *clients) @@ -193,6 +285,8 @@ ETargetType CPlayerManager::TargetPlayerString(int iCommandClient, const char* t targetType = ETargetType::T; else if (!V_stricmp(target, "@ct")) targetType = ETargetType::CT; + else if (!V_stricmp(target, "@spec")) + targetType = ETargetType::SPECTATOR; else if (!V_stricmp(target, "@random")) targetType = ETargetType::RANDOM; else if (!V_stricmp(target, "@randomt")) @@ -200,45 +294,50 @@ ETargetType CPlayerManager::TargetPlayerString(int iCommandClient, const char* t else if (!V_stricmp(target, "@randomct")) targetType = ETargetType::RANDOM_CT; - if (targetType == ETargetType::SELF) + if (targetType == ETargetType::SELF && iCommandClient != -1) { clients[iNumClients++] = iCommandClient; } else if (targetType == ETargetType::ALL) { - for (int i = 0; i < sizeof(m_vecPlayers) / sizeof(*m_vecPlayers); i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { if (m_vecPlayers[i] == nullptr) continue; + CCSPlayerController* player = CCSPlayerController::FromSlot(i); + + if (!player || !player->IsController() || !player->IsConnected()) + continue; + clients[iNumClients++] = i; } } - else if (targetType == ETargetType::T || targetType == ETargetType::CT) + else if (targetType >= ETargetType::SPECTATOR) { - for (int i = 0; i < sizeof(m_vecPlayers) / sizeof(*m_vecPlayers); i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { if (m_vecPlayers[i] == nullptr) continue; - CBasePlayerController* player = (CBasePlayerController*)g_pEntitySystem->GetBaseEntity((CEntityIndex)(i + 1)); + CCSPlayerController* player = CCSPlayerController::FromSlot(i); - if (!player) + if (!player || !player->IsController() || !player->IsConnected()) continue; - if (player->m_iTeamNum() != (targetType == ETargetType::T ? CS_TEAM_T : CS_TEAM_CT)) + if (player->m_iTeamNum() != (targetType == ETargetType::T ? CS_TEAM_T : targetType == ETargetType::CT ? CS_TEAM_CT : CS_TEAM_SPECTATOR)) continue; clients[iNumClients++] = i; } } - else if (targetType >= ETargetType::RANDOM) + else if (targetType >= ETargetType::RANDOM && targetType <= ETargetType::RANDOM_CT) { int attempts = 0; while (iNumClients == 0 && attempts < 10000) { - int slot = rand() % ((sizeof(m_vecPlayers) / sizeof(*m_vecPlayers)) - 1); + int slot = rand() % (gpGlobals->maxClients - 1); // Prevent infinite loop attempts++; @@ -246,9 +345,9 @@ ETargetType CPlayerManager::TargetPlayerString(int iCommandClient, const char* t if (m_vecPlayers[slot] == nullptr) continue; - CBasePlayerController* player = (CBasePlayerController*)g_pEntitySystem->GetBaseEntity((CEntityIndex)(slot + 1)); + CCSPlayerController* player = CCSPlayerController::FromSlot(slot); - if (!player) + if (!player || !player->IsController() || !player->IsConnected()) continue; if (targetType >= ETargetType::RANDOM_T && (player->m_iTeamNum() != (targetType == ETargetType::RANDOM_T ? CS_TEAM_T : CS_TEAM_CT))) @@ -264,19 +363,21 @@ ETargetType CPlayerManager::TargetPlayerString(int iCommandClient, const char* t if (userid != -1) { targetType = ETargetType::PLAYER; - clients[iNumClients++] = GetSlotFromUserId(userid).Get(); + CCSPlayerController* player = CCSPlayerController::FromSlot(GetSlotFromUserId(userid).Get()); + if(player && player->IsController() && player->IsConnected()) + clients[iNumClients++] = GetSlotFromUserId(userid).Get(); } } else { - for (int i = 0; i < sizeof(m_vecPlayers) / sizeof(*m_vecPlayers); i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { if (m_vecPlayers[i] == nullptr) continue; - CBasePlayerController* player = (CBasePlayerController*)g_pEntitySystem->GetBaseEntity((CEntityIndex)(i + 1)); + CCSPlayerController* player = CCSPlayerController::FromSlot(i); - if (!player) + if (!player || !player->IsController() || !player->IsConnected()) continue; if (V_stristr(player->GetPlayerName(), target)) @@ -291,15 +392,94 @@ ETargetType CPlayerManager::TargetPlayerString(int iCommandClient, const char* t return targetType; } -CPlayerSlot CPlayerManager::GetSlotFromUserId(int userid) +ZEPlayer *CPlayerManager::GetPlayer(CPlayerSlot slot) +{ + if (slot.Get() < 0 || slot.Get() >= gpGlobals->maxClients) + return nullptr; + + return m_vecPlayers[slot.Get()]; +}; + +// In userids, the lower byte is always the player slot +CPlayerSlot CPlayerManager::GetSlotFromUserId(uint16 userid) { - return m_UserIdLookup[userid]; + return CPlayerSlot(userid & 0xFF); } -ZEPlayer *CPlayerManager::GetPlayerFromUserId(int userid) +ZEPlayer *CPlayerManager::GetPlayerFromUserId(uint16 userid) { - if (m_UserIdLookup[userid] == -1) + uint8 index = userid & 0xFF; + + if (index >= gpGlobals->maxClients) return nullptr; - return m_vecPlayers[m_UserIdLookup[userid]]; -} \ No newline at end of file + return m_vecPlayers[index]; +} + +ZEPlayer* CPlayerManager::GetPlayerFromSteamId(uint64 steamid) +{ + for (ZEPlayer* player : m_vecPlayers) + { + if (player && player->IsAuthenticated() && player->GetSteamId64() == steamid) + return player; + } + + return nullptr; +} + +void CPlayerManager::SetPlayerStopSound(int slot, bool set) +{ + if (set) + m_nUsingStopSound |= ((uint64)1 << slot); + else + m_nUsingStopSound &= ~((uint64)1 << slot); + + // Set the user prefs if the player is ingame + ZEPlayer* pPlayer = m_vecPlayers[slot]; + if (!pPlayer) return; + + uint64 iSlotMask = (uint64)1 << slot; + int iStopPreferenceStatus = (m_nUsingStopSound & iSlotMask)?1:0; + int iSilencePreferenceStatus = (m_nUsingSilenceSound & iSlotMask)?2:0; + //g_pUserPreferencesSystem->SetPreferenceInt(slot, SOUND_STATUS_PREF_KEY_NAME, iStopPreferenceStatus + iSilencePreferenceStatus); +} + +void CPlayerManager::SetPlayerSilenceSound(int slot, bool set) +{ + if (set) + m_nUsingSilenceSound |= ((uint64)1 << slot); + else + m_nUsingSilenceSound &= ~((uint64)1 << slot); + + // Set the user prefs if the player is ingame + ZEPlayer* pPlayer = m_vecPlayers[slot]; + if (!pPlayer) return; + + uint64 iSlotMask = (uint64)1 << slot; + int iStopPreferenceStatus = (m_nUsingStopSound & iSlotMask)?1:0; + int iSilencePreferenceStatus = (m_nUsingSilenceSound & iSlotMask)?2:0; + //g_pUserPreferencesSystem->SetPreferenceInt(slot, SOUND_STATUS_PREF_KEY_NAME, iStopPreferenceStatus + iSilencePreferenceStatus); +} + +void CPlayerManager::SetPlayerStopDecals(int slot, bool set) +{ + if (set) + m_nUsingStopDecals |= ((uint64)1 << slot); + else + m_nUsingStopDecals &= ~((uint64)1 << slot); + + // Set the user prefs if the player is ingame + ZEPlayer* pPlayer = m_vecPlayers[slot]; + if (!pPlayer) return; + + uint64 iSlotMask = (uint64)1 << slot; + int iDecalPreferenceStatus = (m_nUsingStopDecals & iSlotMask)?1:0; + //g_pUserPreferencesSystem->SetPreferenceInt(slot, DECAL_PREF_KEY_NAME, iDecalPreferenceStatus); +} + +void CPlayerManager::ResetPlayerFlags(int slot) +{ + SetPlayerStopSound(slot, false); + SetPlayerSilenceSound(slot, true); + SetPlayerStopDecals(slot, true); +} diff --git a/src/playermanager.h b/src/playermanager.h index 61bc7b2e..108d1af7 100644 --- a/src/playermanager.h +++ b/src/playermanager.h @@ -23,6 +23,12 @@ #include "steam/steamclientpublic.h" #include #include "bitvec.h" +#include "entity/lights.h" +#include "entity/cparticlesystem.h" + +#define DECAL_PREF_KEY_NAME "hide_decals" +#define HIDE_DISTANCE_PREF_KEY_NAME "hide_distance" +#define SOUND_STATUS_PREF_KEY_NAME "sound_status" enum class ETargetType { NONE, @@ -32,6 +38,7 @@ enum class ETargetType { RANDOM_T, RANDOM_CT, ALL, + SPECTATOR, T, CT, }; @@ -42,54 +49,101 @@ class ZEPlayer ZEPlayer(CPlayerSlot slot, bool m_bFakeClient = false): m_slot(slot), m_bFakeClient(m_bFakeClient) { m_bAuthenticated = false; - m_bStopSound = false; - m_bStopDecals = true; m_iAdminFlags = 0; m_SteamID = nullptr; m_bGagged = false; m_bMuted = false; m_iHideDistance = 0; m_bConnected = false; + m_iTotalDamage = 0; + m_iTotalHits = 0; + m_iTotalKills = 0; + m_bVotedRTV = false; + m_bVotedExtend = false; + m_bIsInfected = false; + m_flRTVVoteTime = 0; + m_flExtendVoteTime = 0; + m_iFloodTokens = 0; + m_flLastTalkTime = 0; + m_bInGame = false; + m_iMZImmunity = 0; // out of 100 + m_flNominateTime = -60.0f; + + lastThrow_position = Vector(0,0,0); + } + + ~ZEPlayer() + { + } bool IsFakeClient() { return m_bFakeClient; } bool IsAuthenticated() { return m_bAuthenticated; } bool IsConnected() { return m_bConnected; } + uint64 GetUnauthenticatedSteamId64() { return m_UnauthenticatedSteamID->ConvertToUint64(); } + const CSteamID* GetUnauthenticatedSteamId() { return m_UnauthenticatedSteamID; } uint64 GetSteamId64() { return m_SteamID->ConvertToUint64(); } const CSteamID* GetSteamId() { return m_SteamID; } bool IsAdminFlagSet(uint64 iFlag); + bool IsFlooding(); void SetAuthenticated() { m_bAuthenticated = true; } void SetConnected() { m_bConnected = true; } + void SetUnauthenticatedSteamId(const CSteamID* steamID) { m_UnauthenticatedSteamID = steamID; } void SetSteamId(const CSteamID* steamID) { m_SteamID = steamID; } + uint64 GetAdminFlags() { return m_iAdminFlags; } void SetAdminFlags(uint64 iAdminFlags) { m_iAdminFlags = iAdminFlags; } void SetPlayerSlot(CPlayerSlot slot) { m_slot = slot; } void SetMuted(bool muted) { m_bMuted = muted; } void SetGagged(bool gagged) { m_bGagged = gagged; } void SetTransmit(int index, bool shouldTransmit) { shouldTransmit ? m_shouldTransmit.Set(index) : m_shouldTransmit.Clear(index); } void ClearTransmit() { m_shouldTransmit.ClearAll(); } - void SetHideDistance(int distance) { m_iHideDistance = distance; } + void SetTotalDamage(int damage) { m_iTotalDamage = damage; } + void SetTotalHits(int hits) { m_iTotalHits = hits; } + void SetTotalKills(int kills) { m_iTotalKills = kills; } + void SetRTVVote(bool bRTVVote) { m_bVotedRTV = bRTVVote; } + void SetRTVVoteTime(float flCurtime) { m_flRTVVoteTime = flCurtime; } + void SetExtendVote(bool bExtendVote) { m_bVotedExtend = bExtendVote; } + void SetInfectState(bool bInfectState) { m_bIsInfected = bInfectState; } + void SetExtendVoteTime(float flCurtime) { m_flExtendVoteTime = flCurtime; } + void SetIpAddress(std::string strIp) { m_strIp = strIp; } + void SetInGame(bool bInGame) { m_bInGame = bInGame; } + void SetImmunity(int iMZImmunity) { m_iMZImmunity = iMZImmunity; } + void SetNominateTime(float flCurtime) { m_flNominateTime = flCurtime; } + - void ToggleStopSound() { m_bStopSound = !m_bStopSound; } - void ToggleStopDecals() { m_bStopDecals = !m_bStopDecals; } - bool IsUsingStopSound() { return m_bStopSound; } - bool IsUsingStopDecals() { return m_bStopDecals; } bool IsMuted() { return m_bMuted; } bool IsGagged() { return m_bGagged; } bool ShouldBlockTransmit(int index) { return m_shouldTransmit.Get(index); } - int GetHideDistance() { return m_iHideDistance; } CPlayerSlot GetPlayerSlot() { return m_slot; } + int GetTotalDamage() { return m_iTotalDamage; } + int GetTotalHits() { return m_iTotalHits; } + int GetTotalKills() { return m_iTotalKills; } + bool GetRTVVote() { return m_bVotedRTV; } + float GetRTVVoteTime() { return m_flRTVVoteTime; } + bool GetExtendVote() { return m_bVotedExtend; } + bool IsInfected() { return m_bIsInfected; } + float GetExtendVoteTime() { return m_flExtendVoteTime; } + const char* GetIpAddress() { return m_strIp.c_str(); } + bool IsInGame() { return m_bInGame; } + int GetImmunity() { return m_iMZImmunity; } + float GetNominateTime() { return m_flNominateTime; } void OnAuthenticated(); void CheckAdmin(); void CheckInfractions(); + + + Vector lastThrow_position; + QAngle lastThrow_rotation; + + private: bool m_bAuthenticated; bool m_bConnected; + const CSteamID* m_UnauthenticatedSteamID; const CSteamID* m_SteamID; - bool m_bStopSound; - bool m_bStopDecals; bool m_bFakeClient; bool m_bMuted; bool m_bGagged; @@ -97,31 +151,73 @@ class ZEPlayer uint64 m_iAdminFlags; int m_iHideDistance; CBitVec m_shouldTransmit; + int m_iTotalDamage; + int m_iTotalHits; + int m_iTotalKills; + bool m_bVotedRTV; + float m_flRTVVoteTime; + bool m_bVotedExtend; + bool m_bIsInfected; + float m_flExtendVoteTime; + int m_iFloodTokens; + float m_flLastTalkTime; + std::string m_strIp; + bool m_bInGame; + int m_iMZImmunity; + float m_flNominateTime; + }; class CPlayerManager { public: - CPlayerManager() + CPlayerManager(bool late = false) { V_memset(m_vecPlayers, 0, sizeof(m_vecPlayers)); - V_memset(m_UserIdLookup, -1, sizeof(m_UserIdLookup)); + m_nUsingStopSound = 0; + m_nUsingSilenceSound = -1; // On by default + m_nUsingStopDecals = -1; // On by default + + if (late) + OnLateLoad(); } - bool OnClientConnected(CPlayerSlot slot); + bool OnClientConnected(CPlayerSlot slot, uint64 xuid, const char* pszNetworkID); void OnClientDisconnect(CPlayerSlot slot); void OnBotConnected(CPlayerSlot slot); + void OnClientPutInServer(CPlayerSlot slot); + void OnLateLoad(); void TryAuthenticate(); void CheckInfractions(); - void CheckHideDistances(); - CPlayerSlot GetSlotFromUserId(int userid); - ZEPlayer *GetPlayerFromUserId(int userid); + + void SetupInfiniteAmmo(); + CPlayerSlot GetSlotFromUserId(uint16 userid); + ZEPlayer *GetPlayerFromUserId(uint16 userid); + ZEPlayer *GetPlayerFromSteamId(uint64 steamid); ETargetType TargetPlayerString(int iCommandClient, const char* target, int &iNumClients, int *clients); - ZEPlayer *GetPlayer(CPlayerSlot slot) { return m_vecPlayers[slot.Get()]; }; + + ZEPlayer *GetPlayer(CPlayerSlot slot); + + uint64 GetStopSoundMask() { return m_nUsingStopSound; } + uint64 GetSilenceSoundMask() { return m_nUsingSilenceSound; } + uint64 GetStopDecalsMask() { return m_nUsingStopDecals; } + + void SetPlayerStopSound(int slot, bool set); + void SetPlayerSilenceSound(int slot, bool set); + void SetPlayerStopDecals(int slot, bool set); + + void ResetPlayerFlags(int slot); + + bool IsPlayerUsingStopSound(int slot) { return m_nUsingStopSound & ((uint64)1 << slot); } + bool IsPlayerUsingSilenceSound(int slot) { return m_nUsingSilenceSound & ((uint64)1 << slot); } + bool IsPlayerUsingStopDecals(int slot) { return m_nUsingStopDecals & ((uint64)1 << slot); } private: - ZEPlayer* m_vecPlayers[MAXPLAYERS]; - uint16 m_UserIdLookup[USHRT_MAX+1]; + ZEPlayer *m_vecPlayers[MAXPLAYERS]; + + uint64 m_nUsingStopSound; + uint64 m_nUsingSilenceSound; + uint64 m_nUsingStopDecals; }; extern CPlayerManager *g_playerManager; \ No newline at end of file diff --git a/src/utils/entity.cpp b/src/utils/entity.cpp index 79619d73..5597ff5d 100644 --- a/src/utils/entity.cpp +++ b/src/utils/entity.cpp @@ -18,23 +18,54 @@ */ #include "entity.h" + +#include "../addresses.h" #include "../common.h" -#include "platform.h" +#include "../gameconfig.h" +#include "../utils/virtual.h" #include "entitysystem.h" +#include "platform.h" +#include "entity/cgamerules.h" #include "tier0/memdbgon.h" -extern CEntitySystem *g_pEntitySystem; +extern CGameEntitySystem *g_pEntitySystem; +extern CGameConfig *g_GameConfig; +extern CCSGameRules *g_pGameRules; + +class Z_CBaseEntity; -CEntityInstance* UTIL_FindEntityByClassname(CEntityInstance* pStart, const char* name) +Z_CBaseEntity *UTIL_FindPickerEntity(CBasePlayerController *pPlayer) { - CEntityIdentity* pEntity = pStart ? pStart->m_pEntity->m_pNext : g_pEntitySystem->m_EntityList.m_pFirstActiveEntity; + static int offset = g_GameConfig->GetOffset("CGameRules_FindPickerEntity"); - for (; pEntity; pEntity = pEntity->m_pNext) + if (offset < 0) { - if (!V_strnicmp(pEntity->m_designerName.String(), name, V_strlen(name))) - return pEntity->m_pInstance; - }; + Panic("Missing offset for CGameRules_FindPickerEntity!\n"); + return nullptr; + } + + return CALL_VIRTUAL(Z_CBaseEntity *, offset, g_pGameRules, pPlayer); +} + +Z_CBaseEntity *UTIL_FindEntityByClassname(CEntityInstance *pStartEntity, const char *szName) +{ + return addresses::CGameEntitySystem_FindEntityByClassName(g_pEntitySystem, pStartEntity, szName); +} - return nullptr; +Z_CBaseEntity *UTIL_FindEntityByName(CEntityInstance *pStartEntity, const char *szName, + CEntityInstance *pSearchingEntity, CEntityInstance *pActivator, CEntityInstance *pCaller, IEntityFindFilter *pFilter) +{ + return addresses::CGameEntitySystem_FindEntityByName(g_pEntitySystem, pStartEntity, szName, pSearchingEntity, pActivator, pCaller, pFilter); } + +Z_CBaseEntity* CreateEntityByName(const char* className) +{ + return addresses::CreateEntityByName(className, -1); +} +/* +void UTIL_AddEntityIOEvent(CEntityInstance *pTarget, const char *pszInput, + CEntityInstance *pActivator, CEntityInstance *pCaller, variant_t value, float flDelay) +{ + addresses::CEntitySystem_AddEntityIOEvent(g_pEntitySystem, pTarget, pszInput, pActivator, pCaller, &value, flDelay, 0); +}*/ diff --git a/src/utils/entity.h b/src/utils/entity.h index 15c35bf3..787b958a 100644 --- a/src/utils/entity.h +++ b/src/utils/entity.h @@ -19,6 +19,25 @@ #pragma once +#include "platform.h" +#include "datamap.h" +#include "string_t.h" +#include "variant.h" + class CEntityInstance; +class Z_CBaseEntity; +class CBasePlayerController; +class IEntityFindFilter; + +Z_CBaseEntity *UTIL_FindPickerEntity(CBasePlayerController *pPlayer); +Z_CBaseEntity *UTIL_FindEntityByClassname(CEntityInstance *pStart, const char *name); +Z_CBaseEntity *UTIL_FindEntityByName(CEntityInstance *pStartEntity, const char *szName, + CEntityInstance *pSearchingEntity = nullptr, CEntityInstance *pActivator = nullptr, + CEntityInstance *pCaller = nullptr, IEntityFindFilter *pFilter = nullptr); +Z_CBaseEntity* CreateEntityByName(const char* className); -CEntityInstance* UTIL_FindEntityByClassname(CEntityInstance* pStart, const char* name); \ No newline at end of file +// Add an entity IO event to the event queue, just like a map would +// The queue is processed after all entities are simulated every frame +void UTIL_AddEntityIOEvent(CEntityInstance *pTarget, const char *pszInput, + CEntityInstance *pActivator = nullptr, CEntityInstance *pCaller = nullptr, + variant_t value = variant_t(""), float flDelay = 0.0f); diff --git a/src/utils/module.h b/src/utils/module.h index 92f88740..24f7cf5b 100644 --- a/src/utils/module.h +++ b/src/utils/module.h @@ -28,6 +28,13 @@ #include #endif +enum SigError +{ + SIG_OK, + SIG_NOT_FOUND, + SIG_FOUND_MULTIPLE, +}; + class CModule { public: @@ -54,15 +61,14 @@ class CModule Error("Failed to get module info for %s, error %d\n", szModule, e); #endif - Message("Initialized module %s base: %p | size: %d\n", m_pszModule, m_base, m_size); + Message("Initialized module %s base: 0x%p | size: %d\n", m_pszModule, m_base, m_size); } - void *FindSignature(const byte *pData) + void *FindSignature(const byte *pData, size_t iSigLength, int &error) { unsigned char *pMemory; void *return_addr = nullptr; - - size_t iSigLength = V_strlen((const char *)pData); + error = 0; pMemory = (byte*)m_base; @@ -73,10 +79,21 @@ class CModule { Matches++; if (Matches == iSigLength) + { + if (return_addr) + { + error = SIG_FOUND_MULTIPLE; + return return_addr; + } + return_addr = (void *)(pMemory + i); + } } } + if (!return_addr) + error = SIG_NOT_FOUND; + return return_addr; } @@ -92,7 +109,7 @@ class CModule if (!pInterface) Error("Could not find %s in %s\n", name, m_pszModule); - Message("Found %s in %s!\n", name, m_pszModule); + Message("Found interface %s in %s\n", name, m_pszModule); return pInterface; } diff --git a/src/utils/plat_unix.cpp b/src/utils/plat_unix.cpp index 47334bf4..07a1060b 100644 --- a/src/utils/plat_unix.cpp +++ b/src/utils/plat_unix.cpp @@ -187,8 +187,8 @@ static int get_prot(void* pAddr, size_t nSize) *dst++ = *src++; *dst = 0; - uintptr_t nStart = (uintptr_t)strtoul(start, NULL, 16); - uintptr_t nEnd = (uintptr_t)strtoul(end, NULL, 16); + uintptr_t nStart = (uintptr_t)strtoul(start, nullptr, 16); + uintptr_t nEnd = (uintptr_t)strtoul(end, nullptr, 16); if (nStart < nAddr && nEnd >(nAddr + nSize)) { diff --git a/vendor/funchook/lib/Debug/distorm.lib b/vendor/funchook/lib/Debug/distorm.lib new file mode 100644 index 00000000..c6fb3983 Binary files /dev/null and b/vendor/funchook/lib/Debug/distorm.lib differ diff --git a/vendor/funchook/lib/Debug/distorm.pdb b/vendor/funchook/lib/Debug/distorm.pdb new file mode 100644 index 00000000..c15ddfee Binary files /dev/null and b/vendor/funchook/lib/Debug/distorm.pdb differ diff --git a/vendor/funchook/lib/Debug/funchook.lib b/vendor/funchook/lib/Debug/funchook.lib new file mode 100644 index 00000000..319115e7 Binary files /dev/null and b/vendor/funchook/lib/Debug/funchook.lib differ diff --git a/vendor/funchook/lib/Debug/funchook.pdb b/vendor/funchook/lib/Debug/funchook.pdb new file mode 100644 index 00000000..4f5c4a8f Binary files /dev/null and b/vendor/funchook/lib/Debug/funchook.pdb differ diff --git a/vendor/funchook/lib/Debug/libdistorm.a b/vendor/funchook/lib/Debug/libdistorm.a new file mode 100644 index 00000000..d449bda6 Binary files /dev/null and b/vendor/funchook/lib/Debug/libdistorm.a differ diff --git a/vendor/funchook/lib/Debug/libfunchook.a b/vendor/funchook/lib/Debug/libfunchook.a new file mode 100644 index 00000000..572919fb Binary files /dev/null and b/vendor/funchook/lib/Debug/libfunchook.a differ diff --git a/vendor/funchook/lib/Release/distorm.lib b/vendor/funchook/lib/Release/distorm.lib new file mode 100644 index 00000000..31aa0b3c Binary files /dev/null and b/vendor/funchook/lib/Release/distorm.lib differ diff --git a/vendor/funchook/lib/Release/funchook.lib b/vendor/funchook/lib/Release/funchook.lib new file mode 100644 index 00000000..7ce89598 Binary files /dev/null and b/vendor/funchook/lib/Release/funchook.lib differ diff --git a/vendor/funchook/lib/libdistorm.a b/vendor/funchook/lib/Release/libdistorm.a similarity index 100% rename from vendor/funchook/lib/libdistorm.a rename to vendor/funchook/lib/Release/libdistorm.a diff --git a/vendor/funchook/lib/libfunchook.a b/vendor/funchook/lib/Release/libfunchook.a similarity index 100% rename from vendor/funchook/lib/libfunchook.a rename to vendor/funchook/lib/Release/libfunchook.a diff --git a/vendor/funchook/lib/distorm.lib b/vendor/funchook/lib/distorm.lib deleted file mode 100644 index 746006f8..00000000 Binary files a/vendor/funchook/lib/distorm.lib and /dev/null differ diff --git a/vendor/funchook/lib/funchook.lib b/vendor/funchook/lib/funchook.lib deleted file mode 100644 index c321ae51..00000000 Binary files a/vendor/funchook/lib/funchook.lib and /dev/null differ diff --git a/vendor/nlohmann/json.hpp b/vendor/nlohmann/json.hpp new file mode 100644 index 00000000..8b72ea65 --- /dev/null +++ b/vendor/nlohmann/json.hpp @@ -0,0 +1,24765 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple +#include // char_traits + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template