Merge branch 'indev' into launcher_rework

This commit is contained in:
Kawe Mazidjatari 2024-06-01 11:13:27 +02:00
commit 3e281d785c
1553 changed files with 660560 additions and 45761 deletions

View File

@ -14,7 +14,7 @@ apply_project_settings()
include_directories( "${ENGINE_SOURCE_DIR}" ) include_directories( "${ENGINE_SOURCE_DIR}" )
include_directories( "${ENGINE_SOURCE_DIR}/public" ) include_directories( "${ENGINE_SOURCE_DIR}/public" )
include_directories( "${ENGINE_SOURCE_DIR}/thirdparty" ) include_directories( "${THIRDPARTY_SOURCE_DIR}" )
# Include the subdirectories that contain the individual projects # Include the subdirectories that contain the individual projects
add_subdirectory( "${ENGINE_SOURCE_DIR}" ) add_subdirectory( "${ENGINE_SOURCE_DIR}" )

View File

@ -42,10 +42,6 @@ which are located in `<gamedir>\platform\cfg\startup_*.cfg`.
This is not a cheat or hack; attempting to use the SDK on the live version of the game could result in a permanent account ban.<br /> This is not a cheat or hack; attempting to use the SDK on the live version of the game could result in a permanent account ban.<br />
The supported game versions are: The supported game versions are:
* S0 `R5pc_r5launch_J1557_CL387233_2019_01_28_07_43_PM`.
* S0 `R5pc_r5launch_J1624A_CL394493_2019_02_24_09_29_PM`.
* S1 `R5pc_r5launch_N52A_CL399039_2019_03_12_03_21_PM`.
* S2 `R5pc_r5launch_N428_CL436418_2019_08_07_09_35_PM`.
* S3 `R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM`. * S3 `R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM`.
## Pylon [DISCLAIMER] ## Pylon [DISCLAIMER]

View File

@ -29,6 +29,47 @@ Microsoft Detours
// SOFTWARE. // SOFTWARE.
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
************************************************************************************
NVIDIA NvAPI
************************************************************************************
// Copyright © 2012 NVIDIA Corporation. All rights reserved.
//
// NOTICE TO USER:
//
// This software is subject to NVIDIA ownership rights under U.S.
// and international Copyright laws.
//
// This software and the information contained herein are PROPRIETARY and
// CONFIDENTIAL to NVIDIA and are being provided solely under the terms and
// conditions of an NVIDIA software license agreement.
// Otherwise, you have no rights to use or access this software in any manner.
//
// If not covered by the applicable NVIDIA software license agreement:
// NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
// PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY
// KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, AND
// FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY
// SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.
//
// U.S. Government End Users.
// This software is a "commercial item" as that term is defined at
// 48 C.F.R. 2.101 (OCT 1995), consisting of "commercial computer software" and
// "commercial computer software documentation" as such terms are used in
// 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government only as a
// commercial end item. Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1
// through 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the
// software with only those rights set forth herein.
//
// Any use of this software in individual and commercial software must include,
// in the user documentation and internal comments to the code,
// the above Disclaimer (as applicable) and U.S. Government End Users Notice.
////////////////////////////////////////////////////////////////////////////
************************************************************************************ ************************************************************************************
Recast & Detour Recast & Detour
************************************************************************************ ************************************************************************************
@ -96,7 +137,7 @@ Dear ImGui
// The MIT License (MIT) // The MIT License (MIT)
// //
// Copyright (c) 2014-2022 Omar Cornut // Copyright (c) 2014-2024 Omar Cornut
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@ -286,30 +327,22 @@ VDF Parser
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
************************************************************************************ ************************************************************************************
Nlohmann JSON RapidJSON
************************************************************************************ ************************************************************************************
// MIT License // Tencent is pleased to support the open source community by making RapidJSON available.
// //
// Copyright (c) 2013-2022 Niels Lohmann // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the MIT License (the "License"); you may not use this file except
// of this software and associated documentation files (the "Software"), to deal // in compliance with the License. You may obtain a copy of the License at
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in all // http://opensource.org/licenses/MIT
// copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software distributed
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // specific language governing permissions and limitations under the License.
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
************************************************************************************ ************************************************************************************
@ -340,6 +373,396 @@ Curl
// in this Software without prior written authorization of the copyright holder. // in this Software without prior written authorization of the copyright holder.
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
************************************************************************************
Mbed TLS & l8w8jwt
************************************************************************************
// Apache License
// Version 2.0, January 2004
// http://www.apache.org/licenses/
//
// TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
//
// 1. Definitions.
//
// "License" shall mean the terms and conditions for use, reproduction,
// and distribution as defined by Sections 1 through 9 of this document.
//
// "Licensor" shall mean the copyright owner or entity authorized by
// the copyright owner that is granting the License.
//
// "Legal Entity" shall mean the union of the acting entity and all
// other entities that control, are controlled by, or are under common
// control with that entity. For the purposes of this definition,
// "control" means (i) the power, direct or indirect, to cause the
// direction or management of such entity, whether by contract or
// otherwise, or (ii) ownership of fifty percent (50%) or more of the
// outstanding shares, or (iii) beneficial ownership of such entity.
//
// "You" (or "Your") shall mean an individual or Legal Entity
// exercising permissions granted by this License.
//
// "Source" form shall mean the preferred form for making modifications,
// including but not limited to software source code, documentation
// source, and configuration files.
//
// "Object" form shall mean any form resulting from mechanical
// transformation or translation of a Source form, including but
// not limited to compiled object code, generated documentation,
// and conversions to other media types.
//
// "Work" shall mean the work of authorship, whether in Source or
// Object form, made available under the License, as indicated by a
// copyright notice that is included in or attached to the work
// (an example is provided in the Appendix below).
//
// "Derivative Works" shall mean any work, whether in Source or Object
// form, that is based on (or derived from) the Work and for which the
// editorial revisions, annotations, elaborations, or other modifications
// represent, as a whole, an original work of authorship. For the purposes
// of this License, Derivative Works shall not include works that remain
// separable from, or merely link (or bind by name) to the interfaces of,
// the Work and Derivative Works thereof.
//
// "Contribution" shall mean any work of authorship, including
// the original version of the Work and any modifications or additions
// to that Work or Derivative Works thereof, that is intentionally
// submitted to Licensor for inclusion in the Work by the copyright owner
// or by an individual or Legal Entity authorized to submit on behalf of
// the copyright owner. For the purposes of this definition, "submitted"
// means any form of electronic, verbal, or written communication sent
// to the Licensor or its representatives, including but not limited to
// communication on electronic mailing lists, source code control systems,
// and issue tracking systems that are managed by, or on behalf of, the
// Licensor for the purpose of discussing and improving the Work, but
// excluding communication that is conspicuously marked or otherwise
// designated in writing by the copyright owner as "Not a Contribution."
//
// "Contributor" shall mean Licensor and any individual or Legal Entity
// on behalf of whom a Contribution has been received by Licensor and
// subsequently incorporated within the Work.
//
// 2. Grant of Copyright License. Subject to the terms and conditions of
// this License, each Contributor hereby grants to You a perpetual,
// worldwide, non-exclusive, no-charge, royalty-free, irrevocable
// copyright license to reproduce, prepare Derivative Works of,
// publicly display, publicly perform, sublicense, and distribute the
// Work and such Derivative Works in Source or Object form.
//
// 3. Grant of Patent License. Subject to the terms and conditions of
// this License, each Contributor hereby grants to You a perpetual,
// worldwide, non-exclusive, no-charge, royalty-free, irrevocable
// (except as stated in this section) patent license to make, have made,
// use, offer to sell, sell, import, and otherwise transfer the Work,
// where such license applies only to those patent claims licensable
// by such Contributor that are necessarily infringed by their
// Contribution(s) alone or by combination of their Contribution(s)
// with the Work to which such Contribution(s) was submitted. If You
// institute patent litigation against any entity (including a
// cross-claim or counterclaim in a lawsuit) alleging that the Work
// or a Contribution incorporated within the Work constitutes direct
// or contributory patent infringement, then any patent licenses
// granted to You under this License for that Work shall terminate
// as of the date such litigation is filed.
//
// 4. Redistribution. You may reproduce and distribute copies of the
// Work or Derivative Works thereof in any medium, with or without
// modifications, and in Source or Object form, provided that You
// meet the following conditions:
//
// (a) You must give any other recipients of the Work or
// Derivative Works a copy of this License; and
//
// (b) You must cause any modified files to carry prominent notices
// stating that You changed the files; and
//
// (c) You must retain, in the Source form of any Derivative Works
// that You distribute, all copyright, patent, trademark, and
// attribution notices from the Source form of the Work,
// excluding those notices that do not pertain to any part of
// the Derivative Works; and
//
// (d) If the Work includes a "NOTICE" text file as part of its
// distribution, then any Derivative Works that You distribute must
// include a readable copy of the attribution notices contained
// within such NOTICE file, excluding those notices that do not
// pertain to any part of the Derivative Works, in at least one
// of the following places: within a NOTICE text file distributed
// as part of the Derivative Works; within the Source form or
// documentation, if provided along with the Derivative Works; or,
// within a display generated by the Derivative Works, if and
// wherever such third-party notices normally appear. The contents
// of the NOTICE file are for informational purposes only and
// do not modify the License. You may add Your own attribution
// notices within Derivative Works that You distribute, alongside
// or as an addendum to the NOTICE text from the Work, provided
// that such additional attribution notices cannot be construed
// as modifying the License.
//
// You may add Your own copyright statement to Your modifications and
// may provide additional or different license terms and conditions
// for use, reproduction, or distribution of Your modifications, or
// for any such Derivative Works as a whole, provided Your use,
// reproduction, and distribution of the Work otherwise complies with
// the conditions stated in this License.
//
// 5. Submission of Contributions. Unless You explicitly state otherwise,
// any Contribution intentionally submitted for inclusion in the Work
// by You to the Licensor shall be under the terms and conditions of
// this License, without any additional terms or conditions.
// Notwithstanding the above, nothing herein shall supersede or modify
// the terms of any separate license agreement you may have executed
// with Licensor regarding such Contributions.
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor,
// except as required for reasonable and customary use in describing the
// origin of the Work and reproducing the content of the NOTICE file.
//
// 7. Disclaimer of Warranty. Unless required by applicable law or
// agreed to in writing, Licensor provides the Work (and each
// Contributor provides its Contributions) on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied, including, without limitation, any warranties or conditions
// of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
// PARTICULAR PURPOSE. You are solely responsible for determining the
// appropriateness of using or redistributing the Work and assume any
// risks associated with Your exercise of permissions under this License.
//
// 8. Limitation of Liability. In no event and under no legal theory,
// whether in tort (including negligence), contract, or otherwise,
// unless required by applicable law (such as deliberate and grossly
// negligent acts) or agreed to in writing, shall any Contributor be
// liable to You for damages, including any direct, indirect, special,
// incidental, or consequential damages of any character arising as a
// result of this License or out of the use or inability to use the
// Work (including but not limited to damages for loss of goodwill,
// work stoppage, computer failure or malfunction, or any and all
// other commercial damages or losses), even if such Contributor
// has been advised of the possibility of such damages.
//
// 9. Accepting Warranty or Additional Liability. While redistributing
// the Work or Derivative Works thereof, You may choose to offer,
// and charge a fee for, acceptance of support, warranty, indemnity,
// or other liability obligations and/or rights consistent with this
// License. However, in accepting such obligations, You may act only
// on Your own behalf and on Your sole responsibility, not on behalf
// of any other Contributor, and only if You agree to indemnify,
// defend, and hold each Contributor harmless for any liability
// incurred by, or claims asserted against, such Contributor by reason
// of your accepting any such warranty or additional liability.
//
// END OF TERMS AND CONDITIONS
//
// APPENDIX: How to apply the Apache License to your work.
//
// To apply the Apache License to your work, attach the following
// boilerplate notice, with the fields enclosed by brackets "[]"
// replaced with your own identifying information. (Don't include
// the brackets!) The text should be enclosed in the appropriate
// comment syntax for the file format. We also recommend that a
// file or class name and description of purpose be included on the
// same "printed page" as the copyright notice for easier
// identification within third-party archives.
//
// Copyright [yyyy] [name of copyright owner]
//
// 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.
////////////////////////////////////////////////////////////////////////////
************************************************************************************
DirtySDK (EA WebKit)
************************************************************************************
// Copyright (C) 1999-2007, 2009-2010, 2012-2013 Electronic Arts Inc
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////
************************************************************************************
EAThread (EA WebKit)
************************************************************************************
//--------------------------------------------------------------------------
// Copyright (C) 2017 Electronic Arts Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//--------------------------------------------------------------------------
//
// Additional licenses also apply to this software package as detailed below.
//
//--------------------------------------------------------------------------
// Copyright (c) 2015 Jeff Preshing
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgement in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//--------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////
************************************************************************************
EABase (EA WebKit)
************************************************************************************
// Copyright (C) 2002-2013 Electronic Arts Inc
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////
************************************************************************************
Zstandard
************************************************************************************
// BSD License
//
// For Zstandard software
//
// Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name Facebook, nor Meta, nor the names of its contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////
************************************************************************************
LZ4
************************************************************************************
// LZ4 Library
// Copyright (c) 2011-2020, Yann Collet
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////
************************************************************************************ ************************************************************************************
LZHAM LZHAM
************************************************************************************ ************************************************************************************
@ -365,46 +788,6 @@ LZHAM
// THE SOFTWARE. // THE SOFTWARE.
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
************************************************************************************
SHA256
************************************************************************************
// Updated to C++, zedwood.com 2012
// Based on Olivier Gay's version
// See Modified BSD License below:
//
// FIPS 180-2 SHA-224/256/384/512 implementation
// Issue date: 04/30/2005
// http://www.ouah.org/ogay/sha2/
//
// Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////
************************************************************************************ ************************************************************************************
CRC32 CRC32
************************************************************************************ ************************************************************************************

View File

@ -15,6 +15,7 @@ add_subdirectory( vstdlib )
add_subdirectory( vphysics ) add_subdirectory( vphysics )
add_subdirectory( ebisusdk ) add_subdirectory( ebisusdk )
add_subdirectory( codecs ) add_subdirectory( codecs )
add_subdirectory( geforce )
set( FOLDER_CONTEXT "Protocols" ) set( FOLDER_CONTEXT "Protocols" )
add_subdirectory( protoc ) add_subdirectory( protoc )
@ -23,31 +24,43 @@ set( FOLDER_CONTEXT "Respawn" )
add_subdirectory( rtech ) add_subdirectory( rtech )
set( FOLDER_CONTEXT "Thirdparty" ) set( FOLDER_CONTEXT "Thirdparty" )
add_subdirectory( thirdparty/cppnet )
add_subdirectory( thirdparty/curl )
add_subdirectory( thirdparty/sdl )
add_subdirectory( thirdparty/imgui )
add_subdirectory( thirdparty/spdlog ) add_subdirectory( thirdparty/spdlog )
set( FOLDER_CONTEXT "Thirdparty/Recast" )
add_subdirectory( thirdparty/recast )
add_subdirectory( thirdparty/detours )
set( FOLDER_CONTEXT "Thirdparty/Compression" )
add_subdirectory( thirdparty/lzham ) add_subdirectory( thirdparty/lzham )
add_subdirectory( thirdparty/fastlz ) add_subdirectory( thirdparty/fastlz )
add_subdirectory( thirdparty/bzip2 ) add_subdirectory( thirdparty/bzip2 )
add_subdirectory( thirdparty/zlib ) add_subdirectory( thirdparty/zlib )
add_subdirectory( thirdparty/lzma ) add_subdirectory( thirdparty/zstd )
add_subdirectory( thirdparty/lz4 )
add_subdirectory( thirdparty/zip ) add_subdirectory( thirdparty/zip )
set( FOLDER_CONTEXT "Thirdparty/Recast" ) set( FOLDER_CONTEXT "Thirdparty/Security" )
add_subdirectory( thirdparty/recast ) add_subdirectory( thirdparty/mbedtls )
add_subdirectory( thirdparty/jwt )
set( FOLDER_CONTEXT "Thirdparty/Microsoft" ) set( FOLDER_CONTEXT "Thirdparty/Multimedia" )
add_subdirectory( thirdparty/detours ) add_subdirectory( thirdparty/sdl )
add_subdirectory( thirdparty/imgui )
add_subdirectory( thirdparty/cppnet )
set( FOLDER_CONTEXT "Thirdparty/Google" ) set( FOLDER_CONTEXT "Thirdparty/Networking" )
add_subdirectory( thirdparty/protobuf ) add_subdirectory( thirdparty/protobuf )
add_subdirectory( thirdparty/curl )
add_subdirectory( thirdparty/dirtysdk )
set( FOLDER_CONTEXT "Thirdparty/Threading" )
add_subdirectory( thirdparty/ea/EAThread )
set( FOLDER_CONTEXT "Tools" ) set( FOLDER_CONTEXT "Tools" )
add_subdirectory( sdklauncher ) add_subdirectory( sdklauncher )
add_subdirectory( netconsole ) add_subdirectory( netconsole )
add_subdirectory( naveditor ) add_subdirectory( naveditor )
add_subdirectory( revpk )
set( FOLDER_CONTEXT "System" ) set( FOLDER_CONTEXT "System" )
add_subdirectory( networksystem ) add_subdirectory( networksystem )

View File

@ -14,7 +14,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CAppSystemGroup::StaticDestroy(CAppSystemGroup* pModAppSystemGroup) void CAppSystemGroup::StaticDestroy(CAppSystemGroup* pModAppSystemGroup)
{ {
CAppSystemGroup_Destroy(pModAppSystemGroup); CAppSystemGroup__Destroy(pModAppSystemGroup);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -25,11 +25,48 @@ CAppSystemGroup::AppSystemGroupStage_t CAppSystemGroup::GetCurrentStage() const
return m_nCurrentStage; return m_nCurrentStage;
} }
void VAppSystemGroup::Attach(void) const //-----------------------------------------------------------------------------
// Methods to find various global singleton systems
//-----------------------------------------------------------------------------
void* CAppSystemGroup::FindSystem(const char* pSystemName)
{ {
DetourAttach(&CAppSystemGroup_Destroy, &CAppSystemGroup::StaticDestroy); unsigned short i = m_SystemDict.Find(pSystemName);
if (i != m_SystemDict.InvalidIndex())
return m_Systems[m_SystemDict[i]];
// If it's not an interface we know about, it could be an older
// version of an interface, or maybe something implemented by
// one of the instantiated interfaces...
// QUESTION: What order should we iterate this in?
// It controls who wins if multiple ones implement the same interface
for (i = 0; i < m_Systems.Count(); ++i)
{
void* pInterface = m_Systems[i]->QueryInterface(pSystemName);
if (pInterface)
return pInterface;
}
int nExternalCount = m_NonAppSystemFactories.Count();
for (i = 0; i < nExternalCount; ++i)
{
void* pInterface = m_NonAppSystemFactories[i](pSystemName, NULL);
if (pInterface)
return pInterface;
}
if (m_pParentAppSystem)
{
void* pInterface = m_pParentAppSystem->FindSystem(pSystemName);
if (pInterface)
return pInterface;
}
// No dice..
return NULL;
} }
void VAppSystemGroup::Detach(void) const
void VAppSystemGroup::Detour(const bool bAttach) const
{ {
DetourDetach(&CAppSystemGroup_Destroy, &CAppSystemGroup::StaticDestroy); DetourSetup(&CAppSystemGroup__Destroy, &CAppSystemGroup::StaticDestroy, bAttach);
} }

View File

@ -51,14 +51,8 @@ macro( add_module MODULE_TYPE MODULE_NAME REUSE_PCH FOLDER_NAME WARNINGS_AS_ERRO
add_library( ${PROJECT_NAME} ) add_library( ${PROJECT_NAME} )
elseif( ${MODULE_TYPE} STREQUAL "shared_lib" ) elseif( ${MODULE_TYPE} STREQUAL "shared_lib" )
add_library( ${PROJECT_NAME} SHARED ) add_library( ${PROJECT_NAME} SHARED )
target_link_options( ${PROJECT_NAME} PRIVATE
"$<$<CONFIG:Release>:/LTCG>"
)
elseif( ${MODULE_TYPE} STREQUAL "exe" ) elseif( ${MODULE_TYPE} STREQUAL "exe" )
add_executable( ${PROJECT_NAME} ) add_executable( ${PROJECT_NAME} )
target_link_options( ${PROJECT_NAME} PRIVATE
"$<$<CONFIG:Release>:/LTCG>"
)
else() else()
message( FATAL_ERROR "Invalid module type: ${MODULE_TYPE}; expected 'lib', 'shared_lib', or 'exe'." ) message( FATAL_ERROR "Invalid module type: ${MODULE_TYPE}; expected 'lib', 'shared_lib', or 'exe'." )
endif() endif()
@ -69,7 +63,7 @@ macro( add_module MODULE_TYPE MODULE_NAME REUSE_PCH FOLDER_NAME WARNINGS_AS_ERRO
set_target_properties( ${MODULE_NAME} PROPERTIES FOLDER ${FOLDER_NAME} ) set_target_properties( ${MODULE_NAME} PROPERTIES FOLDER ${FOLDER_NAME} )
if( ${GLOBAL_WARNINGS_AS_ERRORS} ) if( ${OPTION_WARNINGS_AS_ERRORS} )
warnings_as_errors( ${PROJECT_NAME} ${WARNINGS_AS_ERRORS} ) warnings_as_errors( ${PROJECT_NAME} ${WARNINGS_AS_ERRORS} )
endif() endif()
@ -80,6 +74,7 @@ macro( add_module MODULE_TYPE MODULE_NAME REUSE_PCH FOLDER_NAME WARNINGS_AS_ERRO
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/Ot> $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/Ot>
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/GS-> $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/GS->
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/Gy> $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/Gy>
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/GT>
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/fp:fast> $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/fp:fast>
) )
endif() endif()
@ -101,12 +96,13 @@ macro( define_compiler_variables )
endmacro() endmacro()
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Apply whole program optimization for this target in release ( !slow! ) # Apply whole program optimization for this target in release and profile ( !slow! )
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
macro( whole_program_optimization ) macro( whole_program_optimization )
target_compile_options( ${PROJECT_NAME} PRIVATE if( ${OPTION_LTCG_MODE} STREQUAL "ON" )
$<$<CONFIG:Release>:/GL> set_property( TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
) set_property( TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION_PROFILE TRUE)
endif()
endmacro() endmacro()
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
@ -134,18 +130,25 @@ endmacro()
macro( thirdparty_suppress_warnings ) macro( thirdparty_suppress_warnings )
if( MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) if( MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
target_compile_options( ${PROJECT_NAME} PRIVATE target_compile_options( ${PROJECT_NAME} PRIVATE
/wd4057 # 'function': 'int *' differs in indirection to slightly different base types from 'unsigned int [4]'
/wd4100 # Unreferenced formal parameter. /wd4100 # Unreferenced formal parameter.
/wd4131 # Using old-style declarations /wd4131 # Using old-style declarations.
/wd4152 # Function/data pointer conversion in expression. /wd4152 # Function/data pointer conversion in expression.
/wd4200 # Zero-sized array in union; SDL2 uses this for compiler compatibility. /wd4200 # Zero-sized array in union; SDL2 uses this for compiler compatibility.
/wd4201 # Nameless struct/union. /wd4201 # Nameless struct/union.
/wd4204 # nonstandard extension used: non-constant aggregate initializer.
/wd4221 # nonstandard extension used: 'value': cannot be initialized using address of automatic variable 'symbol'
/wd4244 # Type conversion truncation; protobuf has many, but this appears intentional. /wd4244 # Type conversion truncation; protobuf has many, but this appears intentional.
/wd4245 # 'return': conversion signed/unsigned mismatch
/wd4267 # Type conversion truncation; protobuf has many, but this appears intentional. /wd4267 # Type conversion truncation; protobuf has many, but this appears intentional.
/wd4295 # Array is too small to include terminating null character.
/wd4307 # Integral constant overflow. /wd4307 # Integral constant overflow.
/wd4389 # Signed/unsigned mismatch. /wd4389 # Signed/unsigned mismatch.
/wd4456 # Declaration hides previous local declaration. /wd4456 # Declaration hides previous local declaration.
/wd4457 # Declaration hides function parameter. /wd4457 # Declaration hides function parameter.
/wd4505 # Unreferenced local function has been removed. /wd4505 # Unreferenced local function has been removed.
/wd4701 # potentially uninitialized local variable.
/wd4702 # Unreachable code.
) )
endif() endif()
warnings_as_errors( ${PROJECT_NAME} FALSE ) warnings_as_errors( ${PROJECT_NAME} FALSE )

View File

@ -20,27 +20,52 @@ macro( apply_project_settings )
) )
# Some thirdparty code have Warnings as Errors disabled; this option won't override those. # Some thirdparty code have Warnings as Errors disabled; this option won't override those.
option( GLOBAL_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" ON ) option( OPTION_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" ON )
option( ENABLE_LTCG "Enable link-time code generation (significantly increases compile times)" OFF )
set( GAMEDLL_OPTION "GAMEDLL_S3" CACHE STRING "Game DLL version" ) set( OPTION_LTCG_MODE "OFF" CACHE STRING "Enables link-time code generation (significantly increases compile times)" )
set_property( CACHE GAMEDLL_OPTION PROPERTY STRINGS set_property( CACHE OPTION_LTCG_MODE PROPERTY STRINGS
"GAMEDLL_S0" "OFF"
"GAMEDLL_S1" "ON" # Only on projects that specified LTCG
"GAMEDLL_S2" "ALL" # All projects, whether or not LTCG was specified
"GAMEDLL_S3"
) )
option( OPTION_CERTAIN "This build is certain; debug statements (such as DevMsg(...)) will NOT be compiled" OFF )
option( OPTION_RETAIL "This build is retail; enable this among with 'OPTION_CERTAIN' to form a release build" OFF )
# Set common defines # Set common defines
add_compile_definitions( add_compile_definitions(
"_CRT_SECURE_NO_WARNINGS" "_CRT_SECURE_NO_WARNINGS"
"SPDLOG_COMPILED_LIB" "SPDLOG_COMPILED_LIB"
"SPDLOG_NO_EXCEPTIONS" "SPDLOG_NO_EXCEPTIONS"
"CURL_STATICLIB" "CURL_STATICLIB"
"PLATFORM_64BITS" # Target is 64bits only.
"${GAMEDLL_OPTION}" # Must be explicitly defined to toggle SIMD optimizations for RapidJSON.
# Don't set this to anything higher than SSE2, as the game supports from
# SSE3 and higher, and the next level of optimizations in RapidJSON is SSE4.2.
"RAPIDJSON_SSE2"
# Use iterative parsing to protect against stack overflows in rare cases; see:
# https://rapidjson.org/md_doc_features.html
# https://github.com/Tencent/rapidjson/issues/1227
# https://github.com/Tencent/rapidjson/issues/2260
"RAPIDJSON_PARSE_DEFAULT_FLAGS=kParseIterativeFlag|kParseValidateEncodingFlag"
# Target is 64bits only.
"PLATFORM_64BITS"
) )
if( ${OPTION_CERTAIN} )
add_compile_definitions(
"_CERT"
)
endif()
if( ${OPTION_RETAIL} )
add_compile_definitions(
"_RETAIL"
)
endif()
# Set settings for Debug configuration # Set settings for Debug configuration
add_compile_options( add_compile_options(
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Debug>>:/MTd> $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Debug>>:/MTd>
@ -61,11 +86,9 @@ macro( apply_project_settings )
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/EHsc> $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/EHsc>
) )
if( ${ENABLE_LTCG} ) if( ${OPTION_LTCG_MODE} STREQUAL "ALL" )
add_compile_options( set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Profile>>:/GL> set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_PROFILE ON)
$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Release>>:/GL>
)
endif() endif()
set( CMAKE_EXE_LINKER_FLAGS_RELEASE set( CMAKE_EXE_LINKER_FLAGS_RELEASE
@ -81,9 +104,9 @@ macro( apply_project_settings )
include_directories( include_directories(
"${ENGINE_SOURCE_DIR}/" "${ENGINE_SOURCE_DIR}/"
"${ENGINE_SOURCE_DIR}/public/" "${ENGINE_SOURCE_DIR}/public/"
"${ENGINE_SOURCE_DIR}/thirdparty/" "${THIRDPARTY_SOURCE_DIR}/"
"${ENGINE_SOURCE_DIR}/thirdparty/imgui/" "${THIRDPARTY_SOURCE_DIR}/imgui/"
"${ENGINE_SOURCE_DIR}/thirdparty/recast/" "${THIRDPARTY_SOURCE_DIR}/recast/"
) )
endmacro() endmacro()

View File

@ -1,7 +1,11 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "miles_impl.h" #include "miles_impl.h"
#include "tier0/fasttimer.h" #include "tier0/fasttimer.h"
#include "tier0/commandline.h"
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "filesystem/filesystem.h"
static ConVar miles_debug("miles_debug", "0", FCVAR_RELEASE, "Enables debug prints for the Miles Sound System", "1 = print; 0 (zero) = no print");
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: logs debug output emitted from the Miles Sound System // Purpose: logs debug output emitted from the Miles Sound System
@ -10,7 +14,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void AIL_LogFunc(int64_t nLogLevel, const char* pszMessage) void AIL_LogFunc(int64_t nLogLevel, const char* pszMessage)
{ {
DevMsg(eDLL_T::AUDIO, "%s\n", pszMessage); Msg(eDLL_T::AUDIO, "%s\n", pszMessage);
v_AIL_LogFunc(nLogLevel, pszMessage); v_AIL_LogFunc(nLogLevel, pszMessage);
} }
@ -22,48 +26,93 @@ bool Miles_Initialize()
{ {
const char* pszLanguage = miles_language->GetString(); const char* pszLanguage = miles_language->GetString();
if (!pszLanguage[0]) if (!pszLanguage[0])
{
pszLanguage = MILES_DEFAULT_LANGUAGE; pszLanguage = MILES_DEFAULT_LANGUAGE;
const bool isEnglishLanguage = _stricmp(pszLanguage, "english") == 0;
if (!isEnglishLanguage)
{
const bool useShipSound = !CommandLine()->FindParm("-devsound") || CommandLine()->FindParm("-shipsound");
const std::string baseStreamFilePath = Format("%s/general_%s.mstr", useShipSound ? "audio/ship" : "audio/dev", pszLanguage);
// if the requested language for miles does not have a MSTR file present, throw a non-fatal error and force english as a fallback
// if we are loading english and the file is still not found, we can let it hit the regular engine error, since that is not recoverable
if (!FileSystem()->FileExists(baseStreamFilePath.c_str()))
{
Error(eDLL_T::AUDIO, NO_ERROR, "%s: attempted to load language '%s' but the required streaming source file (%s) was not found. falling back to english...\n", __FUNCTION__, pszLanguage, baseStreamFilePath.c_str());
pszLanguage = MILES_DEFAULT_LANGUAGE;
miles_language->SetValue(pszLanguage);
}
} }
DevMsg(eDLL_T::AUDIO, "%s: initializing MSS with language: '%s'\n", __FUNCTION__, pszLanguage); Msg(eDLL_T::AUDIO, "%s: initializing MSS with language: '%s'\n", __FUNCTION__, pszLanguage);
CFastTimer initTimer; CFastTimer initTimer;
initTimer.Start(); initTimer.Start();
bool bResult = v_Miles_Initialize(); bool bResult = v_Miles_Initialize();
initTimer.End(); initTimer.End();
DevMsg(eDLL_T::AUDIO, "%s: %s ('%f' seconds)\n", __FUNCTION__, bResult ? "success" : "failure", initTimer.GetDuration().GetSeconds()); Msg(eDLL_T::AUDIO, "%s: %s ('%f' seconds)\n", __FUNCTION__, bResult ? "success" : "failure", initTimer.GetDuration().GetSeconds());
return bResult; return bResult;
} }
void MilesQueueEventRun(Miles::Queue* queue, const char* eventName) void MilesQueueEventRun(Miles::Queue* queue, const char* eventName)
{ {
if(miles_debug->GetBool()) if(miles_debug.GetBool())
DevMsg(eDLL_T::AUDIO, "%s: running event: '%s'\n", __FUNCTION__, eventName); Msg(eDLL_T::AUDIO, "%s: running event: '%s'\n", __FUNCTION__, eventName);
v_MilesQueueEventRun(queue, eventName); v_MilesQueueEventRun(queue, eventName);
} }
void MilesBankPatch(Miles::Bank* bank, char* streamPatch, char* localizedStreamPatch) void MilesBankPatch(Miles::Bank* bank, char* streamPatch, char* localizedStreamPatch)
{ {
// TODO [REXX]: add print for patch loading when Miles::Bank struct is mapped out a bit better with file name if (miles_debug.GetBool())
{
Msg(eDLL_T::AUDIO,
"%s: patching bank \"%s\". stream patches: \"%s\", \"%s\"\n",
__FUNCTION__,
bank->GetBankName(),
V_UnqualifiedFileName(streamPatch), V_UnqualifiedFileName(localizedStreamPatch)
);
}
const Miles::BankHeader_t* header = bank->GetHeader();
if (header->bankIndex >= header->project->bankCount)
Error(eDLL_T::AUDIO, EXIT_FAILURE,
"%s: Attempted to patch bank '%s' that identified itself as bank idx %i.\nProject expects a highest index of %i\n",
__FUNCTION__,
bank->GetBankName(),
header->bankIndex,
header->project->bankCount - 1
);
v_MilesBankPatch(bank, streamPatch, localizedStreamPatch); v_MilesBankPatch(bank, streamPatch, localizedStreamPatch);
} }
/////////////////////////////////////////////////////////////////////////////// void CSOM_AddEventToQueue(const char* eventName)
void MilesCore::Attach() const
{ {
DetourAttach(&v_AIL_LogFunc, &AIL_LogFunc); if (miles_debug.GetBool())
DetourAttach(&v_Miles_Initialize, &Miles_Initialize); Msg(eDLL_T::AUDIO, "%s: queuing audio event '%s'\n", __FUNCTION__, eventName);
DetourAttach(&v_MilesQueueEventRun, &MilesQueueEventRun);
DetourAttach(&v_MilesBankPatch, &MilesBankPatch);
}
void MilesCore::Detach() const v_CSOM_AddEventToQueue(eventName);
if (g_milesGlobals->queuedEventHash == 1)
Warning(eDLL_T::AUDIO, "%s: failed to add event to queue; invalid event name '%s'\n", __FUNCTION__, eventName);
if (g_milesGlobals->queuedEventHash == 2)
Warning(eDLL_T::AUDIO, "%s: failed to add event to queue; event '%s' not found.\n", __FUNCTION__, eventName);
};
///////////////////////////////////////////////////////////////////////////////
void MilesCore::Detour(const bool bAttach) const
{ {
DetourDetach(&v_AIL_LogFunc, &AIL_LogFunc); DetourSetup(&v_AIL_LogFunc, &AIL_LogFunc, bAttach);
DetourDetach(&v_Miles_Initialize, &Miles_Initialize); DetourSetup(&v_Miles_Initialize, &Miles_Initialize, bAttach);
DetourDetach(&v_MilesQueueEventRun, &MilesQueueEventRun); DetourSetup(&v_MilesQueueEventRun, &MilesQueueEventRun, bAttach);
DetourDetach(&v_MilesBankPatch, &MilesBankPatch); DetourSetup(&v_MilesBankPatch, &MilesBankPatch, bAttach);
} DetourSetup(&v_CSOM_AddEventToQueue, &CSOM_AddEventToQueue, bAttach);
}

View File

@ -2,48 +2,76 @@
#include "miles_types.h" #include "miles_types.h"
/* ==== WASAPI THREAD SERVICE =========================================================================================================================================== */ /* ==== WASAPI THREAD SERVICE =========================================================================================================================================== */
inline CMemory p_AIL_LogFunc;
inline void(*v_AIL_LogFunc)(int64_t nLogLevel, const char* pszMessage); inline void(*v_AIL_LogFunc)(int64_t nLogLevel, const char* pszMessage);
inline CMemory p_Miles_Initialize;
inline bool(*v_Miles_Initialize)(); inline bool(*v_Miles_Initialize)();
inline CMemory p_MilesQueueEventRun;
inline void(*v_MilesQueueEventRun)(Miles::Queue*, const char*); inline void(*v_MilesQueueEventRun)(Miles::Queue*, const char*);
inline CMemory p_MilesBankPatch;
inline void(*v_MilesBankPatch)(Miles::Bank*, char*, char*); inline void(*v_MilesBankPatch)(Miles::Bank*, char*, char*);
inline void(*v_CSOM_AddEventToQueue)(const char* eventName);
struct MilesBankList_t
{
char banks[64][16];
int bankCount;
};
struct MilesGlobalState_t
{
char gap0[24];
bool mismatchedBuildTag;
char gap19[63];
uintptr_t queuedEventHash;
char gap60[4];
Vector3D queuedSoundPosition;
char gap70[24];
float soundMasterVolume;
char gap8c[28];
void* samplesXlogType;
char gapB0[8];
void* dumpXlogType;
char gapC0[48];
void* driver;
void* queue;
char gap100[40];
MilesBankList_t bankList;
char gap52c[4];
void* loadedBanks[16];
char gap5b0[290448];
HANDLE milesInitializedEvent;
HANDLE milesThread;
char gap47450[272];
char milesOutputBuffer[1024];
char unk[96];
};
inline MilesGlobalState_t* g_milesGlobals;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class MilesCore : public IDetour class MilesCore : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("AIL_LogFunc", p_AIL_LogFunc.GetPtr()); LogFunAdr("AIL_LogFunc", v_AIL_LogFunc);
LogFunAdr("Miles_Initialize", p_Miles_Initialize.GetPtr()); LogFunAdr("Miles_Initialize", v_Miles_Initialize);
LogFunAdr("MilesQueueEventRun", v_MilesQueueEventRun);
LogFunAdr("MilesBankPatch", v_MilesBankPatch);
LogFunAdr("CSOM_AddEventToQueue", v_CSOM_AddEventToQueue);
LogVarAdr("g_milesGlobals", g_milesGlobals);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_AIL_LogFunc = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B DA 48 8D 15 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B DA 48 8D 15 ?? ?? ?? ??").GetPtr(v_AIL_LogFunc);
v_AIL_LogFunc = p_AIL_LogFunc.RCast<void(*)(int64_t, const char*)>(); g_GameDll.FindPatternSIMD("0F B6 11 4C 8B C1").GetPtr(v_CSOM_AddEventToQueue);
CMemory milesInitializeFunc = g_GameDll.FindPatternSIMD("40 53 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ??");
milesInitializeFunc.GetPtr(v_Miles_Initialize);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2) g_milesGlobals = milesInitializeFunc.FindPatternSelf("48 8D", CMemory::Direction::DOWN, 0x50).ResolveRelativeAddressSelf(0x3, 0x7).RCast<MilesGlobalState_t*>();
p_Miles_Initialize = g_GameDll.FindPatternSIMD("40 53 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ??");
#else
p_Miles_Initialize = g_GameDll.FindPatternSIMD("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ??");
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2)
v_Miles_Initialize = p_Miles_Initialize.RCast<bool(*)()>();
p_MilesQueueEventRun = g_RadAudioSystemDll.GetExportedSymbol("MilesQueueEventRun");
v_MilesQueueEventRun = p_MilesQueueEventRun.RCast<void(*)(Miles::Queue*, const char*)>();
p_MilesBankPatch = g_RadAudioSystemDll.GetExportedSymbol("MilesBankPatch");
v_MilesBankPatch = p_MilesBankPatch.RCast<void(*)(Miles::Bank*, char*, char*)>();
g_RadAudioSystemDll.GetExportedSymbol("MilesQueueEventRun").GetPtr(v_MilesQueueEventRun);
g_RadAudioSystemDll.GetExportedSymbol("MilesBankPatch").GetPtr(v_MilesBankPatch);
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -4,6 +4,9 @@ constexpr char MILES_DEFAULT_LANGUAGE[] = "english";
namespace Miles namespace Miles
{ {
constexpr int TEMPLATEID_FLAG_SOURCE = 0x40000000;
struct Queue struct Queue
{ {
char gap0[0x8]; char gap0[0x8];
@ -11,8 +14,107 @@ namespace Miles
char gap10[0x20]; char gap10[0x20];
}; };
struct BankHeader_t;
struct Source_t
{
BankHeader_t* bank; // reserved on disk - written at runtime
char gap8[80];
};
struct Event_t
{
int nameOffset;
int unkOffset; // offset into BankHeader_t::unk_68 data - some sort of event metadata?
};
// internal project data structure
struct IntProjectData_t
{
char gap0[0xCF0];
int bankCount;
BankHeader_t** loadedBanks;
};
struct BankHeader_t
{
int magic; // 'CBNK'
int version; // 32
uint32_t dataSize;
int bankMagic; // 'BANK'
const char* bankName;
void* unk_18;
IntProjectData_t* project;
void* unk_28;
void* unk_30;
void* unk_38;
void* unk_40; // used to index into both sources and localised sources
Source_t* sources;
Source_t* localizedSources;
void* unk_58;
Event_t* events;
void* unk_68;
const char* stringTable;
void* unk_78;
void* unk_80;
void* unk_88;
uint8_t bankIndex;
// 3 byte padding
uint32_t localizedSourceCount;
uint32_t sourceCount;
uint32_t patchCount;
uint32_t eventCount;
uint32_t count_A4;
uint32_t count_A8;
uint32_t count_AC;
uint32_t buildTag;
uint32_t unk_B4;
uint32_t someDataSize;
const char* GetBankName() const
{
return bankName;
}
};
static_assert(offsetof(BankHeader_t, project) == 0x20);
static_assert(offsetof(BankHeader_t, stringTable) == 0x70);
static_assert(offsetof(BankHeader_t, unk_B4) == 0xB4);
struct Bank struct Bank
{ {
// TODO [REXX]: map out this struct and its internal counterpart void* internalData;
void* unk_8;
char* fileData;
int unk_18;
char gap_1c[4];
const Miles::BankHeader_t* GetHeader() const
{
return reinterpret_cast<Miles::BankHeader_t*>(fileData);
}
const char* GetBankName() const
{
return GetHeader()->GetBankName();
}
}; };
static_assert(sizeof(Bank) == 0x20);
} }

View File

@ -8,7 +8,7 @@ class VRadShal : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("WASAPI_GetAudioDevice", p_WASAPI_GetAudioDevice.GetPtr()); LogFunAdr("WASAPI_GetAudioDevice", (void*)p_WASAPI_GetAudioDevice.GetPtr());
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
@ -17,7 +17,6 @@ class VRadShal : public IDetour
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -20,12 +20,7 @@ void* BinkOpen(HANDLE hBinkFile, UINT32 nFlags)
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void BinkCore::Attach() const void BinkCore::Detour(const bool bAttach) const
{ {
DetourAttach(&v_BinkOpen, &BinkOpen); DetourSetup(&v_BinkOpen, &BinkOpen, bAttach);
} }
void BinkCore::Detach() const
{
DetourDetach(&v_BinkOpen, &BinkOpen);
}

View File

@ -1,12 +1,7 @@
#pragma once #pragma once
inline CMemory p_BinkOpen;
inline void*(*v_BinkOpen)(HANDLE hBinkFile, UINT32 nFlags); inline void*(*v_BinkOpen)(HANDLE hBinkFile, UINT32 nFlags);
inline CMemory p_BinkClose;
inline void(*v_BinkClose)(HANDLE hBinkFile); inline void(*v_BinkClose)(HANDLE hBinkFile);
inline CMemory p_BinkGetError;
inline const char*(*v_BinkGetError)(void); inline const char*(*v_BinkGetError)(void);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -14,23 +9,18 @@ class BinkCore : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("BinkOpen", p_BinkOpen.GetPtr()); LogFunAdr("BinkOpen", v_BinkOpen);
LogFunAdr("BinkClose", p_BinkClose.GetPtr()); LogFunAdr("BinkClose", v_BinkClose);
LogFunAdr("BinkGetError", p_BinkGetError.GetPtr()); LogFunAdr("BinkGetError", v_BinkGetError);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_BinkOpen = g_RadVideoToolsDll.GetExportedSymbol("BinkOpen"); g_RadVideoToolsDll.GetExportedSymbol("BinkOpen").GetPtr(v_BinkOpen);
v_BinkOpen = p_BinkOpen.RCast<void*(*)(HANDLE, UINT32)>(); g_RadVideoToolsDll.GetExportedSymbol("BinkClose").GetPtr(v_BinkClose);
p_BinkClose = g_RadVideoToolsDll.GetExportedSymbol("BinkClose"); g_RadVideoToolsDll.GetExportedSymbol("BinkGetError").GetPtr(v_BinkGetError);
v_BinkClose = p_BinkClose.RCast<void(*)(HANDLE)>();
p_BinkGetError = g_RadVideoToolsDll.GetExportedSymbol("BinkGetError");
v_BinkGetError = p_BinkGetError.RCast<const char* (*)(void)>();
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -1,102 +1,52 @@
#pragma once #pragma once
inline CMemory p_SetupGamemode; inline bool(*v_SetupGamemode)(const char* pszPlayList);
inline bool(*SetupGamemode)(const char* pszPlayList);
/* ==== CONCOMMANDCALLBACK ============================================================================================================================================== */ /* ==== CONCOMMANDCALLBACK ============================================================================================================================================== */
inline CMemory p_DownloadPlaylists_f; inline void(*v__Cmd_Exec_f)(const CCommand& args);
inline void(*_DownloadPlaylists_f)(void);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void MP_GameMode_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValue); void MP_GameMode_Changed_f(IConVar* pConVar, const char* pOldString);
void MP_HostName_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValue);
#ifndef DEDICATED
void ToggleConsole_f(const CCommand& args);
void ToggleBrowser_f(const CCommand& args);
#endif // !DEDICATED
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
void Host_Kick_f(const CCommand& args);
void Host_KickID_f(const CCommand& args);
void Host_Ban_f(const CCommand& args);
void Host_BanID_f(const CCommand& args);
void Host_Unban_f(const CCommand& args);
void Host_ReloadBanList_f(const CCommand& args);
void Host_ReloadPlaylists_f(const CCommand& args);
void Host_Changelevel_f(const CCommand& args); void Host_Changelevel_f(const CCommand& args);
void Detour_HotSwap_f(const CCommand& args);
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
void Pak_ListPaks_f(const CCommand& args);
void Pak_ListTypes_f(const CCommand& args);
void Pak_RequestUnload_f(const CCommand& args);
void Pak_RequestLoad_f(const CCommand& args);
void Pak_Swap_f(const CCommand& args);
void RTech_StringToGUID_f(const CCommand& args);
void RTech_Decompress_f(const CCommand& args);
void VPK_Pack_f(const CCommand& args); void VPK_Pack_f(const CCommand& args);
void VPK_Unpack_f(const CCommand& args); void VPK_Unpack_f(const CCommand& args);
void VPK_Mount_f(const CCommand& args); void VPK_Mount_f(const CCommand& args);
void VPK_Unmount_f(const CCommand& args); void VPK_Unmount_f(const CCommand& args);
void NET_SetKey_f(const CCommand& args); void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString);
void NET_GenerateKey_f(const CCommand& args);
void NET_UseRandomKeyChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue);
void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue);
void SIG_GetAdr_f(const CCommand& args);
void CON_Help_f(const CCommand& args);
#ifndef DEDICATED #ifndef DEDICATED
void CON_LogHistory_f(const CCommand& args);
void CON_RemoveLine_f(const CCommand& args);
void CON_ClearLines_f(const CCommand& args);
void CON_ClearHistory_f(const CCommand& args);
void RCON_CmdQuery_f(const CCommand& args); void GFX_NVN_Changed_f(IConVar* pConVar, const char* pOldString);
void RCON_Disconnect_f(const CCommand& args);
void RCON_InputOnlyChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue);
#endif // !DEDICATED #endif // !DEDICATED
void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); void LanguageChanged_f(IConVar* pConVar, const char* pOldString);
#ifndef CLIENT_DLL
void SV_LanguageChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue);
void RCON_WhiteListAddresChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue);
void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue);
void SQVM_ServerScript_f(const CCommand& args);
#endif // !CLIENT_DLL
#ifndef DEDICATED #ifndef DEDICATED
void SQVM_ClientScript_f(const CCommand& args);
void SQVM_UIScript_f(const CCommand& args);
void Mat_CrossHair_f(const CCommand& args); void Mat_CrossHair_f(const CCommand& args);
void Line_f(const CCommand& args); void Line_f(const CCommand& args);
void Sphere_f(const CCommand& args); void Sphere_f(const CCommand& args);
void Capsule_f(const CCommand& args); void Capsule_f(const CCommand& args);
#endif // !DEDICATED #endif // !DEDICATED
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1)
void BHit_f(const CCommand& args); void BHit_f(const CCommand& args);
#endif // !GAMEDLL_S0 && !GAMEDLL_S1
void CVHelp_f(const CCommand& args); void CVHelp_f(const CCommand& args);
void CVList_f(const CCommand& args); void CVList_f(const CCommand& args);
void CVDiff_f(const CCommand& args); void CVDiff_f(const CCommand& args);
void CVFlag_f(const CCommand& args); void CVFlag_f(const CCommand& args);
#ifndef CLIENT_DLL
void CC_CreateFakePlayer_f(const CCommand& args);
#endif // !CLIENT_DLL
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VCallback : public IDetour class VCallback : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("SetupGamemode", p_SetupGamemode.GetPtr()); LogFunAdr("SetupGamemode", v_SetupGamemode);
LogFunAdr("DownloadPlaylist_f", p_DownloadPlaylists_f.GetPtr()); LogFunAdr("Cmd_Exec_f", v__Cmd_Exec_f);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_SetupGamemode = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B D9 48 C7 C0 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B D9 48 C7 C0 ?? ?? ?? ??").GetPtr(v_SetupGamemode);
p_DownloadPlaylists_f = g_GameDll.FindPatternSIMD("33 C9 C6 05 ?? ?? ?? ?? ?? E9 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("40 55 53 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9").GetPtr(v__Cmd_Exec_f);
SetupGamemode = p_SetupGamemode.RCast<bool(*)(const char*)>(); /*40 53 48 83 EC 20 48 8B D9 48 C7 C0 ?? ?? ?? ??*/
_DownloadPlaylists_f = p_DownloadPlaylists_f.RCast<void(*)(void)>(); /*33 C9 C6 05 ?? ?? ?? ?? ?? E9 ?? ?? ?? ??*/
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -27,7 +27,7 @@ int _Host_Map_f_CompletionFunc(char const* cmdname, char const* partial, char co
substring = (char*)partial + strlen(cmdname); substring = (char*)partial + strlen(cmdname);
} }
const int mapcount = (int)g_InstalledMaps.size(); const int mapcount = g_InstalledMaps.Count();
const int longest = COMMAND_COMPLETION_ITEM_LENGTH; const int longest = COMMAND_COMPLETION_ITEM_LENGTH;
const int count = MIN(mapcount, COMMAND_COMPLETION_MAXITEMS); const int count = MIN(mapcount, COMMAND_COMPLETION_MAXITEMS);
@ -36,9 +36,9 @@ int _Host_Map_f_CompletionFunc(char const* cmdname, char const* partial, char co
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
if (strstr(g_InstalledMaps[i].c_str(), substring)) if (strstr(g_InstalledMaps[i].String(), substring))
{ {
strncpy(commands[filtered_count], g_InstalledMaps[i].c_str(), longest); strncpy(commands[filtered_count], g_InstalledMaps[i].String(), longest);
char old[COMMAND_COMPLETION_ITEM_LENGTH]; char old[COMMAND_COMPLETION_ITEM_LENGTH];
strncpy(old, commands[filtered_count], sizeof(old)); strncpy(old, commands[filtered_count], sizeof(old));
@ -170,6 +170,18 @@ int RTech_PakUnload_f_CompletionFunc(char const* partial, char commands[COMMAND_
return _Host_Pak_f_CompletionFunc(&s_PakUnloadAutoFileList, partial, commands); return _Host_Pak_f_CompletionFunc(&s_PakUnloadAutoFileList, partial, commands);
} }
static CBaseAutoCompleteFileList s_PakCompress("pak_compress", "paks/Win64_override", "rpak");
//-----------------------------------------------------------------------------
// Purpose:
// Input : *partial -
// **commands -
// Output : int
//-----------------------------------------------------------------------------
int RTech_PakCompress_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])
{
return _Host_Pak_f_CompletionFunc(&s_PakCompress, partial, commands);
}
static CBaseAutoCompleteFileList s_PakDecompress("pak_decompress", "paks/Win64", "rpak"); static CBaseAutoCompleteFileList s_PakDecompress("pak_decompress", "paks/Win64", "rpak");
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: // Purpose:

View File

@ -11,10 +11,10 @@ int Game_Give_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLE
int RTech_PakLoad_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]); int RTech_PakLoad_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
int RTech_PakUnload_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]); int RTech_PakUnload_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
int RTech_PakCompress_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
int RTech_PakDecompress_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]); int RTech_PakDecompress_f_CompletionFunc(char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
inline CMemory p_CBaseAutoCompleteFileList_AutoCompletionFunc; inline int(*CBaseAutoCompleteFileList__AutoCompletionFunc)
inline int(*v_CBaseAutoCompleteFileList_AutoCompletionFunc)
(CBaseAutoCompleteFileList* thisp, const char* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]); (CBaseAutoCompleteFileList* thisp, const char* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -22,21 +22,14 @@ class VCompletion : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CBaseAutoCompleteFileList::AutoCompletionFunc", p_CBaseAutoCompleteFileList_AutoCompletionFunc.GetPtr()); LogFunAdr("CBaseAutoCompleteFileList::AutoCompletionFunc", CBaseAutoCompleteFileList__AutoCompletionFunc);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 8B C4 4C 89 40 18 55 41 54").GetPtr(CBaseAutoCompleteFileList__AutoCompletionFunc);
p_CBaseAutoCompleteFileList_AutoCompletionFunc = g_GameDll.FindPatternSIMD("40 55 53 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 39");
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_CBaseAutoCompleteFileList_AutoCompletionFunc = g_GameDll.FindPatternSIMD("48 8B C4 4C 89 40 18 55 41 54");
#endif
v_CBaseAutoCompleteFileList_AutoCompletionFunc = p_CBaseAutoCompleteFileList_AutoCompletionFunc.RCast<int(*)(
CBaseAutoCompleteFileList*, const char*, char[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])>();
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -10,9 +10,13 @@
#include "callback.h" #include "callback.h"
#include "global.h" #include "global.h"
ConVar curl_debug("curl_debug", "0", FCVAR_DEVELOPMENTONLY, "Determines whether or not to enable curl debug logging.", "1 = curl logs; 0 (zero) = no logs");
ConVar curl_timeout("curl_timeout", "15", FCVAR_DEVELOPMENTONLY, "Maximum time in seconds a curl transfer operation could take.");
ConVar ssl_verify_peer("ssl_verify_peer", "1", FCVAR_DEVELOPMENTONLY, "Verify the authenticity of the peer's SSL certificate.", "1 = curl verifies; 0 (zero) = no verification");
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// ENGINE | // ENGINE |
ConVar* sdk_fixedframe_tickinterval = nullptr;
ConVar* single_frame_shutdown_for_reload = nullptr; ConVar* single_frame_shutdown_for_reload = nullptr;
ConVar* old_gather_props = nullptr; ConVar* old_gather_props = nullptr;
@ -21,12 +25,14 @@ ConVar* debug_draw_box_depth_test = nullptr;
ConVar* developer = nullptr; ConVar* developer = nullptr;
ConVar* fps_max = nullptr; ConVar* fps_max = nullptr;
ConVar* fps_max_vsync = nullptr;
// Taken from S15: #ifndef DEDICATED
ConVar* usercmd_frametime_max = nullptr; ConVar* in_syncRT = nullptr;
ConVar* usercmd_frametime_min = nullptr; #endif // !DEDICATED
ConVar* usercmd_dualwield_enable = nullptr; ConVar* base_tickinterval_sp = nullptr;
ConVar* base_tickinterval_mp = nullptr;
ConVar* staticProp_no_fade_scalar = nullptr; ConVar* staticProp_no_fade_scalar = nullptr;
ConVar* staticProp_gather_size_weight = nullptr; ConVar* staticProp_gather_size_weight = nullptr;
@ -36,7 +42,6 @@ ConVar* model_defaultFadeDistMin = nullptr;
ConVar* ip_cvar = nullptr; ConVar* ip_cvar = nullptr;
ConVar* hostname = nullptr; ConVar* hostname = nullptr;
ConVar* hostdesc = nullptr;
ConVar* hostip = nullptr; ConVar* hostip = nullptr;
ConVar* hostport = nullptr; ConVar* hostport = nullptr;
@ -45,17 +50,6 @@ ConVar* host_timescale = nullptr;
ConVar* mp_gamemode = nullptr; ConVar* mp_gamemode = nullptr;
ConVar* rcon_address = nullptr;
ConVar* rcon_password = nullptr;
ConVar* r_debug_overlay_nodecay = nullptr;
ConVar* r_debug_overlay_invisible = nullptr;
ConVar* r_debug_overlay_wireframe = nullptr;
ConVar* r_debug_draw_depth_test = nullptr;
ConVar* r_drawWorldMeshes = nullptr;
ConVar* r_drawWorldMeshesDepthOnly = nullptr;
ConVar* r_drawWorldMeshesDepthAtTheEnd = nullptr;
#ifndef DEDICATED #ifndef DEDICATED
ConVar* r_visualizetraces = nullptr; ConVar* r_visualizetraces = nullptr;
ConVar* r_visualizetraces_duration = nullptr; ConVar* r_visualizetraces_duration = nullptr;
@ -63,399 +57,75 @@ ConVar* r_visualizetraces_duration = nullptr;
ConVar* stream_overlay = nullptr; ConVar* stream_overlay = nullptr;
ConVar* stream_overlay_mode = nullptr; ConVar* stream_overlay_mode = nullptr;
//-----------------------------------------------------------------------------
// SHARED | ConVar* eula_version = nullptr;
ConVar* modsystem_enable = nullptr; ConVar* eula_version_accepted = nullptr;
ConVar* modsystem_debug = nullptr;
ConVar* language_cvar = nullptr;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// SERVER | // SERVER |
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
ConVar* ai_ainDumpOnLoad = nullptr;
ConVar* ai_ainDebugConnect = nullptr;
ConVar* ai_script_nodes_draw = nullptr; ConVar* ai_script_nodes_draw = nullptr;
ConVar* ai_script_nodes_draw_range = nullptr;
ConVar* ai_script_nodes_draw_nearest = nullptr;
ConVar* navmesh_always_reachable = nullptr;
ConVar* navmesh_debug_type = nullptr;
ConVar* navmesh_debug_tile_range = nullptr;
ConVar* navmesh_debug_camera_range = nullptr;
#ifndef DEDICATED
ConVar* navmesh_draw_bvtree = nullptr;
ConVar* navmesh_draw_portal = nullptr;
ConVar* navmesh_draw_polys = nullptr;
ConVar* navmesh_draw_poly_bounds = nullptr;
ConVar* navmesh_draw_poly_bounds_inner = nullptr;
#endif // !DEDICATED
ConVar* sv_language = nullptr;
ConVar* sv_showconnecting = nullptr;
ConVar* sv_globalBanlist = nullptr;
ConVar* sv_pylonVisibility = nullptr;
ConVar* sv_pylonRefreshRate = nullptr;
ConVar* sv_banlistRefreshRate = nullptr;
ConVar* sv_statusRefreshRate = nullptr;
ConVar* sv_forceChatToTeamOnly = nullptr; ConVar* sv_forceChatToTeamOnly = nullptr;
ConVar* sv_single_core_dedi = nullptr; ConVar* sv_single_core_dedi = nullptr;
ConVar* sv_updaterate_mp = nullptr; ConVar* sv_maxunlag = nullptr;
ConVar* sv_updaterate_sp = nullptr; ConVar* sv_clockcorrection_msecs = nullptr;
ConVar* sv_autoReloadRate = nullptr;
ConVar* sv_updaterate_sp = nullptr;
ConVar* sv_updaterate_mp = nullptr;
ConVar* sv_simulateBots = nullptr;
ConVar* sv_showhitboxes = nullptr; ConVar* sv_showhitboxes = nullptr;
ConVar* sv_stats = nullptr; ConVar* sv_stats = nullptr;
ConVar* sv_quota_stringCmdsPerSecond = nullptr;
ConVar* sv_validatePersonaName = nullptr;
ConVar* sv_minPersonaNameLength = nullptr;
ConVar* sv_maxPersonaNameLength = nullptr;
ConVar* sv_voiceEcho = nullptr; ConVar* sv_voiceEcho = nullptr;
ConVar* sv_voiceenable = nullptr; ConVar* sv_voiceenable = nullptr;
ConVar* sv_alltalk = nullptr; ConVar* sv_alltalk = nullptr;
ConVar* player_userCmdsQueueWarning = nullptr; ConVar* player_userCmdsQueueWarning = nullptr;
//#ifdef DEDICATED
ConVar* sv_rcon_debug = nullptr;
ConVar* sv_rcon_sendlogs = nullptr;
//ConVar* sv_rcon_banpenalty = nullptr; // TODO
ConVar* sv_rcon_maxfailures = nullptr;
ConVar* sv_rcon_maxignores = nullptr;
ConVar* sv_rcon_maxsockets = nullptr;
ConVar* sv_rcon_maxconnections = nullptr;
ConVar* sv_rcon_maxpacketsize = nullptr;
ConVar* sv_rcon_whitelist_address = nullptr;
//#endif // DEDICATED
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
ConVar* sv_cheats = nullptr; ConVar* sv_cheats = nullptr;
ConVar* sv_visualizetraces = nullptr; ConVar* sv_visualizetraces = nullptr;
ConVar* sv_visualizetraces_duration = nullptr; ConVar* sv_visualizetraces_duration = nullptr;
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1)
ConVar* bhit_enable = nullptr; ConVar* bhit_enable = nullptr;
ConVar* bhit_depth_test = nullptr;
ConVar* bhit_abs_origin = nullptr;
#endif // !GAMEDLL_S0 && !GAMEDLL_S1
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// CLIENT | // CLIENT |
#ifndef DEDICATED #ifndef DEDICATED
ConVar* cl_rcon_inputonly = nullptr; ConVar* cl_updaterate_mp = nullptr;
ConVar* cl_quota_stringCmdsPerSecond = nullptr;
ConVar* cl_cmdrate = nullptr;
ConVar* cl_move_use_dt = nullptr;
ConVar* cl_notify_invert_x = nullptr;
ConVar* cl_notify_invert_y = nullptr;
ConVar* cl_notify_offset_x = nullptr;
ConVar* cl_notify_offset_y = nullptr;
ConVar* cl_showsimstats = nullptr;
ConVar* cl_simstats_invert_x = nullptr;
ConVar* cl_simstats_invert_y = nullptr;
ConVar* cl_simstats_offset_x = nullptr;
ConVar* cl_simstats_offset_y = nullptr;
ConVar* cl_showgpustats = nullptr;
ConVar* cl_gpustats_invert_x = nullptr;
ConVar* cl_gpustats_invert_y = nullptr;
ConVar* cl_gpustats_offset_x = nullptr;
ConVar* cl_gpustats_offset_y = nullptr;
ConVar* cl_showmaterialinfo = nullptr;
ConVar* cl_materialinfo_offset_x = nullptr;
ConVar* cl_materialinfo_offset_y = nullptr;
ConVar* cl_threaded_bone_setup = nullptr; ConVar* cl_threaded_bone_setup = nullptr;
ConVar* con_drawnotify = nullptr;
ConVar* con_notifylines = nullptr;
ConVar* con_notifytime = nullptr;
ConVar* con_notify_invert_x = nullptr;
ConVar* con_notify_invert_y = nullptr;
ConVar* con_notify_offset_x = nullptr;
ConVar* con_notify_offset_y = nullptr;
ConVar* con_notify_script_server_clr = nullptr;
ConVar* con_notify_script_client_clr = nullptr;
ConVar* con_notify_script_ui_clr = nullptr;
ConVar* con_notify_native_server_clr = nullptr;
ConVar* con_notify_native_client_clr = nullptr;
ConVar* con_notify_native_ui_clr = nullptr;
ConVar* con_notify_native_engine_clr = nullptr;
ConVar* con_notify_native_fs_clr = nullptr;
ConVar* con_notify_native_rtech_clr = nullptr;
ConVar* con_notify_native_ms_clr = nullptr;
ConVar* con_notify_native_audio_clr = nullptr;
ConVar* con_notify_native_video_clr = nullptr;
ConVar* con_notify_netcon_clr = nullptr;
ConVar* con_notify_common_clr = nullptr;
ConVar* con_notify_warning_clr = nullptr;
ConVar* con_notify_error_clr = nullptr;
ConVar* con_max_lines = nullptr;
ConVar* con_max_history = nullptr;
ConVar* con_suggest_limit = nullptr;
ConVar* con_suggest_showhelptext = nullptr;
ConVar* con_suggest_showflags = nullptr;
ConVar* origin_disconnectWhenOffline = nullptr; ConVar* origin_disconnectWhenOffline = nullptr;
ConVar* discord_updatePresence = nullptr; ConVar* discord_updatePresence = nullptr;
ConVar* serverbrowser_hideEmptyServers = nullptr;
ConVar* serverbrowser_mapFilter = nullptr;
ConVar* serverbrowser_gamemodeFilter = nullptr;
#endif // !DEDICATED #endif // !DEDICATED
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// FILESYSTEM | // FILESYSTEM |
ConVar* fs_showWarnings = nullptr;
ConVar* fs_showAllReads = nullptr; ConVar* fs_showAllReads = nullptr;
ConVar* fs_packedstore_entryblock_stats = nullptr;
ConVar* fs_packedstore_workspace = nullptr;
ConVar* fs_packedstore_compression_level = nullptr;
ConVar* fs_packedstore_max_helper_threads = nullptr;
//-----------------------------------------------------------------------------
// MATERIALSYSTEM |
#ifndef DEDICATED
ConVar* mat_alwaysComplain = nullptr;
#endif // !DEDICATED
//-----------------------------------------------------------------------------
// SQUIRREL |
ConVar* script_show_output = nullptr;
ConVar* script_show_warning = nullptr;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// NETCHANNEL | // NETCHANNEL |
ConVar* net_tracePayload = nullptr; ConVar* net_usesocketsforloopback;
ConVar* net_encryptionEnable = nullptr; ConVar* net_data_block_enabled = nullptr;
ConVar* net_useRandomKey = nullptr;
ConVar* net_usesocketsforloopback = nullptr;
ConVar* net_processTimeBudget = nullptr;
ConVar* net_datablock_networkLossForSlowSpeed = nullptr; ConVar* net_datablock_networkLossForSlowSpeed = nullptr;
ConVar* net_compressDataBlock = nullptr;
ConVar* pylon_matchmaking_hostname = nullptr; ConVar* net_showmsg = nullptr;
ConVar* pylon_host_update_interval = nullptr; ConVar* net_blockmsg = nullptr;
ConVar* pylon_showdebuginfo = nullptr; ConVar* net_showpeaks = nullptr;
ConVar* ssl_verify_peer = nullptr;
ConVar* curl_timeout = nullptr;
ConVar* curl_debug = nullptr;
//-----------------------------------------------------------------------------
// RTECH API |
ConVar* rtech_debug = nullptr;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// RUI | // RUI |
#ifndef DEDICATED #ifndef DEDICATED
ConVar* rui_drawEnable = nullptr;
ConVar* rui_defaultDebugFontFace = nullptr; ConVar* rui_defaultDebugFontFace = nullptr;
#endif // !DEDICATED #endif // !DEDICATED
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// MILES | // MILES |
#ifndef DEDICATED #ifndef DEDICATED
ConVar* miles_debug = nullptr;
ConVar* miles_language = nullptr; ConVar* miles_language = nullptr;
#endif #endif
//-----------------------------------------------------------------------------
// Purpose: initialize ConVar's
//-----------------------------------------------------------------------------
void ConVar_StaticInit(void)
{
//-------------------------------------------------------------------------
// ENGINE |
hostdesc = ConVar::StaticCreate("hostdesc", "", FCVAR_RELEASE, "Host game server description.", false, 0.f, false, 0.f, nullptr, nullptr);
sdk_fixedframe_tickinterval = ConVar::StaticCreate("sdk_fixedframe_tickinterval", "0.01", FCVAR_RELEASE, "The tick interval used by the SDK fixed frame.", false, 0.f, false, 0.f, nullptr, nullptr);
curl_debug = ConVar::StaticCreate("curl_debug" , "0" , FCVAR_DEVELOPMENTONLY, "Determines whether or not to enable curl debug logging.", false, 0.f, false, 0.f, nullptr, "1 = curl logs; 0 (zero) = no logs");
curl_timeout = ConVar::StaticCreate("curl_timeout" , "15", FCVAR_DEVELOPMENTONLY, "Maximum time in seconds a curl transfer operation could take.", false, 0.f, false, 0.f, nullptr, nullptr);
ssl_verify_peer = ConVar::StaticCreate("ssl_verify_peer", "1" , FCVAR_DEVELOPMENTONLY, "Verify the authenticity of the peer's SSL certificate.", false, 0.f, false, 0.f, nullptr, "1 = curl verifies; 0 (zero) = no verification");
rcon_address = ConVar::StaticCreate("rcon_address", "[loopback]:37015", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access address.", false, 0.f, false, 0.f, nullptr, nullptr);
rcon_password = ConVar::StaticCreate("rcon_password", "" , FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access password (rcon is disabled if empty).", false, 0.f, false, 0.f, &RCON_PasswordChanged_f, nullptr);
r_debug_overlay_nodecay = ConVar::StaticCreate("r_debug_overlay_nodecay" , "0", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Keeps all debug overlays alive regardless of their lifetime. Use command 'clear_debug_overlays' to clear everything.", false, 0.f, false, 0.f, nullptr, nullptr);
r_debug_overlay_invisible = ConVar::StaticCreate("r_debug_overlay_invisible" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Show invisible debug overlays (alpha < 1 = 255).", false, 0.f, false, 0.f, nullptr, nullptr);
r_debug_overlay_wireframe = ConVar::StaticCreate("r_debug_overlay_wireframe" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Use wireframe in debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
r_debug_draw_depth_test = ConVar::StaticCreate("r_debug_draw_depth_test" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Toggle depth test for other debug draw functionality.", false, 0.f, false, 0.f, nullptr, nullptr);
r_drawWorldMeshes = ConVar::StaticCreate("r_drawWorldMeshes" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Render world meshes.", false, 0.f, false, 0.f, nullptr, nullptr);
r_drawWorldMeshesDepthOnly = ConVar::StaticCreate("r_drawWorldMeshesDepthOnly" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Render world meshes (depth only).", false, 0.f, false, 0.f, nullptr, nullptr);
r_drawWorldMeshesDepthAtTheEnd = ConVar::StaticCreate("r_drawWorldMeshesDepthAtTheEnd", "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Render world meshes (depth at the end).", false, 0.f, false, 0.f, nullptr, nullptr);
//-------------------------------------------------------------------------
// SHARED |
modsystem_enable = ConVar::StaticCreate("modsystem_enable", "1", FCVAR_RELEASE, "Enable the modsystem.", false, 0.f, false, 0.f, nullptr, nullptr);
modsystem_debug = ConVar::StaticCreate("modsystem_debug" , "0", FCVAR_RELEASE, "Debug the modsystem." , false, 0.f, false, 0.f, nullptr, nullptr);
//-------------------------------------------------------------------------
// SERVER |
#ifndef CLIENT_DLL
ai_ainDumpOnLoad = ConVar::StaticCreate("ai_ainDumpOnLoad" , "0", FCVAR_DEVELOPMENTONLY, "Dumps AIN data from node graphs loaded from the disk on load.", false, 0.f, false, 0.f, nullptr, nullptr);
ai_ainDebugConnect = ConVar::StaticCreate("ai_ainDebugConnect" , "0", FCVAR_DEVELOPMENTONLY, "Debug AIN node connections.", false, 0.f, false, 0.f, nullptr, nullptr);
ai_script_nodes_draw_range = ConVar::StaticCreate("ai_script_nodes_draw_range" , "0", FCVAR_DEVELOPMENTONLY, "Debug draw AIN script nodes ranging from shift index to this cvar.", false, 0.f, false, 0.f, nullptr, nullptr);
ai_script_nodes_draw_nearest = ConVar::StaticCreate("ai_script_nodes_draw_nearest", "1", FCVAR_DEVELOPMENTONLY, "Debug draw AIN script node links to nearest node (build order is used if null).", false, 0.f, false, 0.f, nullptr, nullptr);
navmesh_always_reachable = ConVar::StaticCreate("navmesh_always_reachable" , "0" , FCVAR_DEVELOPMENTONLY, "Marks goal poly from agent poly as reachable regardless of table data ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr);
navmesh_debug_type = ConVar::StaticCreate("navmesh_debug_type" , "0" , FCVAR_DEVELOPMENTONLY, "NavMesh debug draw hull index.", true, 0.f, true, 4.f, nullptr, "0 = small, 1 = med_short, 2 = medium, 3 = large, 4 = extra large");
navmesh_debug_tile_range = ConVar::StaticCreate("navmesh_debug_tile_range" , "0" , FCVAR_DEVELOPMENTONLY, "NavMesh debug draw tiles ranging from shift index to this cvar.", true, 0.f, false, 0.f, nullptr, nullptr);
navmesh_debug_camera_range = ConVar::StaticCreate("navmesh_debug_camera_range" , "2000" , FCVAR_DEVELOPMENTONLY, "Only debug draw tiles within this distance from camera origin.", true, 0.f, false, 0.f, nullptr, nullptr);
#ifndef DEDICATED
navmesh_draw_bvtree = ConVar::StaticCreate("navmesh_draw_bvtree" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the BVTree of the NavMesh tiles.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount");
navmesh_draw_portal = ConVar::StaticCreate("navmesh_draw_portal" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the portal of the NavMesh tiles.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount");
navmesh_draw_polys = ConVar::StaticCreate("navmesh_draw_polys" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the polys of the NavMesh tiles.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount");
navmesh_draw_poly_bounds = ConVar::StaticCreate("navmesh_draw_poly_bounds" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the bounds of the NavMesh polys.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount");
navmesh_draw_poly_bounds_inner = ConVar::StaticCreate("navmesh_draw_poly_bounds_inner" , "0" , FCVAR_DEVELOPMENTONLY, "Draws the inner bounds of the NavMesh polys (requires navmesh_draw_poly_bounds).", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount");
#endif // !DEDICATED
sv_language = ConVar::StaticCreate("sv_language", "english", FCVAR_RELEASE, "Language of the server. Sent to MasterServer for localising error messages.", false, 0.f, false, 0.f, SV_LanguageChanged_f, nullptr);
sv_showconnecting = ConVar::StaticCreate("sv_showconnecting" , "1", FCVAR_RELEASE, "Logs information about the connecting client to the console.", false, 0.f, false, 0.f, nullptr, nullptr);
sv_globalBanlist = ConVar::StaticCreate("sv_globalBanlist" , "1", FCVAR_RELEASE, "Determines whether or not to use the global banned list.", false, 0.f, false, 0.f, nullptr, "0 = Disable, 1 = Enable.");
sv_pylonVisibility = ConVar::StaticCreate("sv_pylonVisibility", "0", FCVAR_RELEASE, "Determines the visibility to the Pylon master server.", false, 0.f, false, 0.f, nullptr, "0 = Offline, 1 = Hidden, 2 = Public.");
sv_pylonRefreshRate = ConVar::StaticCreate("sv_pylonRefreshRate" , "5.0" , FCVAR_DEVELOPMENTONLY, "Pylon host refresh rate (seconds).", true, 2.f, true, 8.f, nullptr, nullptr);
sv_banlistRefreshRate = ConVar::StaticCreate("sv_banlistRefreshRate", "30.0", FCVAR_DEVELOPMENTONLY, "Banned list refresh rate (seconds).", true, 1.f, false, 0.f, nullptr, nullptr);
sv_statusRefreshRate = ConVar::StaticCreate("sv_statusRefreshRate" , "0.5", FCVAR_RELEASE, "Server status refresh rate (seconds).", true, 0.f, false, 0.f, nullptr, nullptr);
sv_autoReloadRate = ConVar::StaticCreate("sv_autoReloadRate" , "0" , FCVAR_RELEASE, "Time in seconds between each server auto-reload (disabled if null).", true, 0.f, false, 0.f, nullptr, nullptr);
sv_simulateBots = ConVar::StaticCreate("sv_simulateBots", "1", FCVAR_RELEASE, "Simulate user commands for bots on the server.", true, 0.f, false, 0.f, nullptr, nullptr);
sv_rcon_debug = ConVar::StaticCreate("sv_rcon_debug" , "0" , FCVAR_RELEASE, "Show rcon debug information ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr);
sv_rcon_sendlogs = ConVar::StaticCreate("sv_rcon_sendlogs" , "0" , FCVAR_RELEASE, "Network console logs to connected and authenticated sockets.", false, 0.f, false, 0.f, nullptr, nullptr);
//sv_rcon_banpenalty = ConVar::StaticCreate("sv_rcon_banpenalty" , "10", FCVAR_RELEASE, "Number of minutes to ban users who fail rcon authentication.", false, 0.f, false, 0.f, nullptr, nullptr);
sv_rcon_maxfailures = ConVar::StaticCreate("sv_rcon_maxfailures", "10", FCVAR_RELEASE, "Max number of times an user can fail rcon authentication before being banned.", true, 1.f, false, 0.f, nullptr, nullptr);
sv_rcon_maxignores = ConVar::StaticCreate("sv_rcon_maxignores" , "15", FCVAR_RELEASE, "Max number of times an user can ignore the instruction message before being banned.", true, 1.f, false, 0.f, nullptr, nullptr);
sv_rcon_maxsockets = ConVar::StaticCreate("sv_rcon_maxsockets" , "32", FCVAR_RELEASE, "Max number of accepted sockets before the server starts closing redundant sockets.", true, 1.f, true, MAX_PLAYERS, nullptr, nullptr);
sv_rcon_maxconnections = ConVar::StaticCreate("sv_rcon_maxconnections" , "1" , FCVAR_RELEASE, "Max number of authenticated connections before the server closes the listen socket.", true, 1.f, true, MAX_PLAYERS, &RCON_ConnectionCountChanged_f, nullptr);
sv_rcon_maxpacketsize = ConVar::StaticCreate("sv_rcon_maxpacketsize" , "1024", FCVAR_RELEASE, "Max number of bytes allowed in a command packet from a non-authenticated netconsole.", true, 0.f, false, 0.f, nullptr, nullptr);
sv_rcon_whitelist_address = ConVar::StaticCreate("sv_rcon_whitelist_address", "" , FCVAR_RELEASE, "This address is not considered a 'redundant' socket and will never be banned for failed authentication attempts.", false, 0.f, false, 0.f, &RCON_WhiteListAddresChanged_f, "Format: '::ffff:127.0.0.1'");
sv_quota_stringCmdsPerSecond = ConVar::StaticCreate("sv_quota_stringCmdsPerSecond", "16", FCVAR_RELEASE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands.", true, 0.f, false, 0.f, nullptr, nullptr);
sv_validatePersonaName = ConVar::StaticCreate("sv_validatePersonaName" , "1" , FCVAR_RELEASE, "Validate the client's textual persona name on connect.", true, 0.f, false, 0.f, nullptr, nullptr);
sv_minPersonaNameLength = ConVar::StaticCreate("sv_minPersonaNameLength", "4" , FCVAR_RELEASE, "The minimum length of the client's textual persona name.", true, 0.f, false, 0.f, nullptr, nullptr);
sv_maxPersonaNameLength = ConVar::StaticCreate("sv_maxPersonaNameLength", "16", FCVAR_RELEASE, "The maximum length of the client's textual persona name.", true, 0.f, false, 0.f, nullptr, nullptr);
#endif // !CLIENT_DLL
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1)
bhit_depth_test = ConVar::StaticCreate("bhit_depth_test", "0", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Use depth test for bullet ray trace overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
bhit_abs_origin = ConVar::StaticCreate("bhit_abs_origin", "1", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Draw entity's predicted abs origin upon bullet impact for trajectory debugging (requires 'r_visualizetraces' to be set!).", false, 0.f, false, 0.f, nullptr, nullptr);
#endif // !GAMEDLL_S0 && !GAMEDLL_S1
//-------------------------------------------------------------------------
// CLIENT |
#ifndef DEDICATED
cl_rcon_inputonly = ConVar::StaticCreate("cl_rcon_inputonly", "0" , FCVAR_RELEASE, "Tells the rcon server whether or not we are input only.", false, 0.f, false, 0.f, RCON_InputOnlyChanged_f, nullptr);
cl_quota_stringCmdsPerSecond = ConVar::StaticCreate("cl_quota_stringCmdsPerSecond", "16" , FCVAR_RELEASE, "How many string commands per second user is allowed to submit, 0 to allow all submissions.", true, 0.f, false, 0.f, nullptr, nullptr);
cl_notify_invert_x = ConVar::StaticCreate("cl_notify_invert_x", "0", FCVAR_DEVELOPMENTONLY, "Inverts the X offset for console notify debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_notify_invert_y = ConVar::StaticCreate("cl_notify_invert_y", "0", FCVAR_DEVELOPMENTONLY, "Inverts the Y offset for console notify debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_notify_offset_x = ConVar::StaticCreate("cl_notify_offset_x", "10", FCVAR_DEVELOPMENTONLY, "X offset for console notify debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_notify_offset_y = ConVar::StaticCreate("cl_notify_offset_y", "10", FCVAR_DEVELOPMENTONLY, "Y offset for console notify debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_showsimstats = ConVar::StaticCreate("cl_showsimstats" , "0" , FCVAR_DEVELOPMENTONLY, "Shows the tick counter for the server/client simulation and the render frame.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_simstats_invert_x = ConVar::StaticCreate("cl_simstats_invert_x", "1" , FCVAR_DEVELOPMENTONLY, "Inverts the X offset for simulation debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_simstats_invert_y = ConVar::StaticCreate("cl_simstats_invert_y", "1" , FCVAR_DEVELOPMENTONLY, "Inverts the Y offset for simulation debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_simstats_offset_x = ConVar::StaticCreate("cl_simstats_offset_x", "650", FCVAR_DEVELOPMENTONLY, "X offset for simulation debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_simstats_offset_y = ConVar::StaticCreate("cl_simstats_offset_y", "120", FCVAR_DEVELOPMENTONLY, "Y offset for simulation debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_showgpustats = ConVar::StaticCreate("cl_showgpustats" , "0", FCVAR_DEVELOPMENTONLY, "Texture streaming debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_gpustats_invert_x = ConVar::StaticCreate("cl_gpustats_invert_x", "1", FCVAR_DEVELOPMENTONLY, "Inverts the X offset for texture streaming debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_gpustats_invert_y = ConVar::StaticCreate("cl_gpustats_invert_y", "1", FCVAR_DEVELOPMENTONLY, "Inverts the Y offset for texture streaming debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_gpustats_offset_x = ConVar::StaticCreate("cl_gpustats_offset_x", "650", FCVAR_DEVELOPMENTONLY, "X offset for texture streaming debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_gpustats_offset_y = ConVar::StaticCreate("cl_gpustats_offset_y", "105", FCVAR_DEVELOPMENTONLY, "Y offset for texture streaming debug overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_showmaterialinfo = ConVar::StaticCreate("cl_showmaterialinfo" , "0" , FCVAR_DEVELOPMENTONLY, "Draw info for the material under the crosshair on screen.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_materialinfo_offset_x = ConVar::StaticCreate("cl_materialinfo_offset_x", "0" , FCVAR_DEVELOPMENTONLY, "X offset for material debug info overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
cl_materialinfo_offset_y = ConVar::StaticCreate("cl_materialinfo_offset_y", "420", FCVAR_DEVELOPMENTONLY, "Y offset for material debug info overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
con_drawnotify = ConVar::StaticCreate("con_drawnotify", "0", FCVAR_RELEASE, "Draws the RUI console to the hud.", false, 0.f, false, 0.f, nullptr, nullptr);
con_notifylines = ConVar::StaticCreate("con_notifylines" , "3" , FCVAR_MATERIAL_SYSTEM_THREAD, "Number of console lines to overlay for debugging.", true, 1.f, false, 0.f, nullptr, nullptr);
con_notifytime = ConVar::StaticCreate("con_notifytime" , "6" , FCVAR_MATERIAL_SYSTEM_THREAD, "How long to display recent console text to the upper part of the game window.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_invert_x = ConVar::StaticCreate("con_notify_invert_x", "0" , FCVAR_MATERIAL_SYSTEM_THREAD, "Inverts the X offset for RUI console overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
con_notify_invert_y = ConVar::StaticCreate("con_notify_invert_y", "0" , FCVAR_MATERIAL_SYSTEM_THREAD, "Inverts the Y offset for RUI console overlay.", false, 0.f, false, 0.f, nullptr, nullptr);
con_notify_offset_x = ConVar::StaticCreate("con_notify_offset_x", "10", FCVAR_MATERIAL_SYSTEM_THREAD, "X offset for RUI console overlay.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_offset_y = ConVar::StaticCreate("con_notify_offset_y", "10", FCVAR_MATERIAL_SYSTEM_THREAD, "Y offset for RUI console overlay.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_script_server_clr = ConVar::StaticCreate("con_notify_script_server_clr", "130 120 245 255", FCVAR_MATERIAL_SYSTEM_THREAD, "Script SERVER VM RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_script_client_clr = ConVar::StaticCreate("con_notify_script_client_clr", "117 116 139 255", FCVAR_MATERIAL_SYSTEM_THREAD, "Script CLIENT VM RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_script_ui_clr = ConVar::StaticCreate("con_notify_script_ui_clr" , "200 110 110 255", FCVAR_MATERIAL_SYSTEM_THREAD, "Script UI VM RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_server_clr = ConVar::StaticCreate("con_notify_native_server_clr", "20 50 248 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native SERVER RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_client_clr = ConVar::StaticCreate("con_notify_native_client_clr", "70 70 70 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native CLIENT RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_ui_clr = ConVar::StaticCreate("con_notify_native_ui_clr" , "200 60 60 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native UI RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_engine_clr = ConVar::StaticCreate("con_notify_native_engine_clr", "255 255 255 255", FCVAR_MATERIAL_SYSTEM_THREAD, "Native engine RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_fs_clr = ConVar::StaticCreate("con_notify_native_fs_clr" , "0 100 225 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native FileSystem RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_rtech_clr = ConVar::StaticCreate("con_notify_native_rtech_clr" , "25 120 20 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native RTech RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_ms_clr = ConVar::StaticCreate("con_notify_native_ms_clr" , "200 20 180 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native MaterialSystem RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_audio_clr = ConVar::StaticCreate("con_notify_native_audio_clr" , "238 43 10 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native AudioSystem RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_native_video_clr = ConVar::StaticCreate("con_notify_native_video_clr" , "115 0 235 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native VideoSystem RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_netcon_clr = ConVar::StaticCreate("con_notify_netcon_clr" , "255 255 255 255", FCVAR_MATERIAL_SYSTEM_THREAD, "Netconsole RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_common_clr = ConVar::StaticCreate("con_notify_common_clr" , "255 140 80 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Common RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_warning_clr = ConVar::StaticCreate("con_notify_warning_clr", "180 180 20 255", FCVAR_MATERIAL_SYSTEM_THREAD, "Warning RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_notify_error_clr = ConVar::StaticCreate("con_notify_error_clr" , "225 20 20 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Error RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr);
con_max_lines = ConVar::StaticCreate("con_max_lines" , "1024", FCVAR_DEVELOPMENTONLY, "Maximum number of lines in the console before cleanup starts.", true, 1.f, false, 0.f, nullptr, nullptr);
con_max_history = ConVar::StaticCreate("con_max_history" , "512" , FCVAR_DEVELOPMENTONLY, "Maximum number of command submission items before history cleanup starts.", true, 0.f, false, 0.f, nullptr, nullptr);
con_suggest_limit = ConVar::StaticCreate("con_suggest_limit" , "128" , FCVAR_DEVELOPMENTONLY, "Maximum number of suggestions the autocomplete window will show for the console.", true, 0.f, false, 0.f, nullptr, nullptr);
con_suggest_showhelptext = ConVar::StaticCreate("con_suggest_showhelptext" , "1" , FCVAR_DEVELOPMENTONLY, "Show CommandBase help text in autocomplete window.", false, 0.f, false, 0.f, nullptr, nullptr);
con_suggest_showflags = ConVar::StaticCreate("con_suggest_showflags" , "1" , FCVAR_DEVELOPMENTONLY, "Show CommandBase flags in autocomplete window.", false, 0.f, false, 0.f, nullptr, nullptr);
serverbrowser_hideEmptyServers = ConVar::StaticCreate("serverbrowser_hideEmptyServers", "0", FCVAR_RELEASE, "Hide empty servers in the server browser.", false, 0.f, false, 0.f, nullptr, nullptr);
serverbrowser_mapFilter = ConVar::StaticCreate("serverbrowser_mapFilter", "0", FCVAR_RELEASE, "Filter servers by map in the server browser.", false, 0.f, false, 0.f, nullptr, nullptr);
serverbrowser_gamemodeFilter = ConVar::StaticCreate("serverbrowser_gamemodeFilter", "0", FCVAR_RELEASE, "Filter servers by gamemode in the server browser.", false, 0.f, false, 0.f, nullptr, nullptr);
#endif // !DEDICATED
// Taken from S15:
usercmd_frametime_max = ConVar::StaticCreate("usercmd_frametime_max", "0.100", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "The largest amount of simulation seconds a UserCmd can have.", false, 0.f, false, 0.f, nullptr, nullptr);
usercmd_frametime_min = ConVar::StaticCreate("usercmd_frametime_min", "0.002857", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "The smallest amount of simulation seconds a UserCmd can have.", false, 0.f, false, 0.f, nullptr, nullptr);
usercmd_dualwield_enable = ConVar::StaticCreate("usercmd_dualwield_enable", "0", FCVAR_REPLICATED | FCVAR_RELEASE, "Allows setting dual wield cycle slots, and activating multiple inventory weapons from UserCmd.", false, 0.f, false, 0.f, nullptr, nullptr);
//-------------------------------------------------------------------------
// FILESYSTEM |
fs_showWarnings = ConVar::StaticCreate("fs_showWarnings" , "0", FCVAR_DEVELOPMENTONLY, "Logs the FileSystem warnings to the console, filtered by 'fs_warning_level' ( !slower! ).", true, 0.f, true, 2.f, nullptr, "0 = log to file. 1 = 0 + log to console. 2 = 1 + log to notify");
fs_packedstore_entryblock_stats = ConVar::StaticCreate("fs_packedstore_entryblock_stats" , "0", FCVAR_DEVELOPMENTONLY, "Logs the stats of each file entry in the VPK during decompression ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr);
fs_packedstore_workspace = ConVar::StaticCreate("fs_packedstore_workspace" , "ship", FCVAR_DEVELOPMENTONLY, "Determines the current VPK workspace.", false, 0.f, false, 0.f, nullptr, nullptr);
fs_packedstore_compression_level = ConVar::StaticCreate("fs_packedstore_compression_level", "default", FCVAR_DEVELOPMENTONLY, "Determines the VPK compression level.", false, 0.f, false, 0.f, nullptr, "fastest faster default better uber");
fs_packedstore_max_helper_threads = ConVar::StaticCreate("fs_packedstore_max_helper_threads" , "-1", FCVAR_DEVELOPMENTONLY, "Max # of additional \"helper\" threads to create during compression.", true, -1, true, LZHAM_MAX_HELPER_THREADS, nullptr, "Must range between [-1,LZHAM_MAX_HELPER_THREADS], where -1=max practical");
//-------------------------------------------------------------------------
// MATERIALSYSTEM |
#ifndef DEDICATED
mat_alwaysComplain = ConVar::StaticCreate("mat_alwaysComplain", "0", FCVAR_RELEASE | FCVAR_MATERIAL_SYSTEM_THREAD, "Always complain when a material is missing.", false, 0.f, false, 0.f, nullptr, nullptr);
#endif // !DEDICATED
//-------------------------------------------------------------------------
// SQUIRREL |
script_show_output = ConVar::StaticCreate("script_show_output" , "0", FCVAR_RELEASE, "Prints the VM output to the console ( !slower! ).", true, 0.f, true, 2.f, nullptr, "0 = log to file. 1 = 0 + log to console. 2 = 1 + log to notify");
script_show_warning = ConVar::StaticCreate("script_show_warning", "0", FCVAR_RELEASE, "Prints the VM warning output to the console ( !slower! ).", true, 0.f, true, 2.f, nullptr, "0 = log to file. 1 = 0 + log to console. 2 = 1 + log to notify");
//-------------------------------------------------------------------------
// NETCHANNEL |
net_tracePayload = ConVar::StaticCreate("net_tracePayload" , "0", FCVAR_DEVELOPMENTONLY , "Log the payload of the send/recv datagram to a file on the disk.", false, 0.f, false, 0.f, nullptr, nullptr);
net_encryptionEnable = ConVar::StaticCreate("net_encryptionEnable" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED , "Use AES encryption on game packets.", false, 0.f, false, 0.f, nullptr, nullptr);
net_useRandomKey = ConVar::StaticCreate("net_useRandomKey" , "1" , FCVAR_RELEASE , "Use random AES encryption key for game packets.", false, 0.f, false, 0.f, &NET_UseRandomKeyChanged_f, nullptr);
net_processTimeBudget = ConVar::StaticCreate("net_processTimeBudget" ,"200" , FCVAR_RELEASE , "Net message process time budget in milliseconds (removing netchannel if exceeded).", true, 0.f, false, 0.f, nullptr, "0 = disabled");
//-------------------------------------------------------------------------
// NETWORKSYSTEM |
pylon_matchmaking_hostname = ConVar::StaticCreate("pylon_matchmaking_hostname", "ms.r5reloaded.com", FCVAR_RELEASE, "Holds the pylon matchmaking hostname.", false, 0.f, false, 0.f, &MP_HostName_Changed_f, nullptr);
pylon_host_update_interval = ConVar::StaticCreate("pylon_host_update_interval", "5" , FCVAR_RELEASE, "Length of time in seconds between each status update interval to master server.", true, 5.f, false, 0.f, nullptr, nullptr);
pylon_showdebuginfo = ConVar::StaticCreate("pylon_showdebuginfo" , "0" , FCVAR_RELEASE, "Shows debug output for pylon.", false, 0.f, false, 0.f, nullptr, nullptr);
//-------------------------------------------------------------------------
// RTECH API |
rtech_debug = ConVar::StaticCreate("rtech_debug", "0", FCVAR_DEVELOPMENTONLY, "Shows debug output for the RTech system.", false, 0.f, false, 0.f, nullptr, nullptr);
//-------------------------------------------------------------------------
// RUI |
#ifndef DEDICATED
rui_drawEnable = ConVar::StaticCreate("rui_drawEnable", "1", FCVAR_RELEASE, "Draws the RUI if set.", false, 0.f, false, 0.f, nullptr, "1 = draw; 0 (zero) = no draw");
#endif // !DEDICATED
//-------------------------------------------------------------------------
// MILES |
#ifndef DEDICATED
miles_debug = ConVar::StaticCreate("miles_debug", "0", FCVAR_RELEASE, "Enables debug prints for the Miles Sound System.", false, 0.f, false, 0.f, nullptr, "1 = print; 0 (zero) = no print");
#endif // !DEDICATED
//-------------------------------------------------------------------------
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: initialize shipped ConVar's // Purpose: initialize shipped ConVar's
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -463,16 +133,21 @@ void ConVar_InitShipped(void)
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
ai_script_nodes_draw = g_pCVar->FindVar("ai_script_nodes_draw"); ai_script_nodes_draw = g_pCVar->FindVar("ai_script_nodes_draw");
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1)
bhit_enable = g_pCVar->FindVar("bhit_enable"); bhit_enable = g_pCVar->FindVar("bhit_enable");
#endif // !GAMEDLL_S0 && !GAMEDLL_S1
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
developer = g_pCVar->FindVar("developer"); developer = g_pCVar->FindVar("developer");
fps_max = g_pCVar->FindVar("fps_max"); fps_max = g_pCVar->FindVar("fps_max");
fps_max_vsync = g_pCVar->FindVar("fps_max_vsync");
base_tickinterval_sp = g_pCVar->FindVar("base_tickinterval_sp");
base_tickinterval_mp = g_pCVar->FindVar("base_tickinterval_mp");
fs_showAllReads = g_pCVar->FindVar("fs_showAllReads"); fs_showAllReads = g_pCVar->FindVar("fs_showAllReads");
eula_version = g_pCVar->FindVar("eula_version");
eula_version_accepted = g_pCVar->FindVar("eula_version_accepted");
language_cvar = g_pCVar->FindVar("language");
#ifndef DEDICATED #ifndef DEDICATED
cl_cmdrate = g_pCVar->FindVar("cl_cmdrate"); cl_updaterate_mp = g_pCVar->FindVar("cl_updaterate_mp");
cl_move_use_dt = g_pCVar->FindVar("cl_move_use_dt");
cl_threaded_bone_setup = g_pCVar->FindVar("cl_threaded_bone_setup"); cl_threaded_bone_setup = g_pCVar->FindVar("cl_threaded_bone_setup");
#endif // !DEDICATED #endif // !DEDICATED
single_frame_shutdown_for_reload = g_pCVar->FindVar("single_frame_shutdown_for_reload"); single_frame_shutdown_for_reload = g_pCVar->FindVar("single_frame_shutdown_for_reload");
@ -483,6 +158,7 @@ void ConVar_InitShipped(void)
#ifndef DEDICATED #ifndef DEDICATED
miles_language = g_pCVar->FindVar("miles_language"); miles_language = g_pCVar->FindVar("miles_language");
rui_defaultDebugFontFace = g_pCVar->FindVar("rui_defaultDebugFontFace"); rui_defaultDebugFontFace = g_pCVar->FindVar("rui_defaultDebugFontFace");
in_syncRT = g_pCVar->FindVar("in_syncRT");
r_visualizetraces = g_pCVar->FindVar("r_visualizetraces"); r_visualizetraces = g_pCVar->FindVar("r_visualizetraces");
r_visualizetraces_duration = g_pCVar->FindVar("r_visualizetraces_duration"); r_visualizetraces_duration = g_pCVar->FindVar("r_visualizetraces_duration");
#endif // !DEDICATED #endif // !DEDICATED
@ -496,7 +172,7 @@ void ConVar_InitShipped(void)
old_gather_props = g_pCVar->FindVar("old_gather_props"); old_gather_props = g_pCVar->FindVar("old_gather_props");
#ifndef DEDICATED #ifndef DEDICATED
origin_disconnectWhenOffline = g_pCVar->FindVar("origin_disconnectWhenOffline"); origin_disconnectWhenOffline = g_pCVar->FindVar("origin_disconnectWhenOffline");
discord_updatePresence = g_pCVar->FindVar("discord_updatePresence"); discord_updatePresence = g_pCVar->FindVar("discord_updatePresence");
#endif // !DEDICATED #endif // !DEDICATED
mp_gamemode = g_pCVar->FindVar("mp_gamemode"); mp_gamemode = g_pCVar->FindVar("mp_gamemode");
ip_cvar = g_pCVar->FindVar("ip"); ip_cvar = g_pCVar->FindVar("ip");
@ -505,13 +181,24 @@ void ConVar_InitShipped(void)
hostport = g_pCVar->FindVar("hostport"); hostport = g_pCVar->FindVar("hostport");
host_hasIrreversibleShutdown = g_pCVar->FindVar("host_hasIrreversibleShutdown"); host_hasIrreversibleShutdown = g_pCVar->FindVar("host_hasIrreversibleShutdown");
host_timescale = g_pCVar->FindVar("host_timescale"); host_timescale = g_pCVar->FindVar("host_timescale");
net_data_block_enabled = g_pCVar->FindVar("net_data_block_enabled");
net_compressDataBlock = g_pCVar->FindVar("net_compressDataBlock");
net_datablock_networkLossForSlowSpeed = g_pCVar->FindVar("net_datablock_networkLossForSlowSpeed"); net_datablock_networkLossForSlowSpeed = g_pCVar->FindVar("net_datablock_networkLossForSlowSpeed");
net_usesocketsforloopback = g_pCVar->FindVar("net_usesocketsforloopback"); net_usesocketsforloopback = g_pCVar->FindVar("net_usesocketsforloopback");
net_showmsg = g_pCVar->FindVar("net_showmsg");
net_blockmsg = g_pCVar->FindVar("net_blockmsg");
net_showpeaks = g_pCVar->FindVar("net_showpeaks");
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
sv_stats = g_pCVar->FindVar("sv_stats"); sv_stats = g_pCVar->FindVar("sv_stats");
sv_updaterate_mp = g_pCVar->FindVar("sv_updaterate_mp"); sv_maxunlag = g_pCVar->FindVar("sv_maxunlag");
sv_clockcorrection_msecs = g_pCVar->FindVar("sv_clockcorrection_msecs");
sv_updaterate_sp = g_pCVar->FindVar("sv_updaterate_sp"); sv_updaterate_sp = g_pCVar->FindVar("sv_updaterate_sp");
sv_updaterate_mp = g_pCVar->FindVar("sv_updaterate_mp");
sv_showhitboxes = g_pCVar->FindVar("sv_showhitboxes"); sv_showhitboxes = g_pCVar->FindVar("sv_showhitboxes");
sv_forceChatToTeamOnly = g_pCVar->FindVar("sv_forceChatToTeamOnly"); sv_forceChatToTeamOnly = g_pCVar->FindVar("sv_forceChatToTeamOnly");
@ -523,6 +210,9 @@ void ConVar_InitShipped(void)
sv_alltalk = g_pCVar->FindVar("sv_alltalk"); sv_alltalk = g_pCVar->FindVar("sv_alltalk");
player_userCmdsQueueWarning = g_pCVar->FindVar("player_userCmdsQueueWarning"); player_userCmdsQueueWarning = g_pCVar->FindVar("player_userCmdsQueueWarning");
sv_updaterate_sp->RemoveFlags(FCVAR_DEVELOPMENTONLY);
sv_updaterate_mp->RemoveFlags(FCVAR_DEVELOPMENTONLY);
sv_showhitboxes->SetMin(-1); // Allow user to go over each entity manually without going out of bounds. sv_showhitboxes->SetMin(-1); // Allow user to go over each entity manually without going out of bounds.
sv_showhitboxes->SetMax(NUM_ENT_ENTRIES - 1); sv_showhitboxes->SetMax(NUM_ENT_ENTRIES - 1);
@ -532,21 +222,29 @@ void ConVar_InitShipped(void)
sv_single_core_dedi->RemoveFlags(FCVAR_DEVELOPMENTONLY); sv_single_core_dedi->RemoveFlags(FCVAR_DEVELOPMENTONLY);
ai_script_nodes_draw->SetValue(-1); ai_script_nodes_draw->SetValue(-1);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
bhit_enable->SetValue(0); bhit_enable->SetValue(0);
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2)
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
#ifndef DEDICATED #ifndef DEDICATED
cl_updaterate_mp->RemoveFlags(FCVAR_DEVELOPMENTONLY);
cl_threaded_bone_setup->RemoveFlags(FCVAR_DEVELOPMENTONLY); cl_threaded_bone_setup->RemoveFlags(FCVAR_DEVELOPMENTONLY);
rui_defaultDebugFontFace->RemoveFlags(FCVAR_DEVELOPMENTONLY); rui_defaultDebugFontFace->RemoveFlags(FCVAR_DEVELOPMENTONLY);
origin_disconnectWhenOffline->RemoveFlags(FCVAR_DEVELOPMENTONLY); origin_disconnectWhenOffline->RemoveFlags(FCVAR_DEVELOPMENTONLY);
discord_updatePresence->RemoveFlags(FCVAR_DEVELOPMENTONLY); discord_updatePresence->RemoveFlags(FCVAR_DEVELOPMENTONLY);
#endif // !DEDICATED #endif // !DEDICATED
fps_max_vsync->RemoveFlags(FCVAR_DEVELOPMENTONLY);
base_tickinterval_sp->RemoveFlags(FCVAR_DEVELOPMENTONLY);
base_tickinterval_mp->RemoveFlags(FCVAR_DEVELOPMENTONLY);
mp_gamemode->RemoveFlags(FCVAR_DEVELOPMENTONLY); mp_gamemode->RemoveFlags(FCVAR_DEVELOPMENTONLY);
mp_gamemode->RemoveChangeCallback(mp_gamemode->m_fnChangeCallbacks[0]); mp_gamemode->RemoveChangeCallback(mp_gamemode->m_fnChangeCallbacks[0]);
mp_gamemode->InstallChangeCallback(MP_GameMode_Changed_f, false); mp_gamemode->InstallChangeCallback(MP_GameMode_Changed_f, false);
net_usesocketsforloopback->RemoveFlags(FCVAR_DEVELOPMENTONLY); net_usesocketsforloopback->RemoveFlags(FCVAR_DEVELOPMENTONLY);
net_usesocketsforloopback->InstallChangeCallback(NET_UseSocketsForLoopbackChanged_f, false); net_usesocketsforloopback->InstallChangeCallback(NET_UseSocketsForLoopbackChanged_f, false);
#ifndef DEDICATED
language_cvar->InstallChangeCallback(LanguageChanged_f, false);
#endif // !DEDICATED
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -610,79 +308,19 @@ void ConVar_PurgeHostNames(void)
} }
} }
//----------------------------------------------------------------------------- static ConCommand bhit("bhit", BHit_f, "Bullet-hit trajectory debug", FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL);
// Purpose: ConCommand registration
//-----------------------------------------------------------------------------
void ConCommand_StaticInit(void)
{
//-------------------------------------------------------------------------
// ENGINE DLL |
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1)
ConCommand::StaticCreate("bhit", "Bullet-hit trajectory debug.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL, BHit_f, nullptr);
#endif // !GAMEDLL_S0 && !GAMEDLL_S1
#ifndef DEDICATED #ifndef DEDICATED
ConCommand::StaticCreate("line", "Draw a debug line.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, Line_f, nullptr); static ConCommand line("line", Line_f, "Draw a debug line", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT);
ConCommand::StaticCreate("sphere", "Draw a debug sphere.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, Sphere_f, nullptr); static ConCommand sphere("sphere", Sphere_f, "Draw a debug sphere", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT);
ConCommand::StaticCreate("capsule", "Draw a debug capsule.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, Capsule_f, nullptr); static ConCommand capsule("capsule", Capsule_f, "Draw a debug capsule", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT);
#endif //!DEDICATED #endif //!DEDICATED
ConCommand::StaticCreate("con_help", "Shows the colors and description of each context.", nullptr, FCVAR_RELEASE, CON_Help_f, nullptr);
#ifndef CLIENT_DLL
ConCommand::StaticCreate("reload_playlists", "Reloads the playlists file.", nullptr, FCVAR_RELEASE, Host_ReloadPlaylists_f, nullptr);
#endif // !CLIENT_DLL
//-------------------------------------------------------------------------
// SERVER DLL |
#ifndef CLIENT_DLL
ConCommand::StaticCreate("script", "Run input code as SERVER script on the VM.", nullptr, FCVAR_GAMEDLL | FCVAR_CHEAT, SQVM_ServerScript_f, nullptr);
ConCommand::StaticCreate("kick", "Kick a client from the server by user name.", "kick \"<userId>\"", FCVAR_RELEASE, Host_Kick_f, nullptr);
ConCommand::StaticCreate("kickid", "Kick a client from the server by handle, nucleus id or ip address.", "kickid \"<handle>\"/\"<nucleusId>/<ipAddress>\"", FCVAR_RELEASE, Host_KickID_f, nullptr);
ConCommand::StaticCreate("ban", "Bans a client from the server by user name.", "ban <userId>", FCVAR_RELEASE, Host_Ban_f, nullptr);
ConCommand::StaticCreate("banid", "Bans a client from the server by handle, nucleus id or ip address.", "banid \"<handle>\"/\"<nucleusId>/<ipAddress>\"", FCVAR_RELEASE, Host_BanID_f, nullptr);
ConCommand::StaticCreate("unban", "Unbans a client from the server by nucleus id or ip address.", "unban \"<nucleusId>\"/\"<ipAddress>\"", FCVAR_RELEASE, Host_Unban_f, nullptr);
ConCommand::StaticCreate("sv_reloadbanlist", "Reloads the banned list.", nullptr, FCVAR_RELEASE, Host_ReloadBanList_f, nullptr);
ConCommand::StaticCreate("sv_addbot", "Creates a bot on the server.", nullptr, FCVAR_RELEASE, CC_CreateFakePlayer_f, nullptr);
ConCommand::StaticCreate("navmesh_hotswap", "Hot swap the NavMesh for all hulls.", nullptr, FCVAR_DEVELOPMENTONLY, Detour_HotSwap_f, nullptr);
#endif // !CLIENT_DLL
#ifndef DEDICATED
//-------------------------------------------------------------------------
// CLIENT DLL |
ConCommand::StaticCreate("script_client", "Run input code as CLIENT script on the VM.", nullptr, FCVAR_CLIENTDLL | FCVAR_CHEAT, SQVM_ClientScript_f, nullptr);
ConCommand::StaticCreate("rcon", "Forward RCON query to remote server.", "rcon \"<query>\"", FCVAR_CLIENTDLL | FCVAR_RELEASE, RCON_CmdQuery_f, nullptr);
ConCommand::StaticCreate("rcon_disconnect", "Disconnect from RCON server.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, RCON_Disconnect_f, nullptr);
ConCommand::StaticCreate("con_history", "Shows the developer console submission history.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, CON_LogHistory_f, nullptr); // TODO: move VPK building code to separate file and place this in 'packedstore.cpp'
ConCommand::StaticCreate("con_removeline", "Removes a range of lines from the developer console.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, CON_RemoveLine_f, nullptr); static ConCommand fs_vpk_mount("fs_vpk_mount", VPK_Mount_f, "Mount a VPK file for FileSystem usage", FCVAR_DEVELOPMENTONLY);
ConCommand::StaticCreate("con_clearlines", "Clears all lines from the developer console.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, CON_ClearLines_f, nullptr); static ConCommand fs_vpk_unmount("fs_vpk_unmount", VPK_Unmount_f, "Unmount a VPK file and clear its cache", FCVAR_DEVELOPMENTONLY);
ConCommand::StaticCreate("con_clearhistory", "Clears all submissions from the developer console history.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, CON_ClearHistory_f, nullptr); static ConCommand fs_vpk_pack("fs_vpk_pack", VPK_Pack_f, "Pack a VPK file from current workspace", FCVAR_DEVELOPMENTONLY);
static ConCommand fs_vpk_unpack("fs_vpk_unpack", VPK_Unpack_f, "Unpack all files from a VPK file", FCVAR_DEVELOPMENTONLY);
ConCommand::StaticCreate("toggleconsole", "Show/hide the developer console.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, ToggleConsole_f, nullptr);
ConCommand::StaticCreate("togglebrowser", "Show/hide the server browser.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, ToggleBrowser_f, nullptr);
//-------------------------------------------------------------------------
// UI DLL |
ConCommand::StaticCreate("script_ui", "Run input code as UI script on the VM.", nullptr, FCVAR_CLIENTDLL | FCVAR_CHEAT, SQVM_UIScript_f, nullptr);
#endif // !DEDICATED
//-------------------------------------------------------------------------
// FILESYSTEM API |
ConCommand::StaticCreate("fs_vpk_mount", "Mount a VPK file for FileSystem usage.", nullptr, FCVAR_DEVELOPMENTONLY, VPK_Mount_f, nullptr);
ConCommand::StaticCreate("fs_vpk_unmount", "Unmount a VPK file and clear its cache.", nullptr, FCVAR_DEVELOPMENTONLY, VPK_Unmount_f, nullptr);
ConCommand::StaticCreate("fs_vpk_pack", "Pack a VPK file from current workspace.", nullptr, FCVAR_DEVELOPMENTONLY, VPK_Pack_f, nullptr);
ConCommand::StaticCreate("fs_vpk_unpack", "Unpack all files from a VPK file.", nullptr, FCVAR_DEVELOPMENTONLY, VPK_Unpack_f, nullptr);
//-------------------------------------------------------------------------
// RTECH API |
ConCommand::StaticCreate("rtech_strtoguid", "Calculates the GUID from input data.", nullptr, FCVAR_DEVELOPMENTONLY, RTech_StringToGUID_f, nullptr);
ConCommand::StaticCreate("pak_decompress", "Decompresses specified RPAK file.", nullptr, FCVAR_DEVELOPMENTONLY, RTech_Decompress_f, RTech_PakDecompress_f_CompletionFunc);
ConCommand::StaticCreate("pak_requestload", "Requests asynchronous load for specified RPAK file.", nullptr, FCVAR_DEVELOPMENTONLY, Pak_RequestLoad_f, RTech_PakLoad_f_CompletionFunc);
ConCommand::StaticCreate("pak_requestunload", "Requests unload for specified RPAK file or ID.", nullptr, FCVAR_DEVELOPMENTONLY, Pak_RequestUnload_f, RTech_PakUnload_f_CompletionFunc);
ConCommand::StaticCreate("pak_swap", "Requests swap for specified RPAK file or ID", nullptr, FCVAR_DEVELOPMENTONLY, Pak_Swap_f, nullptr);
ConCommand::StaticCreate("pak_listpaks", "Display a list of the loaded Pak files.", nullptr, FCVAR_RELEASE, Pak_ListPaks_f, nullptr);
ConCommand::StaticCreate("pak_listtypes", "Display a list of the registered asset types.", nullptr, FCVAR_RELEASE, Pak_ListTypes_f, nullptr);
//-------------------------------------------------------------------------
// NETCHANNEL |
ConCommand::StaticCreate("net_setkey", "Sets user specified base64 net key.", nullptr, FCVAR_RELEASE, NET_SetKey_f, nullptr);
ConCommand::StaticCreate("net_generatekey", "Generates and sets a random base64 net key.", nullptr, FCVAR_RELEASE, NET_GenerateKey_f, nullptr);
//-------------------------------------------------------------------------
// TIER0 |
ConCommand::StaticCreate("sig_getadr", "Logs the sigscan results to the console.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_HIDDEN, SIG_GetAdr_f, nullptr);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: shipped ConCommand initialization // Purpose: shipped ConCommand initialization

View File

@ -3,7 +3,6 @@
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// ENGINE | // ENGINE |
extern ConVar* sdk_fixedframe_tickinterval;
extern ConVar* single_frame_shutdown_for_reload; extern ConVar* single_frame_shutdown_for_reload;
extern ConVar* old_gather_props; extern ConVar* old_gather_props;
@ -12,12 +11,14 @@ extern ConVar* debug_draw_box_depth_test;
extern ConVar* developer; extern ConVar* developer;
extern ConVar* fps_max; extern ConVar* fps_max;
extern ConVar* fps_max_vsync;
// taken from S15: #ifndef DEDICATED
extern ConVar* usercmd_frametime_max; extern ConVar* in_syncRT;
extern ConVar* usercmd_frametime_min; #endif // !DEDICATED
extern ConVar* usercmd_dualwield_enable; extern ConVar* base_tickinterval_sp;
extern ConVar* base_tickinterval_mp;
extern ConVar* staticProp_no_fade_scalar; extern ConVar* staticProp_no_fade_scalar;
extern ConVar* staticProp_gather_size_weight; extern ConVar* staticProp_gather_size_weight;
@ -27,7 +28,6 @@ extern ConVar* model_defaultFadeDistMin;
extern ConVar* ip_cvar; extern ConVar* ip_cvar;
extern ConVar* hostname; extern ConVar* hostname;
extern ConVar* hostdesc;
extern ConVar* hostip; extern ConVar* hostip;
extern ConVar* hostport; extern ConVar* hostport;
@ -36,17 +36,6 @@ extern ConVar* host_timescale;
extern ConVar* mp_gamemode; extern ConVar* mp_gamemode;
extern ConVar* rcon_address;
extern ConVar* rcon_password;
extern ConVar* r_debug_overlay_nodecay;
extern ConVar* r_debug_overlay_invisible;
extern ConVar* r_debug_overlay_wireframe;
extern ConVar* r_debug_draw_depth_test;
extern ConVar* r_drawWorldMeshes;
extern ConVar* r_drawWorldMeshesDepthOnly;
extern ConVar* r_drawWorldMeshesDepthAtTheEnd;
#ifndef DEDICATED #ifndef DEDICATED
extern ConVar* r_visualizetraces; extern ConVar* r_visualizetraces;
extern ConVar* r_visualizetraces_duration; extern ConVar* r_visualizetraces_duration;
@ -56,202 +45,80 @@ extern ConVar* stream_overlay;
extern ConVar* stream_overlay_mode; extern ConVar* stream_overlay_mode;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// SHARED | // SHARED |
extern ConVar* modsystem_enable; extern ConVar* eula_version;
extern ConVar* modsystem_debug; extern ConVar* eula_version_accepted;
extern ConVar* language_cvar;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// SERVER | // SERVER |
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
extern ConVar* ai_ainDumpOnLoad;
extern ConVar* ai_ainDebugConnect;
extern ConVar* ai_script_nodes_draw; extern ConVar* ai_script_nodes_draw;
extern ConVar* ai_script_nodes_draw_range;
extern ConVar* ai_script_nodes_draw_nearest;
extern ConVar* navmesh_always_reachable;
extern ConVar* navmesh_debug_type;
extern ConVar* navmesh_debug_tile_range;
extern ConVar* navmesh_debug_camera_range;
#ifndef DEDICATED
extern ConVar* navmesh_draw_bvtree;
extern ConVar* navmesh_draw_portal;
extern ConVar* navmesh_draw_polys;
extern ConVar* navmesh_draw_poly_bounds;
extern ConVar* navmesh_draw_poly_bounds_inner;
#endif // DEDICATED
extern ConVar* sv_language;
extern ConVar* sv_showconnecting;
extern ConVar* sv_globalBanlist;
extern ConVar* sv_pylonVisibility;
extern ConVar* sv_pylonRefreshRate;
extern ConVar* sv_banlistRefreshRate;
extern ConVar* sv_statusRefreshRate;
extern ConVar* sv_forceChatToTeamOnly; extern ConVar* sv_forceChatToTeamOnly;
extern ConVar* sv_single_core_dedi; extern ConVar* sv_single_core_dedi;
extern ConVar* sv_updaterate_mp; extern ConVar* sv_maxunlag;
extern ConVar* sv_updaterate_sp; extern ConVar* sv_clockcorrection_msecs;
extern ConVar* sv_autoReloadRate;
extern ConVar* sv_updaterate_sp;
extern ConVar* sv_updaterate_mp;
extern ConVar* sv_simulateBots;
extern ConVar* sv_showhitboxes; extern ConVar* sv_showhitboxes;
extern ConVar* sv_stats; extern ConVar* sv_stats;
extern ConVar* sv_quota_stringCmdsPerSecond;
extern ConVar* sv_validatePersonaName;
extern ConVar* sv_minPersonaNameLength;
extern ConVar* sv_maxPersonaNameLength;
extern ConVar* sv_voiceEcho; extern ConVar* sv_voiceEcho;
extern ConVar* sv_voiceenable; extern ConVar* sv_voiceenable;
extern ConVar* sv_alltalk; extern ConVar* sv_alltalk;
extern ConVar* player_userCmdsQueueWarning; extern ConVar* player_userCmdsQueueWarning;
//#ifdef DEDICATED
extern ConVar* sv_rcon_debug;
extern ConVar* sv_rcon_sendlogs;
//extern ConVar* sv_rcon_banpenalty;
extern ConVar* sv_rcon_maxfailures;
extern ConVar* sv_rcon_maxignores;
extern ConVar* sv_rcon_maxsockets;
extern ConVar* sv_rcon_maxconnections;
extern ConVar* sv_rcon_maxpacketsize;
extern ConVar* sv_rcon_whitelist_address;
//#endif // DEDICATED
#endif // CLIENT_DLL #endif // CLIENT_DLL
extern ConVar* sv_cheats; extern ConVar* sv_cheats;
extern ConVar* sv_visualizetraces; extern ConVar* sv_visualizetraces;
extern ConVar* sv_visualizetraces_duration; extern ConVar* sv_visualizetraces_duration;
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1)
extern ConVar* bhit_enable; extern ConVar* bhit_enable;
extern ConVar* bhit_depth_test;
extern ConVar* bhit_abs_origin;
#endif // !GAMEDLL_S0 && !GAMEDLL_S1
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// CLIENT | // CLIENT |
#ifndef DEDICATED #ifndef DEDICATED
extern ConVar* cl_rcon_inputonly;
extern ConVar* cl_quota_stringCmdsPerSecond;
extern ConVar* cl_cmdrate;
extern ConVar* cl_move_use_dt;
extern ConVar* cl_notify_invert_x;
extern ConVar* cl_notify_invert_y;
extern ConVar* cl_notify_offset_x;
extern ConVar* cl_notify_offset_y;
extern ConVar* cl_showsimstats;
extern ConVar* cl_simstats_invert_x;
extern ConVar* cl_simstats_invert_y;
extern ConVar* cl_simstats_offset_x;
extern ConVar* cl_simstats_offset_y;
extern ConVar* cl_showgpustats;
extern ConVar* cl_gpustats_invert_x;
extern ConVar* cl_gpustats_invert_y;
extern ConVar* cl_gpustats_offset_x;
extern ConVar* cl_gpustats_offset_y;
extern ConVar* cl_showmaterialinfo;
extern ConVar* cl_materialinfo_offset_x;
extern ConVar* cl_materialinfo_offset_y;
extern ConVar* cl_threaded_bone_setup; extern ConVar* cl_threaded_bone_setup;
extern ConVar* con_drawnotify;
extern ConVar* con_notifylines;
extern ConVar* con_notifytime;
extern ConVar* con_notify_invert_x;
extern ConVar* con_notify_invert_y;
extern ConVar* con_notify_offset_x;
extern ConVar* con_notify_offset_y;
extern ConVar* con_notify_script_server_clr;
extern ConVar* con_notify_script_client_clr;
extern ConVar* con_notify_script_ui_clr;
extern ConVar* con_notify_native_server_clr;
extern ConVar* con_notify_native_client_clr;
extern ConVar* con_notify_native_ui_clr;
extern ConVar* con_notify_native_engine_clr;
extern ConVar* con_notify_native_fs_clr;
extern ConVar* con_notify_native_rtech_clr;
extern ConVar* con_notify_native_ms_clr;
extern ConVar* con_notify_native_audio_clr;
extern ConVar* con_notify_native_video_clr;
extern ConVar* con_notify_netcon_clr;
extern ConVar* con_notify_common_clr;
extern ConVar* con_notify_warning_clr;
extern ConVar* con_notify_error_clr;
extern ConVar* con_max_lines;
extern ConVar* con_max_history;
extern ConVar* con_suggest_limit;
extern ConVar* con_suggest_showhelptext;
extern ConVar* con_suggest_showflags;
extern ConVar* origin_disconnectWhenOffline; extern ConVar* origin_disconnectWhenOffline;
extern ConVar* discord_updatePresence; extern ConVar* discord_updatePresence;
#endif // !DEDICATED #endif // !DEDICATED
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// FILESYSTEM | // FILESYSTEM |
extern ConVar* fs_showWarnings;
extern ConVar* fs_showAllReads; extern ConVar* fs_showAllReads;
extern ConVar* fs_packedstore_entryblock_stats;
extern ConVar* fs_packedstore_workspace;
extern ConVar* fs_packedstore_compression_level;
extern ConVar* fs_packedstore_max_helper_threads;
//-------------------------------------------------------------------------
// MATERIALSYSTEM |
#ifndef DEDICATED
extern ConVar* mat_alwaysComplain;
#endif // !DEDICATED
//-------------------------------------------------------------------------
// SQUIRREL |
extern ConVar* script_show_output;
extern ConVar* script_show_warning;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// NETCHANNEL | // NETCHANNEL |
extern ConVar* net_tracePayload;
extern ConVar* net_encryptionEnable;
extern ConVar* net_useRandomKey;
extern ConVar* net_usesocketsforloopback; extern ConVar* net_usesocketsforloopback;
extern ConVar* net_processTimeBudget;
extern ConVar* net_data_block_enabled;
extern ConVar* net_datablock_networkLossForSlowSpeed; extern ConVar* net_datablock_networkLossForSlowSpeed;
extern ConVar* net_compressDataBlock;
extern ConVar* pylon_matchmaking_hostname; extern ConVar* net_showmsg;
extern ConVar* pylon_host_update_interval; extern ConVar* net_blockmsg;
extern ConVar* pylon_showdebuginfo; extern ConVar* net_showpeaks;
extern ConVar* ssl_verify_peer; extern ConVar ssl_verify_peer;
extern ConVar* curl_timeout; extern ConVar curl_timeout;
extern ConVar* curl_debug; extern ConVar curl_debug;
//-------------------------------------------------------------------------
// RTECH API |
extern ConVar* rtech_debug;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUI | // RUI |
#ifndef DEDICATED #ifndef DEDICATED
extern ConVar* rui_drawEnable;
extern ConVar* rui_defaultDebugFontFace; extern ConVar* rui_defaultDebugFontFace;
#endif // !DEDICATED #endif // !DEDICATED
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// MILES | // MILES |
#ifndef DEDICATED #ifndef DEDICATED
extern ConVar* miles_debug;
extern ConVar* miles_language; extern ConVar* miles_language;
#endif #endif
void ConVar_StaticInit(void);
void ConVar_InitShipped(void); void ConVar_InitShipped(void);
void ConVar_PurgeShipped(void); void ConVar_PurgeShipped(void);
void ConVar_PurgeHostNames(void); void ConVar_PurgeHostNames(void);
void ConCommand_StaticInit(void);
void ConCommand_InitShipped(void); void ConCommand_InitShipped(void);
void ConCommand_PurgeShipped(void); void ConCommand_PurgeShipped(void);

View File

@ -28,7 +28,7 @@ bool SVC_Print::ProcessImpl()
if (len < sizeof(m_szTextBuffer)) if (len < sizeof(m_szTextBuffer))
{ {
DevMsg(eDLL_T::SERVER, m_szText[len-1] == '\n' ? "%s" : "%s\n", m_szText); Msg(eDLL_T::SERVER, m_szText[len-1] == '\n' ? "%s" : "%s\n", m_szText);
} }
} }
@ -56,7 +56,7 @@ bool SVC_UserMessage::ProcessImpl()
if (len && len < sizeof(text)) if (len && len < sizeof(text))
{ {
DevMsg(eDLL_T::SERVER, text[len - 1] == '\n' ? "%s" : "%s\n", text); Msg(eDLL_T::SERVER, text[len - 1] == '\n' ? "%s" : "%s\n", text);
} }
} }
} }
@ -90,6 +90,7 @@ bool CLC_SetPlaylistVarOverride::WriteToBufferImpl(CLC_SetPlaylistVarOverride* t
return CLC_SetPlaylistVarOverride_WriteToBuffer(thisptr, buffer); return CLC_SetPlaylistVarOverride_WriteToBuffer(thisptr, buffer);
} }
static ConVar enable_CmdKeyValues("enable_CmdKeyValues", "0", FCVAR_DEVELOPMENTONLY, "Toggle CmdKeyValues transmit and receive.");
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
// below functions are hooked as 'CmdKeyValues' isn't really used in this game, but // below functions are hooked as 'CmdKeyValues' isn't really used in this game, but
@ -98,8 +99,8 @@ bool CLC_SetPlaylistVarOverride::WriteToBufferImpl(CLC_SetPlaylistVarOverride* t
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
bool Base_CmdKeyValues::ReadFromBufferImpl(Base_CmdKeyValues* thisptr, bf_read* buffer) bool Base_CmdKeyValues::ReadFromBufferImpl(Base_CmdKeyValues* thisptr, bf_read* buffer)
{ {
// Abusable netmsg; only allow if cheats are enabled. // Abusable netmsg; only allow if explicitly enabled by the client.
if (!sv_cheats->GetBool()) if (!enable_CmdKeyValues.GetBool())
{ {
return false; return false;
} }
@ -108,8 +109,8 @@ bool Base_CmdKeyValues::ReadFromBufferImpl(Base_CmdKeyValues* thisptr, bf_read*
} }
bool Base_CmdKeyValues::WriteToBufferImpl(Base_CmdKeyValues* thisptr, bf_write* buffer) bool Base_CmdKeyValues::WriteToBufferImpl(Base_CmdKeyValues* thisptr, bf_write* buffer)
{ {
// Abusable netmsg; only allow if cheats are enabled. // Abusable netmsg; only allow if explicitly enabled by the client.
if (!sv_cheats->GetBool()) if (!enable_CmdKeyValues.GetBool())
{ {
return false; return false;
} }
@ -160,26 +161,28 @@ bool ShouldReplayMessage(const CNetMessage* msg)
} }
} }
void V_NetMessages::Attach() const void V_NetMessages::Detour(const bool bAttach) const
{ {
auto hk_SVCPrint_Process = &SVC_Print::ProcessImpl; if (bAttach)
auto hk_SVCUserMessage_Process = &SVC_UserMessage::ProcessImpl; {
auto hk_SVCPrint_Process = &SVC_Print::ProcessImpl;
auto hk_SVCUserMessage_Process = &SVC_UserMessage::ProcessImpl;
CMemory::HookVirtualMethod((uintptr_t)g_pSVC_Print_VFTable, (LPVOID&)hk_SVCPrint_Process, NetMessageVtbl::Process, (LPVOID*)&SVC_Print_Process); CMemory::HookVirtualMethod((uintptr_t)g_pSVC_Print_VFTable, (LPVOID&)hk_SVCPrint_Process, NetMessageVtbl::Process, (LPVOID*)&SVC_Print_Process);
CMemory::HookVirtualMethod((uintptr_t)g_pSVC_UserMessage_VFTable, (LPVOID&)hk_SVCUserMessage_Process, NetMessageVtbl::Process, (LPVOID*)&SVC_UserMessage_Process); CMemory::HookVirtualMethod((uintptr_t)g_pSVC_UserMessage_VFTable, (LPVOID&)hk_SVCUserMessage_Process, NetMessageVtbl::Process, (LPVOID*)&SVC_UserMessage_Process);
CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID*)&Base_CmdKeyValues::ReadFromBufferImpl, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&Base_CmdKeyValues_ReadFromBuffer); CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID*)&Base_CmdKeyValues::ReadFromBufferImpl, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&Base_CmdKeyValues_ReadFromBuffer);
CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID*)&Base_CmdKeyValues::WriteToBufferImpl, NetMessageVtbl::WriteToBuffer, (LPVOID*)&Base_CmdKeyValues_WriteToBuffer); CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID*)&Base_CmdKeyValues::WriteToBufferImpl, NetMessageVtbl::WriteToBuffer, (LPVOID*)&Base_CmdKeyValues_WriteToBuffer);
CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID*)&CLC_SetPlaylistVarOverride::ReadFromBufferImpl, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&CLC_SetPlaylistVarOverride_ReadFromBuffer); CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID*)&CLC_SetPlaylistVarOverride::ReadFromBufferImpl, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&CLC_SetPlaylistVarOverride_ReadFromBuffer);
CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID*)&CLC_SetPlaylistVarOverride::WriteToBufferImpl, NetMessageVtbl::WriteToBuffer, (LPVOID*)&CLC_SetPlaylistVarOverride_WriteToBuffer); CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID*)&CLC_SetPlaylistVarOverride::WriteToBufferImpl, NetMessageVtbl::WriteToBuffer, (LPVOID*)&CLC_SetPlaylistVarOverride_WriteToBuffer);
} }
else
void V_NetMessages::Detach() const {
{ void* hkRestore = nullptr;
void* hkRestore = nullptr; CMemory::HookVirtualMethod((uintptr_t)g_pSVC_Print_VFTable, (LPVOID)SVC_Print_Process, NetMessageVtbl::Process, (LPVOID*)&hkRestore);
CMemory::HookVirtualMethod((uintptr_t)g_pSVC_Print_VFTable, (LPVOID)SVC_Print_Process, NetMessageVtbl::Process, (LPVOID*)&hkRestore); CMemory::HookVirtualMethod((uintptr_t)g_pSVC_UserMessage_VFTable, (LPVOID)SVC_UserMessage_Process, NetMessageVtbl::Process, (LPVOID*)&hkRestore);
CMemory::HookVirtualMethod((uintptr_t)g_pSVC_UserMessage_VFTable, (LPVOID)SVC_UserMessage_Process, NetMessageVtbl::Process, (LPVOID*)&hkRestore); CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID)Base_CmdKeyValues_ReadFromBuffer, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&hkRestore);
CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID)Base_CmdKeyValues_ReadFromBuffer, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&hkRestore); CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID)Base_CmdKeyValues_WriteToBuffer, NetMessageVtbl::WriteToBuffer, (LPVOID*)&hkRestore);
CMemory::HookVirtualMethod((uintptr_t)g_pBase_CmdKeyValues_VFTable, (LPVOID)Base_CmdKeyValues_WriteToBuffer, NetMessageVtbl::WriteToBuffer, (LPVOID*)&hkRestore); CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID)CLC_SetPlaylistVarOverride_ReadFromBuffer, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&hkRestore);
CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID)CLC_SetPlaylistVarOverride_ReadFromBuffer, NetMessageVtbl::ReadFromBuffer, (LPVOID*)&hkRestore); CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID)CLC_SetPlaylistVarOverride_WriteToBuffer, NetMessageVtbl::WriteToBuffer, (LPVOID*)&hkRestore);
CMemory::HookVirtualMethod((uintptr_t)g_pCLC_SetPlaylistVarOverride_VFTable, (LPVOID)CLC_SetPlaylistVarOverride_WriteToBuffer, NetMessageVtbl::WriteToBuffer, (LPVOID*)&hkRestore); }
} }

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "tier1/bitbuf.h" #include "tier1/bitbuf.h"
#include "common/qlimits.h"
#include "public/inetchannel.h" #include "public/inetchannel.h"
#include "public/inetmessage.h" #include "public/inetmessage.h"
#include "public/inetmsghandler.h" #include "public/inetmsghandler.h"
@ -184,6 +185,24 @@ public:
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
// server messages: // server messages:
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
class SVC_CreateStringTable : public CNetMessage
{
public:
const char* m_szTableName;
int m_nMaxEntries;
int m_nNumEntries;
char m_bUserDataFixedSize;
char _padding0[3];
int m_nUserDataSize;
int m_nUserDataSizeBits;
int m_nDictFlags;
int m_nLength;
bf_read m_DataIn;
bf_write m_DataOut;
char m_bDataCompressed;
char m_szTableNameBuffer[260];
};
class SVC_Print : public CNetMessage class SVC_Print : public CNetMessage
{ {
public: public:
@ -362,6 +381,10 @@ private:
bf_write m_DataOut; bf_write m_DataOut;
}; };
///////////////////////////////////////////////////////////////////////////////////////
// Client messages:
///////////////////////////////////////////////////////////////////////////////////////
class CLC_ClientTick : public CNetMessage class CLC_ClientTick : public CNetMessage
{ {
public: public:
@ -427,7 +450,7 @@ private:
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
// Client messages: // Shared messages:
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
struct NET_StringCmd : CNetMessage struct NET_StringCmd : CNetMessage
@ -436,6 +459,19 @@ struct NET_StringCmd : CNetMessage
char buffer[1024]; char buffer[1024];
}; };
class NET_SetConVar : public CNetMessage
{
public:
typedef struct cvar_s
{
char name[MAX_OSPATH];
char value[MAX_OSPATH];
} cvar_t;
CUtlVector<cvar_t> m_ConVars;
};
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
// This message is subclassed by 'SVC_CmdKeyValues' and 'CLC_CmdKeyValues' // This message is subclassed by 'SVC_CmdKeyValues' and 'CLC_CmdKeyValues'
class Base_CmdKeyValues : public CNetMessage class Base_CmdKeyValues : public CNetMessage
@ -476,15 +512,15 @@ class V_NetMessages : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogConAdr("SVC_Print::`vftable'", reinterpret_cast<uintptr_t>(g_pSVC_Print_VFTable)); LogConAdr("SVC_Print::`vftable'", g_pSVC_Print_VFTable);
LogConAdr("SVC_UserMessage::`vftable'", reinterpret_cast<uintptr_t>(g_pSVC_UserMessage_VFTable)); LogConAdr("SVC_UserMessage::`vftable'", g_pSVC_UserMessage_VFTable);
LogConAdr("SVC_ServerTick::`vftable'", reinterpret_cast<uintptr_t>(g_pSVC_ServerTick_VFTable)); LogConAdr("SVC_ServerTick::`vftable'", g_pSVC_ServerTick_VFTable);
LogConAdr("SVC_VoiceData::`vftable'", reinterpret_cast<uintptr_t>(g_pSVC_VoiceData_VFTable)); LogConAdr("SVC_VoiceData::`vftable'", g_pSVC_VoiceData_VFTable);
LogConAdr("SVC_PlaylistOverrides::`vftable'", reinterpret_cast<uintptr_t>(g_pSVC_PlaylistOverrides_VFTable)); LogConAdr("SVC_PlaylistOverrides::`vftable'", g_pSVC_PlaylistOverrides_VFTable);
LogConAdr("CLC_ClientTick::`vftable'", reinterpret_cast<uintptr_t>(g_pCLC_ClientTick_VFTable)); LogConAdr("CLC_ClientTick::`vftable'", g_pCLC_ClientTick_VFTable);
LogConAdr("CLC_SetPlaylistVarOverride::`vftable'", reinterpret_cast<uintptr_t>(g_pCLC_SetPlaylistVarOverride_VFTable)); LogConAdr("CLC_SetPlaylistVarOverride::`vftable'", g_pCLC_SetPlaylistVarOverride_VFTable);
LogConAdr("Base_CmdKeyValues::`vftable'", reinterpret_cast<uintptr_t>(g_pBase_CmdKeyValues_VFTable)); LogConAdr("Base_CmdKeyValues::`vftable'", g_pBase_CmdKeyValues_VFTable);
//LogFunAdr("MM_Heartbeat::ToString", MM_Heartbeat__ToString.GetPtr()); //LogFunAdr("MM_Heartbeat::ToString", MM_Heartbeat__ToString);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
@ -504,8 +540,7 @@ class V_NetMessages : public IDetour
g_pCLC_SetPlaylistVarOverride_VFTable = g_GameDll.GetVirtualMethodTable(".?AVCLC_SetPlaylistVarOverride@@"); g_pCLC_SetPlaylistVarOverride_VFTable = g_GameDll.GetVirtualMethodTable(".?AVCLC_SetPlaylistVarOverride@@");
g_pBase_CmdKeyValues_VFTable = g_GameDll.GetVirtualMethodTable(".?AVBase_CmdKeyValues@@"); g_pBase_CmdKeyValues_VFTable = g_GameDll.GetVirtualMethodTable(".?AVBase_CmdKeyValues@@");
} }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -23,7 +23,6 @@
#include "game/server/ai_networkmanager.h" #include "game/server/ai_networkmanager.h"
#include "game/server/detour_impl.h" #include "game/server/detour_impl.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
#include "rtech/rtech_game.h"
//#include "rtech/rui/rui.h" //#include "rtech/rui/rui.h"
//#include "materialsystem/cmaterialsystem.h" //#include "materialsystem/cmaterialsystem.h"
//#include "studiorender/studiorendercontext.h" //#include "studiorender/studiorendercontext.h"
@ -345,47 +344,9 @@ void RuntimePtc_Init() /* .TEXT */
#ifndef DEDICATED #ifndef DEDICATED
p_WASAPI_GetAudioDevice.Offset(0x410).FindPatternSelf("FF 15 ?? ?? 01 00", CMemory::Direction::DOWN, 100).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xEB }); // CAL --> NOP | Disable debugger check when miles searches for audio device to allow attaching the debugger to the game upon launch. p_WASAPI_GetAudioDevice.Offset(0x410).FindPatternSelf("FF 15 ?? ?? 01 00", CMemory::Direction::DOWN, 100).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xEB }); // CAL --> NOP | Disable debugger check when miles searches for audio device to allow attaching the debugger to the game upon launch.
p_SQVM_CompileError.Offset(0x0).FindPatternSelf("41 B0 01", CMemory::Direction::DOWN, 400).Patch({ 0x41, 0xB0, 0x00 }); // MOV --> MOV | Set script error level to 0 (not severe): 'mov r8b, 0'. CMemory(v_SQVM_CompileError).Offset(0x0).FindPatternSelf("41 B0 01", CMemory::Direction::DOWN, 400).Patch({ 0x41, 0xB0, 0x00 }); // MOV --> MOV | Set script error level to 0 (not severe): 'mov r8b, 0'.
p_SQVM_CompileError.Offset(0xE0).FindPatternSelf("E8", CMemory::Direction::DOWN, 200).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 }); // CAL --> NOP | TODO: causes errors on client script error. Research required (same function as soft error but that one doesn't crash). CMemory(v_SQVM_CompileError).Offset(0xE0).FindPatternSelf("E8", CMemory::Direction::DOWN, 200).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 }); // CAL --> NOP | TODO: causes errors on client script error. Research required (same function as soft error but that one doesn't crash).
#else #else
p_SQVM_CompileError.Offset(0xE0).FindPatternSelf("E8", CMemory::Direction::DOWN, 200).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 }); // CAL --> NOP | For dedicated we should not perform post-error events such as telemetry / showing 'COM_ExplainDisconnection' UI etc. CMemory(v_SQVM_CompileError).Offset(0xE0).FindPatternSelf("E8", CMemory::Direction::DOWN, 200).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 }); // CAL --> NOP | For dedicated we should not perform post-error events such as telemetry / showing 'COM_ExplainDisconnection' UI etc.
#endif // !DEDICATED #endif // !DEDICATED
#if defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
#ifndef CLIENT_DLL
//p_CAI_NetworkManager__ShouldRebuild.Offset(0xA0).FindPatternSelf("FF ?? ?? ?? 00 00", CMemory::Direction::DOWN, 200).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }); // CAL --> NOP | Virtual call to restart when building AIN (which clears the AIN memory). Remove this once writing to file works.
//p_Detour_LevelInit.Offset(0x100).FindPatternSelf("74", CMemory::Direction::DOWN, 600).Patch({ 0xEB }); // JE --> JMP | Do while loop setting fields to -1 in navmesh is writing out of bounds (!TODO).
#endif // !CLIENT_DLL
#endif
#ifndef CLIENT_DLL
// !!!TODO!!! HACK: this needs to be removed asap! fix the entitlements file formatting on git itself.
Server_S2C_CONNECT_1.Offset(0x7).Patch({ 0xEB }); // JZ --> JMP | Prevent entitlement check to kick player from server on S2C_CONNECT Packet if it does not match the servers one.
#endif // !CLIENT_DLL
vector<uint8_t> starPakOpenFile = {
0x4D, 0x31, 0xC0, // xor, r8, r8
0x48, 0x8D, 0x8C, 0x24, 0x90, 0x00, 0x00, 0x00, // lea rcx, [rsp+378h+90h] FileName
// call RTech::OpenFile [RIP+RVA]
#if defined (GAMEDLL_S0)
0xE8, 0x87, 0x96, 0xFF, 0xFF,
#elif defined (GAMEDLL_S1)
0xE8, 0x27, 0x95, 0xFF, 0xFF,
#elif defined (GAMEDLL_S2)
0xE8, 0x87, 0x95, 0xFF, 0xFF,
#elif defined (GAMEDLL_S3)
0xE8, 0x77, 0x8F, 0xFF, 0xFF,
#endif
0x8B, 0xF8, // mov edi, eax
// jmp [RIP+RVA]
#if defined (GAMEDLL_S0) || defined(GAMEDLL_S1)
0xE9, 0xDC, 0x00, 0x00, 0x00
#elif defined (GAMEDLL_S2) || defined(GAMEDLL_S3)
0xE9, 0xDA, 0x00, 0x00, 0x00
#endif
};
p_CPakFile_OpenFileOffset.Patch(starPakOpenFile);
} }

View File

@ -58,13 +58,6 @@ inline CMemory Host_Shutdown;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
inline CMemory Host_Disconnect; inline CMemory Host_Disconnect;
//-------------------------------------------------------------------------
// RUNTIME: S2C_CHALLENGE
//-------------------------------------------------------------------------
#ifndef CLIENT_DLL
inline CMemory Server_S2C_CONNECT_1;
#endif // !CLIENT_DLL
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: // RUNTIME:
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -88,9 +81,6 @@ class VOpcodes : public IDetour
// LogFunAdr("Sys_InitGame", Sys_InitGame.GetPtr()); // LogFunAdr("Sys_InitGame", Sys_InitGame.GetPtr());
// LogFunAdr("Host_Init_1", gHost_Init_1.GetPtr()); // LogFunAdr("Host_Init_1", gHost_Init_1.GetPtr());
// LogFunAdr("Host_Init_2", gHost_Init_2.GetPtr()); // LogFunAdr("Host_Init_2", gHost_Init_2.GetPtr());
#ifndef CLIENT_DLL
LogFunAdr("Server_S2C_CONNECT", Server_S2C_CONNECT_1.GetPtr());
#endif // !CLIENT_DLL
// LogFunAdr("GetEngineClientThread", GetEngineClientThread.GetPtr()); // LogFunAdr("GetEngineClientThread", GetEngineClientThread.GetPtr());
// LogFunAdr("MatchMaking_Frame", MatchMaking_Frame.GetPtr()); // LogFunAdr("MatchMaking_Frame", MatchMaking_Frame.GetPtr());
//#if !defined (GAMEDLL_S0) || !defined (GAMEDLL_S1) //#if !defined (GAMEDLL_S0) || !defined (GAMEDLL_S1)
@ -148,9 +138,6 @@ class VOpcodes : public IDetour
// // 0x140236640 // 88 4C 24 08 53 55 56 57 48 83 EC 68 // // // 0x140236640 // 88 4C 24 08 53 55 56 57 48 83 EC 68 //
// //
// //------------------------------------------------------------------------- // //-------------------------------------------------------------------------
#ifndef CLIENT_DLL
Server_S2C_CONNECT_1 = g_GameDll.FindPatternSIMD("48 3B 05 ?? ?? ?? ?? 74 0C");
#endif // !CLIENT_DLL
// //
// //------------------------------------------------------------------------- // //-------------------------------------------------------------------------
//#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) //#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
@ -174,7 +161,6 @@ class VOpcodes : public IDetour
//#endif //48 83 EC 28 33 C9 FF 15 ? ? ? ? 48 8D 0D ? ? ? ? //#endif //48 83 EC 28 33 C9 FF 15 ? ? ? ? 48 8D 0D ? ? ? ?
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

45
r5dev/common/proto_oob.h Normal file
View File

@ -0,0 +1,45 @@
//============ Copyright Valve Corporation, All rights reserved. ==============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined( PROTO_OOB_H )
#define PROTO_OOB_H
#ifdef _WIN32
#pragma once
#endif
#include "proto_version.h"
#define PORT_RCON 37015 // default RCON port, TCP
#define PORT_SERVER 37015 // Default server port, UDP/TCP
#define PORT_CLIENT 37005 // Default client port, UDP/TCP
// Out of band message id bytes
// Prefixes: S = server, C = client, A = any
#define C2S_CONNECT 'A' // client requests to connect
#define S2C_DISCONNECT 'B' // server requests to disconnect
#define C2S_CHALLENGE 'H' // + challenge value
#define S2C_CHALLENGE 'I' // + challenge value
#define S2C_CONNACCEPT 'J'
#define S2C_CONNREJECT 'K' // special protocol for rejected connections
// Generic Ping Request
#define A2A_PING 'L' // respond with an A2A_ACK
#define A2A_ACK 'M' // general acknowledgment without info
#define S2C_UNKNOWN_UISCRIPT 'N' // TODO: figure out what this does, see [r5apex + 0x288880]
// Data Block Request
#define S2C_DATABLOCK_FRAGMENT 'O' // data block fragment
#define C2S_DATABLOCK_ACK 'P' // data block fragment acknowledgment
// All OOB packet start with this sequence
#define CONNECTIONLESS_HEADER 0xFFFFFFFF
#endif

View File

@ -0,0 +1,17 @@
//============ Copyright Valve Corporation, All rights reserved. ==============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined( PROTO_VERSION_H )
#define PROTO_VERSION_H
#ifdef _WIN32
#pragma once
#endif
// The current network protocol version. Changing this makes clients and servers incompatible
#define PROTOCOL_VERSION 529
#endif

View File

@ -4,13 +4,20 @@
* _protocol.h * _protocol.h
*-----------------------------------------------------------------------------*/ *-----------------------------------------------------------------------------*/
// Largest # of commands to send in a packet
#define NUM_NEW_COMMAND_BITS 4
#define MAX_NEW_COMMANDS ((1 << NUM_NEW_COMMAND_BITS)-1)
// Max number of history commands to send ( 2 by default ) in case of dropped packets // Max number of history commands to send ( 2 by default ) in case of dropped packets
#define NUM_BACKUP_COMMAND_BITS 4 // Originally 3 bits. #define NUM_BACKUP_COMMAND_BITS 3
#define MAX_BACKUP_COMMANDS ((1 << NUM_BACKUP_COMMAND_BITS)-1) // 15 in R5; see 'CL_Move'. #define MAX_BACKUP_COMMANDS ((1 << NUM_BACKUP_COMMAND_BITS)-1)
// Maximum amount of backup commands to process on the server. // Maximum amount of backup commands to process on the server.
#define MAX_BACKUP_COMMANDS_PROCESS (MAX_BACKUP_COMMANDS+1) * NUM_BACKUP_COMMAND_BITS #define MAX_BACKUP_COMMANDS_PROCESS 64
#define MAX_QUEUED_COMMANDS_PROCESS 0x1B0 #define MAX_QUEUED_COMMANDS_PROCESS 432
// The size of the snapshot scratch buffer, which also applies to data block packets
#define SNAPSHOT_SCRATCH_BUFFER_SIZE 786432
enum class SIGNONSTATE : int enum class SIGNONSTATE : int
{ {
@ -31,9 +38,17 @@ enum class PERSISTENCE : int
PERSISTENCE_NONE = 0, // no persistence data for this client yet. PERSISTENCE_NONE = 0, // no persistence data for this client yet.
PERSISTENCE_PENDING = 1, // pending or processing persistence data. PERSISTENCE_PENDING = 1, // pending or processing persistence data.
PERSISTENCE_AVAILABLE = 2, // persistence is available for this client. PERSISTENCE_AVAILABLE = 2, // persistence is available for this client.
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2)
PERSISTENCE_READY = 3 // persistence is ready for this client.
#else
PERSISTENCE_READY = 5 // persistence is ready for this client. PERSISTENCE_READY = 5 // persistence is ready for this client.
#endif
}; };
#define net_NOP 0 // nop command used for padding.
#define net_Disconnect 1 // disconnect, last message in connection.
// each channel packet has 1 byte of FLAG bits
#define PACKET_FLAG_RELIABLE (1<<0) // packet contains subchannel stream data
#define PACKET_FLAG_COMPRESSED (1<<1) // packet is compressed
#define PACKET_FLAG_ENCRYPTED (1<<2) // packet is encrypted
#define PACKET_FLAG_SPLIT (1<<3) // packet is split
#define PACKET_FLAG_CHOKED (1<<4) // packet was choked by sender
#define PACKET_FLAG_PRESCALED (1<<5) // packet was sent by sender with prescaled frame time
#define PACKET_FLAG_LOOPBACK (1<<6) // packet was sent from loopback connection

View File

@ -21,6 +21,27 @@ typedef uintptr_t uintp;
typedef intptr_t intp; typedef intptr_t intp;
typedef const unsigned char* rsig_t; typedef const unsigned char* rsig_t;
// 32bit and 64bit wide boolean type
typedef int32_t b32;
typedef int64_t b64;
// signed size types
typedef std::make_signed_t<std::size_t> ssize_t; typedef std::make_signed_t<std::size_t> ssize_t;
#ifndef SSIZE_MAX
#ifdef _WIN64
#define SSIZE_MAX 9223372036854775807i64
#define SSIZE_MIN (-9223372036854775807i64 - 1)
#else
#define SSIZE_MAX 2147483647
#define SSIZE_MIN (-2147483647 - 1)
#endif
#endif
// unsigned size types
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t) -1)
#endif
#endif // SDKDEFS_H #endif // SDKDEFS_H

View File

@ -0,0 +1,52 @@
//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============
//
// Purpose: Win32 replacements for XBox.
//
//=============================================================================
#if !defined( XBOXSTUBS_H ) && !defined( _X360 )
#define XBOXSTUBS_H
typedef enum
{
XK_BUTTON_UP,
XK_BUTTON_DOWN,
XK_BUTTON_LEFT,
XK_BUTTON_RIGHT,
XK_BUTTON_START,
XK_BUTTON_BACK,
XK_BUTTON_STICK1,
XK_BUTTON_STICK2,
XK_BUTTON_A,
XK_BUTTON_B,
XK_BUTTON_X,
XK_BUTTON_Y,
XK_BUTTON_LEFT_SHOULDER,
XK_BUTTON_RIGHT_SHOULDER,
XK_XBUTTON_LTRIGGER_PARTIAL,
XK_XBUTTON_LTRIGGER_FULL,
XK_XBUTTON_RTRIGGER_PARTIAL,
XK_XBUTTON_RTRIGGER_FULL,
XK_STICK1_UP,
XK_STICK1_DOWN,
XK_STICK1_LEFT,
XK_STICK1_RIGHT,
XK_STICK2_UP,
XK_STICK2_DOWN,
XK_STICK2_LEFT,
XK_STICK2_RIGHT,
XK_UP_DOWN,
XK_LEFT_RIGHT,
XK_MAX_KEYS,
} xKey_t;
#endif // XBOXSTUBS_H

View File

@ -41,6 +41,8 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
"wldap32.lib" "wldap32.lib"
"ws2_32.lib" "ws2_32.lib"
"Rpcrt4.lib" "Rpcrt4.lib"
"iphlpapi.lib"
"Winmm.lib"
"vpc" "vpc"
"memoverride" "memoverride"
@ -56,26 +58,35 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
"vphysics" "vphysics"
"SigCache_Pb" "SigCache_Pb"
"LiveAPI_Pb"
"SV_RCon_Pb" "SV_RCon_Pb"
"CL_RCon_Pb" "CL_RCon_Pb"
"rtech_tools" "rson"
"rtech_game" "rtech_game"
"playlists"
"stryder" "stryder"
"libdetours"
"liblzham" "liblzham"
"libzstd"
"liblz4"
"libdetours"
"libcurl" "libcurl"
"libprotobuf" "libprotobuf"
"libspdlog" "libspdlog"
"libdetour" "libdetour"
"navdebugutils" "navdebugutils"
"EAThread"
"DirtySDK"
"networksystem" "networksystem"
"pluginsystem" "pluginsystem"
"filesystem" "filesystem"
"datacache" "datacache"
"EbisuSDK" "EbisuSDK"
"GFSDK"
"localize" "localize"
@ -98,6 +109,16 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
"rui" "rui"
"d3d11.lib" "d3d11.lib"
"${THIRDPARTY_SOURCE_DIR}/nvapi/amd64/nvapi64.lib"
)
endif()
if( NOT ${PROJECT_NAME} STREQUAL "client" )
target_link_libraries( ${PROJECT_NAME} PRIVATE
"libmbedcrypto"
"libmbedtls"
"libmbedx509"
"libjwt"
) )
endif() endif()
@ -141,6 +162,11 @@ target_compile_definitions( ${PROJECT_NAME} PRIVATE
endif() endif()
target_include_directories( ${PROJECT_NAME} PRIVATE
"${THIRDPARTY_SOURCE_DIR}/dirtysdk/include/"
"${THIRDPARTY_SOURCE_DIR}/ea/"
)
target_link_options( ${PROJECT_NAME} PRIVATE target_link_options( ${PROJECT_NAME} PRIVATE
"/STACK:8000000" # Match game executable stack reserve size "/STACK:8000000" # Match game executable stack reserve size

View File

@ -10,4 +10,5 @@
// } while (false) // } while (false)
//#else //#else
# define Assert(condition, ...) assert(condition) # define Assert(condition, ...) assert(condition)
# define AssertFatalMsg Assert
//#endif //#endif

View File

@ -3,6 +3,7 @@
#include "core/init.h" #include "core/init.h"
#include "core/logdef.h" #include "core/logdef.h"
#include "core/logger.h" #include "core/logger.h"
#include "tier0/cpu.h"
#include "tier0/basetypes.h" #include "tier0/basetypes.h"
#include "tier0/crashhandler.h" #include "tier0/crashhandler.h"
#include "tier0/commandline.h" #include "tier0/commandline.h"
@ -15,6 +16,7 @@
#include "windows/system.h" #include "windows/system.h"
#include "mathlib/mathlib.h" #include "mathlib/mathlib.h"
#include "launcher/launcher.h" #include "launcher/launcher.h"
#include "protobuf/stubs/common.h"
#ifndef DEDICATED #ifndef DEDICATED
#define SDK_DEFAULT_CFG "cfg/system/startup_default.cfg" #define SDK_DEFAULT_CFG "cfg/system/startup_default.cfg"
@ -24,6 +26,12 @@
bool g_bSdkInitialized = false; bool g_bSdkInitialized = false;
bool g_bSdkInitCallInitiated = false;
bool g_bSdkShutdownCallInitiated = false;
bool g_bSdkShutdownInitiatedFromConsoleHandler = false;
HMODULE s_hModuleHandle = NULL;
//############################################################################# //#############################################################################
// UTILITY // UTILITY
//############################################################################# //#############################################################################
@ -41,14 +49,14 @@ void Show_Emblem()
// Logged as 'SYSTEM_ERROR' for its red color. // Logged as 'SYSTEM_ERROR' for its red color.
for (size_t i = 0; i < SDK_ARRAYSIZE(R5R_EMBLEM); i++) for (size_t i = 0; i < SDK_ARRAYSIZE(R5R_EMBLEM); i++)
{ {
DevMsg(eDLL_T::SYSTEM_ERROR, "%s\n", R5R_EMBLEM[i]); Msg(eDLL_T::SYSTEM_ERROR, "%s\n", R5R_EMBLEM[i]);
} }
// Log the SDK's 'build_id' under the emblem. // Log the SDK's 'build_id' under the emblem.
DevMsg(eDLL_T::SYSTEM_ERROR, Msg(eDLL_T::SYSTEM_ERROR,
"+------------------------------------------------[%s%010d%s]-+\n", "+------------------------------------------------[%s%010d%s]-+\n",
g_svYellowF, g_SDKDll.GetNTHeaders()->FileHeader.TimeDateStamp, g_svRedF); g_svYellowF, g_SDKDll.GetNTHeaders()->FileHeader.TimeDateStamp, g_svRedF);
DevMsg(eDLL_T::SYSTEM_ERROR, "\n"); Msg(eDLL_T::SYSTEM_ERROR, "\n");
} }
//############################################################################# //#############################################################################
@ -62,12 +70,10 @@ void Tier0_Init()
g_RadAudioDecoderDll.InitFromName("binkawin64.dll"); g_RadAudioDecoderDll.InitFromName("binkawin64.dll");
g_RadAudioSystemDll.InitFromName("mileswin64.dll"); g_RadAudioSystemDll.InitFromName("mileswin64.dll");
#endif // !DEDICATED #endif // !DEDICATED
g_pCmdLine = g_GameDll.GetExportedSymbol("g_pCmdLine").RCast<CCommandLine*>();
g_CoreMsgVCallback = &EngineLoggerSink; // Setup logger callback sink. g_CoreMsgVCallback = &EngineLoggerSink; // Setup logger callback sink.
g_pCmdLine->CreateCmdLine(GetCommandLineA()); g_pCmdLine->CreateCmdLine(GetCommandLineA());
g_CrashHandler->SetCrashCallback(&Crash_Callback); g_CrashHandler.SetCrashCallback(&Crash_Callback);
// This prevents the game from recreating it, // This prevents the game from recreating it,
// see 'CCommandLine::StaticCreateCmdLine' for // see 'CCommandLine::StaticCreateCmdLine' for
@ -77,6 +83,28 @@ void Tier0_Init()
void SDK_Init() void SDK_Init()
{ {
assert(!g_bSdkInitialized);
CheckSystemCPU(); // Check CPU as early as possible; error out if CPU isn't supported.
if (g_bSdkInitCallInitiated)
{
spdlog::error("Recursive initialization!\n");
return;
}
// Set after checking cpu and initializing MathLib since we check CPU
// features there. Else we crash on the recursive initialization error as
// SpdLog uses SSE features.
g_bSdkInitCallInitiated = true;
MathLib_Init(); // Initialize Mathlib.
PEB64* pEnv = CModule::GetProcessEnvironmentBlock();
g_GameDll.InitFromBase(pEnv->ImageBaseAddress);
g_SDKDll.InitFromBase((QWORD)s_hModuleHandle);
Tier0_Init(); Tier0_Init();
if (!CommandLine()->CheckParm("-launcher")) if (!CommandLine()->CheckParm("-launcher"))
@ -96,7 +124,9 @@ void SDK_Init()
SpdLog_Init(bAnsiColor); SpdLog_Init(bAnsiColor);
Show_Emblem(); Show_Emblem();
Winsock_Init(); // Initialize Winsock. Winsock_Startup(); // Initialize Winsock.
DirtySDK_Startup();
Systems_Init(); Systems_Init();
WinSys_Init(); WinSys_Init();
@ -104,6 +134,7 @@ void SDK_Init()
Input_Init(); Input_Init();
#endif // !DEDICATED #endif // !DEDICATED
GOOGLE_PROTOBUF_VERIFY_VERSION;
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
lzham_enable_fail_exceptions(true); lzham_enable_fail_exceptions(true);
@ -118,14 +149,26 @@ void SDK_Shutdown()
{ {
assert(g_bSdkInitialized); assert(g_bSdkInitialized);
if (!g_bSdkInitialized) // Also check CPU in shutdown, since this function is exported, if they
// call this with an unsupported CPU we should let them know rather than
// crashing the process.
CheckSystemCPU();
if (g_bSdkShutdownCallInitiated)
{ {
spdlog::error("Recursive shutdown!\n"); spdlog::error("Recursive shutdown!\n");
return; return;
} }
g_bSdkInitialized = false; g_bSdkShutdownCallInitiated = true;
DevMsg(eDLL_T::NONE, "GameSDK shutdown initiated\n");
if (!g_bSdkInitialized)
{
spdlog::error("Not initialized!\n");
return;
}
Msg(eDLL_T::NONE, "GameSDK shutdown initiated\n");
curl_global_cleanup(); curl_global_cleanup();
@ -135,10 +178,18 @@ void SDK_Shutdown()
WinSys_Shutdown(); WinSys_Shutdown();
Systems_Shutdown(); Systems_Shutdown();
DirtySDK_Shutdown();
Winsock_Shutdown(); Winsock_Shutdown();
SpdLog_Shutdown(); SpdLog_Shutdown();
Console_Shutdown();
// If the shutdown was initiated from the console window itself, don't
// shutdown the console as it would otherwise deadlock in FreeConsole!
if (!g_bSdkShutdownInitiatedFromConsoleHandler)
Console_Shutdown();
g_bSdkInitialized = false;
} }
//############################################################################# //#############################################################################
@ -147,27 +198,18 @@ void SDK_Shutdown()
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{ {
CheckCPU(); // Check CPU as early as possible; error out if CPU isn't supported.
MathLib_Init(); // Initialize Mathlib.
NOTE_UNUSED(lpReserved); NOTE_UNUSED(lpReserved);
switch (dwReason) switch (dwReason)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
{ {
PEB64* pEnv = CModule::GetProcessEnvironmentBlock(); s_hModuleHandle = hModule;
g_GameDll.InitFromBase(pEnv->ImageBaseAddress);
g_SDKDll.InitFromBase((QWORD)hModule);
SDK_Init();
break; break;
} }
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
{ {
SDK_Shutdown(); s_hModuleHandle = NULL;
break; break;
} }
} }

View File

@ -18,9 +18,8 @@
#include "tier0/sigcache.h" #include "tier0/sigcache.h"
#include "tier1/cmd.h" #include "tier1/cmd.h"
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "tier1/keyvalues_iface.h"
#include "vpc/IAppSystem.h" #include "vpc/IAppSystem.h"
#include "vpc/keyvalues.h"
#include "vpc/rson.h"
#include "vpc/interfaces.h" #include "vpc/interfaces.h"
#include "common/callback.h" #include "common/callback.h"
#include "common/completion.h" #include "common/completion.h"
@ -38,6 +37,7 @@
#include "codecs/miles/miles_impl.h" #include "codecs/miles/miles_impl.h"
#include "codecs/miles/radshal_wasapi.h" #include "codecs/miles/radshal_wasapi.h"
#endif // !DEDICATED #endif // !DEDICATED
#include "vphysics/physics_collide.h"
#include "vphysics/QHull.h" #include "vphysics/QHull.h"
#include "engine/staticpropmgr.h" #include "engine/staticpropmgr.h"
#include "materialsystem/cmaterialsystem.h" #include "materialsystem/cmaterialsystem.h"
@ -46,6 +46,7 @@
#include "vgui/vgui_baseui_interface.h" #include "vgui/vgui_baseui_interface.h"
#include "vgui/vgui_debugpanel.h" #include "vgui/vgui_debugpanel.h"
#include "vgui/vgui_fpspanel.h" #include "vgui/vgui_fpspanel.h"
#include "vgui/vgui_controls/RichText.h"
#include "vguimatsurface/MatSystemSurface.h" #include "vguimatsurface/MatSystemSurface.h"
#include "engine/client/vengineclient_impl.h" #include "engine/client/vengineclient_impl.h"
#include "engine/client/cdll_engine_int.h" #include "engine/client/cdll_engine_int.h"
@ -58,13 +59,23 @@
#include "engine/server/datablock_sender.h" #include "engine/server/datablock_sender.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
#include "studiorender/studiorendercontext.h" #include "studiorender/studiorendercontext.h"
#include "rtech/rtech_game.h" #ifndef CLIENT_DLL
#include "rtech/rtech_utils.h" #include "rtech/liveapi/liveapi.h"
#endif // !CLIENT_DLL
#include "rtech/rstdlib.h"
#include "rtech/rson.h"
#include "rtech/async/asyncio.h"
#include "rtech/pak/pakalloc.h"
#include "rtech/pak/pakparse.h"
#include "rtech/pak/pakstate.h"
#include "rtech/pak/pakstream.h"
#include "rtech/stryder/stryder.h" #include "rtech/stryder/stryder.h"
#include "rtech/playlists/playlists.h"
#ifndef DEDICATED #ifndef DEDICATED
#include "rtech/rui/rui.h" #include "rtech/rui/rui.h"
#include "engine/client/cl_ents_parse.h" #include "engine/client/cl_ents_parse.h"
#include "engine/client/cl_main.h" #include "engine/client/cl_main.h"
#include "engine/client/cl_rcon.h"
#include "engine/client/cl_splitscreen.h" #include "engine/client/cl_splitscreen.h"
#endif // !DEDICATED #endif // !DEDICATED
#include "engine/client/client.h" #include "engine/client/client.h"
@ -87,6 +98,7 @@
#include "engine/networkstringtable.h" #include "engine/networkstringtable.h"
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
#include "engine/server/sv_main.h" #include "engine/server/sv_main.h"
#include "engine/server/sv_rcon.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
#include "engine/sdk_dll.h" #include "engine/sdk_dll.h"
#include "engine/sys_dll.h" #include "engine/sys_dll.h"
@ -95,13 +107,15 @@
#include "engine/sys_utils.h" #include "engine/sys_utils.h"
#ifndef DEDICATED #ifndef DEDICATED
#include "engine/sys_getmodes.h" #include "engine/sys_getmodes.h"
#include "engine/gl_rmain.h"
#include "engine/sys_mainwind.h" #include "engine/sys_mainwind.h"
#include "engine/matsys_interface.h" #include "engine/matsys_interface.h"
#include "engine/gl_rmain.h"
#include "engine/gl_matsysiface.h" #include "engine/gl_matsysiface.h"
#include "engine/gl_drawlights.h"
#include "engine/gl_screen.h" #include "engine/gl_screen.h"
#include "engine/gl_rsurf.h" #include "engine/gl_rsurf.h"
#include "engine/debugoverlay.h" #include "engine/debugoverlay.h"
#include "engine/keys.h"
#endif // !DEDICATED #endif // !DEDICATED
#include "vscript/languages/squirrel_re/include/squirrel.h" #include "vscript/languages/squirrel_re/include/squirrel.h"
#include "vscript/languages/squirrel_re/include/sqvm.h" #include "vscript/languages/squirrel_re/include/sqvm.h"
@ -137,6 +151,11 @@
#include "windows/id3dx.h" #include "windows/id3dx.h"
#endif // !DEDICATED #endif // !DEDICATED
#include "DirtySDK/dirtysock.h"
#include "DirtySDK/dirtysock/netconn.h"
#include "DirtySDK/proto/protossl.h"
#include "DirtySDK/proto/protowebsocket.h"
///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////
// //
@ -176,7 +195,7 @@ void ScriptConstantRegistrationCallback(CSquirrelVM* s)
void Systems_Init() void Systems_Init()
{ {
DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); Msg(eDLL_T::NONE, "+-------------------------------------------------------------+\n");
QuerySystemInfo(); QuerySystemInfo();
DetourRegister(); DetourRegister();
@ -186,8 +205,8 @@ void Systems_Init()
DetourInit(); DetourInit();
initTimer.End(); initTimer.End();
DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); Msg(eDLL_T::NONE, "+-------------------------------------------------------------+\n");
DevMsg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->InitDB()", Msg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->InitDB()",
initTimer.GetDuration().GetSeconds(), initTimer.GetDuration().GetCycles()); initTimer.GetDuration().GetSeconds(), initTimer.GetDuration().GetCycles());
initTimer.Start(); initTimer.Start();
@ -197,9 +216,9 @@ void Systems_Init()
DetourUpdateThread(GetCurrentThread()); DetourUpdateThread(GetCurrentThread());
// Hook functions // Hook functions
for (const IDetour* Detour : g_DetourVec) for (const IDetour* pd : g_DetourVec)
{ {
Detour->Attach(); pd->Detour(true);
} }
// Patch instructions // Patch instructions
@ -210,16 +229,15 @@ void Systems_Init()
if (hr != NO_ERROR) if (hr != NO_ERROR)
{ {
// Failed to hook into the process, terminate // Failed to hook into the process, terminate
Assert(0);
Error(eDLL_T::COMMON, 0xBAD0C0DE, "Failed to detour process: error code = %08x\n", hr); Error(eDLL_T::COMMON, 0xBAD0C0DE, "Failed to detour process: error code = %08x\n", hr);
} }
initTimer.End(); initTimer.End();
DevMsg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->Attach()", Msg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->Attach()",
initTimer.GetDuration().GetSeconds(), initTimer.GetDuration().GetCycles()); initTimer.GetDuration().GetSeconds(), initTimer.GetDuration().GetCycles());
DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); Msg(eDLL_T::NONE, "+-------------------------------------------------------------+\n");
DevMsg(eDLL_T::NONE, "\n"); Msg(eDLL_T::NONE, "\n");
ConVar_StaticInit();
#ifdef DEDICATED #ifdef DEDICATED
InitCommandLineParameters(); InitCommandLineParameters();
@ -232,6 +250,8 @@ void Systems_Init()
ServerScriptRegister_Callback = Script_RegisterServerFunctions; ServerScriptRegister_Callback = Script_RegisterServerFunctions;
CoreServerScriptRegister_Callback = Script_RegisterCoreServerFunctions; CoreServerScriptRegister_Callback = Script_RegisterCoreServerFunctions;
AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelFunctions; AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelFunctions;
ServerScriptRegisterEnum_Callback = Script_RegisterServerEnums;
#endif// !CLIENT_DLL #endif// !CLIENT_DLL
#ifndef SERVER_DLL #ifndef SERVER_DLL
@ -257,6 +277,18 @@ void Systems_Init()
void Systems_Shutdown() void Systems_Shutdown()
{ {
// Shutdown RCON (closes all open sockets)
#ifndef CLIENT_DLL
RCONServer()->Shutdown();
#endif// !CLIENT_DLL
#ifndef SERVER_DLL
RCONClient()->Shutdown();
#endif // !SERVER_DLL
#ifndef CLIENT_DLL
LiveAPISystem()->Shutdown();
#endif// !CLIENT_DLL
CFastTimer shutdownTimer; CFastTimer shutdownTimer;
shutdownTimer.Start(); shutdownTimer.Start();
@ -265,19 +297,19 @@ void Systems_Shutdown()
DetourUpdateThread(GetCurrentThread()); DetourUpdateThread(GetCurrentThread());
// Unhook functions // Unhook functions
for (const IDetour* Detour : g_DetourVec) for (const IDetour* pd : g_DetourVec)
{ {
Detour->Detach(); pd->Detour(false);
} }
// Commit the transaction // Commit the transaction
DetourTransactionCommit(); DetourTransactionCommit();
shutdownTimer.End(); shutdownTimer.End();
DevMsg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->Detach()", Msg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->Detach()",
shutdownTimer.GetDuration().GetSeconds(), shutdownTimer.GetDuration().GetCycles()); shutdownTimer.GetDuration().GetSeconds(), shutdownTimer.GetDuration().GetCycles());
DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); Msg(eDLL_T::NONE, "+-------------------------------------------------------------+\n");
DevMsg(eDLL_T::NONE, "\n"); Msg(eDLL_T::NONE, "\n");
} }
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -291,25 +323,51 @@ void Systems_Shutdown()
// //
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
void Winsock_Init() void Winsock_Startup()
{ {
WSAData wsaData{}; WSAData wsaData{};
int nError = ::WSAStartup(MAKEWORD(2, 2), &wsaData); const int nError = ::WSAStartup(MAKEWORD(2, 2), &wsaData);
if (nError != 0) if (nError != 0)
{ {
Error(eDLL_T::COMMON, NO_ERROR, "%s: Failed to start Winsock: (%s)\n", Error(eDLL_T::COMMON, 0, "%s: Windows Sockets API startup failure: (%s)\n",
__FUNCTION__, NET_ErrorString(WSAGetLastError())); __FUNCTION__, NET_ErrorString(WSAGetLastError()));
} }
} }
void Winsock_Shutdown() void Winsock_Shutdown()
{ {
int nError = ::WSACleanup(); const int nError = ::WSACleanup();
if (nError != 0) if (nError != 0)
{ {
Error(eDLL_T::COMMON, NO_ERROR, "%s: Failed to stop Winsock: (%s)\n", Error(eDLL_T::COMMON, 0, "%s: Windows Sockets API shutdown failure: (%s)\n",
__FUNCTION__, NET_ErrorString(WSAGetLastError())); __FUNCTION__, NET_ErrorString(WSAGetLastError()));
} }
} }
void DirtySDK_Startup()
{
const int32_t netConStartupRet = NetConnStartup("-servicename=sourcesdk");
if (netConStartupRet < 0)
{
Error(eDLL_T::COMMON, 0, "%s: Network connection module startup failure: (%i)\n",
__FUNCTION__, netConStartupRet);
}
}
void DirtySDK_Shutdown()
{
const int32_t netConShutdownRet = NetConnShutdown(0);
if (netConShutdownRet < 0)
{
Error(eDLL_T::COMMON, 0, "%s: Network connection module shutdown failure: (%i)\n",
__FUNCTION__, netConShutdownRet);
}
}
void QuerySystemInfo() void QuerySystemInfo()
{ {
#ifndef DEDICATED #ifndef DEDICATED
@ -324,20 +382,20 @@ void QuerySystemInfo()
if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) // Only log the primary device. if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) // Only log the primary device.
{ {
DevMsg(eDLL_T::NONE, "%-25s: '%s'\n", "GPU model identifier", dd.DeviceString); Msg(eDLL_T::NONE, "%-25s: '%s'\n", "GPU model identifier", dd.DeviceString);
} }
} }
#endif // !DEDICATED #endif // !DEDICATED
const CPUInformation& pi = GetCPUInformation(); const CPUInformation& pi = GetCPUInformation();
DevMsg(eDLL_T::NONE, "%-25s: '%s'\n","CPU model identifier", pi.m_szProcessorBrand); Msg(eDLL_T::NONE, "%-25s: '%s'\n","CPU model identifier", pi.m_szProcessorBrand);
DevMsg(eDLL_T::NONE, "%-25s: '%s'\n","CPU vendor tag", pi.m_szProcessorID); Msg(eDLL_T::NONE, "%-25s: '%s'\n","CPU vendor tag", pi.m_szProcessorID);
DevMsg(eDLL_T::NONE, "%-25s: '%12hhu' ('%2hhu' %s)\n", "CPU core count", pi.m_nPhysicalProcessors, pi.m_nLogicalProcessors, "logical"); Msg(eDLL_T::NONE, "%-25s: '%12hhu' ('%2hhu' %s)\n", "CPU core count", pi.m_nPhysicalProcessors, pi.m_nLogicalProcessors, "logical");
DevMsg(eDLL_T::NONE, "%-25s: '%12lld' ('%6.1f' %s)\n", "CPU core speed", pi.m_Speed, float(pi.m_Speed / 1000000), "MHz"); Msg(eDLL_T::NONE, "%-25s: '%12lld' ('%6.1f' %s)\n", "CPU core speed", pi.m_Speed, float(pi.m_Speed / 1000000), "MHz");
DevMsg(eDLL_T::NONE, "%-20s%s: '%12lu' ('0x%-8X')\n", "L1 cache", "(KiB)", pi.m_nL1CacheSizeKb, pi.m_nL1CacheDesc); Msg(eDLL_T::NONE, "%-20s%s: '%12lu' ('0x%-8X')\n", "L1 cache", "(KiB)", pi.m_nL1CacheSizeKb, pi.m_nL1CacheDesc);
DevMsg(eDLL_T::NONE, "%-20s%s: '%12lu' ('0x%-8X')\n", "L2 cache", "(KiB)", pi.m_nL2CacheSizeKb, pi.m_nL2CacheDesc); Msg(eDLL_T::NONE, "%-20s%s: '%12lu' ('0x%-8X')\n", "L2 cache", "(KiB)", pi.m_nL2CacheSizeKb, pi.m_nL2CacheDesc);
DevMsg(eDLL_T::NONE, "%-20s%s: '%12lu' ('0x%-8X')\n", "L3 cache", "(KiB)", pi.m_nL3CacheSizeKb, pi.m_nL3CacheDesc); Msg(eDLL_T::NONE, "%-20s%s: '%12lu' ('0x%-8X')\n", "L3 cache", "(KiB)", pi.m_nL3CacheSizeKb, pi.m_nL3CacheDesc);
MEMORYSTATUSEX statex{}; MEMORYSTATUSEX statex{};
statex.dwLength = sizeof(statex); statex.dwLength = sizeof(statex);
@ -350,8 +408,8 @@ void QuerySystemInfo()
DWORDLONG availPhysical = (statex.ullAvailPhys / 1024) / 1024; DWORDLONG availPhysical = (statex.ullAvailPhys / 1024) / 1024;
DWORDLONG availVirtual = (statex.ullAvailVirtual / 1024) / 1024; DWORDLONG availVirtual = (statex.ullAvailVirtual / 1024) / 1024;
DevMsg(eDLL_T::NONE, "%-20s%s: '%12llu' ('%9llu' %s)\n", "Total system memory", "(MiB)", totalPhysical, totalVirtual, "virtual"); Msg(eDLL_T::NONE, "%-20s%s: '%12llu' ('%9llu' %s)\n", "Total system memory", "(MiB)", totalPhysical, totalVirtual, "virtual");
DevMsg(eDLL_T::NONE, "%-20s%s: '%12llu' ('%9llu' %s)\n", "Avail system memory", "(MiB)", availPhysical, availVirtual, "virtual"); Msg(eDLL_T::NONE, "%-20s%s: '%12llu' ('%9llu' %s)\n", "Avail system memory", "(MiB)", availPhysical, availVirtual, "virtual");
} }
else else
{ {
@ -360,30 +418,6 @@ void QuerySystemInfo()
} }
} }
void CheckCPU() // Respawn's engine and our SDK utilize POPCNT, SSE3 and SSSE3 (Supplemental SSE 3 Instructions).
{
const CPUInformation& pi = GetCPUInformation();
static char szBuf[1024];
if (!pi.m_bSSE3)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "SSE 3");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);
ExitProcess(0xFFFFFFFF);
}
if (!pi.m_bSSSE3)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "SSSE 3 (Supplemental SSE 3 Instructions)");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);
ExitProcess(0xFFFFFFFF);
}
if (!pi.m_bPOPCNT)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "POPCNT");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);
ExitProcess(0xFFFFFFFF);
}
}
#if defined (DEDICATED) #if defined (DEDICATED)
#define SIGDB_FILE "cfg/server/startup.bin" #define SIGDB_FILE "cfg/server/startup.bin"
#elif defined (CLIENT_DLL) #elif defined (CLIENT_DLL)
@ -394,27 +428,30 @@ void CheckCPU() // Respawn's engine and our SDK utilize POPCNT, SSE3 and SSSE3 (
void DetourInit() // Run the sigscan void DetourInit() // Run the sigscan
{ {
const bool bLogAdr = CommandLine()->CheckParm("-sig_toconsole") ? true : false;
const bool bNoSmap = CommandLine()->CheckParm("-nosmap") ? true : false; const bool bNoSmap = CommandLine()->CheckParm("-nosmap") ? true : false;
const bool bLogAdr = CommandLine()->CheckParm("-sig_toconsole") ? true : false;
bool bInitDivider = false; bool bInitDivider = false;
g_SigCache.SetDisabled(bNoSmap); g_SigCache.SetDisabled(bNoSmap);
g_SigCache.LoadCache(SIGDB_FILE); g_SigCache.ReadCache(SIGDB_FILE);
for (const IDetour* Detour : g_DetourVec) // No debug logging in non dev builds.
const bool bDevMode = !IsCert() && !IsRetail();
for (const IDetour* pd : g_DetourVec)
{ {
Detour->GetCon(); // Constants. pd->GetCon(); // Constants.
Detour->GetFun(); // Functions. pd->GetFun(); // Functions.
Detour->GetVar(); // Variables. pd->GetVar(); // Variables.
if (bLogAdr) if (bDevMode && bLogAdr)
{ {
if (!bInitDivider) if (!bInitDivider)
{ {
bInitDivider = true; bInitDivider = true;
spdlog::debug("+---------------------------------------------------------------------+\n"); spdlog::debug("+---------------------------------------------------------------------+\n");
} }
Detour->GetAdr(); pd->GetAdr();
spdlog::debug("+---------------------------------------------------------------------+\n"); spdlog::debug("+---------------------------------------------------------------------+\n");
} }
} }
@ -426,14 +463,14 @@ void DetourInit() // Run the sigscan
g_SigCache.WriteCache(SIGDB_FILE); g_SigCache.WriteCache(SIGDB_FILE);
g_SigCache.InvalidateMap(); g_SigCache.InvalidateMap();
} }
void DetourAddress() // Test the sigscan results void DetourAddress() // Test the sigscan results
{ {
spdlog::debug("+---------------------------------------------------------------------+\n"); spdlog::debug("+---------------------------------------------------------------------+\n");
for (const IDetour* Detour : g_DetourVec) for (const IDetour* pd : g_DetourVec)
{ {
Detour->GetAdr(); pd->GetAdr();
spdlog::debug("+---------------------------------------------------------------------+\n"); spdlog::debug("+---------------------------------------------------------------------+\n");
} }
} }
@ -448,7 +485,6 @@ void DetourRegister() // Register detour classes to be searched and hooked.
// Tier1 // Tier1
REGISTER(VCommandLine); REGISTER(VCommandLine);
REGISTER(VConVar);
REGISTER(VCVar); REGISTER(VCVar);
// VPC // VPC
@ -492,6 +528,7 @@ void DetourRegister() // Register detour classes to be searched and hooked.
#endif // !DEDICATED #endif // !DEDICATED
// VPhysics // VPhysics
REGISTER(VPhysicsCollide);
REGISTER(VQHull); REGISTER(VQHull);
// StaticPropMgr // StaticPropMgr
@ -509,6 +546,7 @@ void DetourRegister() // Register detour classes to be searched and hooked.
// VGui // VGui
REGISTER(VEngineVGui); // REGISTER CLIENT ONLY! REGISTER(VEngineVGui); // REGISTER CLIENT ONLY!
REGISTER(VFPSPanel); // REGISTER CLIENT ONLY! REGISTER(VFPSPanel); // REGISTER CLIENT ONLY!
REGISTER(VVGUIRichText); // REGISTER CLIENT ONLY!
REGISTER(VMatSystemSurface); REGISTER(VMatSystemSurface);
// Client // Client
@ -536,9 +574,17 @@ void DetourRegister() // Register detour classes to be searched and hooked.
#endif // !DEDICATED #endif // !DEDICATED
// RTech // RTech
REGISTER(V_RTechGame); REGISTER(V_ReSTD);
REGISTER(V_RTechUtils);
REGISTER(V_AsyncIO);
REGISTER(V_PakAlloc);
REGISTER(V_PakParse);
REGISTER(V_PakState);
REGISTER(V_PakStream);
REGISTER(VStryder); REGISTER(VStryder);
REGISTER(VPlaylists);
#ifndef DEDICATED #ifndef DEDICATED
REGISTER(V_Rui); REGISTER(V_Rui);
@ -573,6 +619,7 @@ void DetourRegister() // Register detour classes to be searched and hooked.
REGISTER(VGL_RMain); REGISTER(VGL_RMain);
REGISTER(VMatSys_Interface); REGISTER(VMatSys_Interface);
REGISTER(VGL_MatSysIFace); REGISTER(VGL_MatSysIFace);
REGISTER(VGL_DrawLights);
REGISTER(VGL_Screen); REGISTER(VGL_Screen);
#endif // !DEDICATED #endif // !DEDICATED
@ -583,6 +630,7 @@ void DetourRegister() // Register detour classes to be searched and hooked.
REGISTER(VGL_RSurf); REGISTER(VGL_RSurf);
REGISTER(VDebugOverlay); // !TODO: This also needs to be exposed to server dll!!! REGISTER(VDebugOverlay); // !TODO: This also needs to be exposed to server dll!!!
REGISTER(VKeys);
#endif // !DEDICATED #endif // !DEDICATED
// VScript // VScript
@ -631,4 +679,12 @@ void DetourRegister() // Register detour classes to be searched and hooked.
REGISTER(VInputSystem); REGISTER(VInputSystem);
REGISTER(VDXGI); REGISTER(VDXGI);
#endif // !DEDICATED #endif // !DEDICATED
} }
//-----------------------------------------------------------------------------
// Singleton accessors:
//-----------------------------------------------------------------------------
IKeyValuesSystem* KeyValuesSystem()
{
return g_pKeyValuesSystem;
}

View File

@ -1,18 +1,20 @@
#pragma once #pragma once
void SDK_Init(); PLATFORM_INTERFACE void SDK_Init();
void SDK_Shutdown(); PLATFORM_INTERFACE void SDK_Shutdown();
void Systems_Init(); void Systems_Init();
void Systems_Shutdown(); void Systems_Shutdown();
void Winsock_Init(); void Winsock_Startup();
void Winsock_Shutdown(); void Winsock_Shutdown();
void DirtySDK_Startup();
void DirtySDK_Shutdown();
void QuerySystemInfo(); void QuerySystemInfo();
void CheckCPU();
void DetourInit(); void DetourInit();
void DetourAddress(); void DetourAddress();
void DetourRegister(); void DetourRegister();
extern bool g_bSdkInitialized; extern bool g_bSdkInitialized;
extern bool g_bSdkShutdownInitiatedFromConsoleHandler;

View File

@ -4,9 +4,47 @@
std::shared_ptr<spdlog::logger> g_TermLogger; std::shared_ptr<spdlog::logger> g_TermLogger;
std::shared_ptr<spdlog::logger> g_ImGuiLogger; std::shared_ptr<spdlog::logger> g_ImGuiLogger;
std::shared_ptr<spdlog::logger> g_SuppementalToolsLogger;
std::ostringstream g_LogStream; std::ostringstream g_LogStream;
std::shared_ptr<spdlog::sinks::ostream_sink_st> g_LogSink; std::shared_ptr<spdlog::sinks::ostream_sink_st> g_LogSink;
#ifndef _TOOLS
static void SpdLog_CreateRotatingLoggers()
{
/************************
* ROTATE LOGGER SETUP *
************************/
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("squirrel_re(warning)"
, fmt::format("{:s}/{:s}", g_LogSessionDirectory, "script_warning.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("squirrel_re"
, fmt::format("{:s}/{:s}", g_LogSessionDirectory, "script.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("sdk"
, fmt::format("{:s}/{:s}", g_LogSessionDirectory, "message.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("sdk(warning)"
, fmt::format("{:s}/{:s}", g_LogSessionDirectory, "warning.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("sdk(error)"
, fmt::format("{:s}/{:s}", g_LogSessionDirectory, "error.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("net_trace"
, fmt::format("{:s}/{:s}", g_LogSessionDirectory, "net_trace.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
#ifndef DEDICATED
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("netconsole"
, fmt::format("{:s}/{:s}", g_LogSessionDirectory, "netconsole.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
#endif // !DEDICATED
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("filesystem"
, fmt::format("{:s}/{:s}", g_LogSessionDirectory, "filesystem.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
}
#endif // !_TOOLS
#ifdef _TOOLS
// NOTE: used for tools as additional file logger on top of the existing terminal logger.
void SpdLog_InstallSupplementalLogger(const char* pszLoggerName, const char* pszLogFileName, const char* pszPattern, const bool bTruncate)
{
g_SuppementalToolsLogger = spdlog::basic_logger_mt(pszLoggerName, pszLogFileName, bTruncate);
g_SuppementalToolsLogger->set_pattern(pszPattern);
}
#endif // _TOOLS
//############################################################################# //#############################################################################
// SPDLOG INIT // SPDLOG INIT
//############################################################################# //#############################################################################
@ -20,9 +58,9 @@ void SpdLog_Init(const bool bAnsiColor)
return; return;
} }
#ifndef NETCONSOLE #ifndef _TOOLS
g_LogSessionUUID = CreateUUID(); g_LogSessionUUID = CreateUUID();
g_LogSessionDirectory = fmt::format("platform\\logs\\{:s}", g_LogSessionUUID); g_LogSessionDirectory = fmt::format("platform/logs/{:s}", g_LogSessionUUID);
/************************ /************************
* IMGUI LOGGER SETUP * * IMGUI LOGGER SETUP *
************************/ ************************/
@ -33,16 +71,16 @@ void SpdLog_Init(const bool bAnsiColor)
g_ImGuiLogger->set_pattern("%v"); g_ImGuiLogger->set_pattern("%v");
g_ImGuiLogger->set_level(spdlog::level::trace); g_ImGuiLogger->set_level(spdlog::level::trace);
} }
#endif // !NETCONSOLE #endif // !_TOOLS
/************************ /************************
* WINDOWS LOGGER SETUP * * WINDOWS LOGGER SETUP *
************************/ ************************/
{ {
#ifdef NETCONSOLE #ifdef _TOOLS
g_TermLogger = spdlog::default_logger(); g_TermLogger = spdlog::default_logger();
#else #else
g_TermLogger = spdlog::stdout_logger_mt("win_console"); g_TermLogger = spdlog::stdout_logger_mt("win_console");
#endif // NETCONSOLE #endif // _TOOLS
// Determine if user wants ansi-color logging in the terminal. // Determine if user wants ansi-color logging in the terminal.
if (bAnsiColor) if (bAnsiColor)
@ -57,38 +95,15 @@ void SpdLog_Init(const bool bAnsiColor)
//g_TermLogger->set_level(spdlog::level::trace); //g_TermLogger->set_level(spdlog::level::trace);
} }
#ifndef NETCONSOLE #ifndef _TOOLS
spdlog::set_default_logger(g_TermLogger); // Set as default. spdlog::set_default_logger(g_TermLogger); // Set as default.
SpdLog_Create(); SpdLog_CreateRotatingLoggers();
#endif // !NETCONSOLE #endif // !_TOOLS
spdlog::set_level(spdlog::level::trace); spdlog::set_level(spdlog::level::trace);
bInitialized = true; spdlog::flush_every(std::chrono::seconds(5));
}
void SpdLog_Create() bInitialized = true;
{
/************************
* ROTATE LOGGER SETUP *
************************/
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("squirrel_re(warning)"
, fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "script_warning.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("squirrel_re"
, fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "script.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("sdk"
, fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "message.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("sdk(warning)"
, fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "warning.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("sdk(error)"
, fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "error.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("net_trace"
, fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "net_trace.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
#ifndef DEDICATED
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("netconsole"
, fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "netconsole.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
#endif // !DEDICATED
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("filesystem"
, fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "filesystem.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
} }
//############################################################################# //#############################################################################
@ -97,4 +112,8 @@ void SpdLog_Create()
void SpdLog_Shutdown() void SpdLog_Shutdown()
{ {
spdlog::shutdown(); spdlog::shutdown();
#ifdef _TOOLS
// Destroy the tools logger to flush it.
g_SuppementalToolsLogger.reset();
#endif // !_TOOLS
} }

View File

@ -18,11 +18,19 @@ inline bool g_bSpdLog_UseAnsiClr = false;
extern std::shared_ptr<spdlog::logger> g_TermLogger; extern std::shared_ptr<spdlog::logger> g_TermLogger;
extern std::shared_ptr<spdlog::logger> g_ImGuiLogger; extern std::shared_ptr<spdlog::logger> g_ImGuiLogger;
#ifdef _TOOLS
extern std::shared_ptr<spdlog::logger> g_SuppementalToolsLogger;
#endif // _TOOLS
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// IMGUI CONSOLE SINK | // IMGUI CONSOLE SINK |
extern std::ostringstream g_LogStream; extern std::ostringstream g_LogStream;
extern std::shared_ptr<spdlog::sinks::ostream_sink_st> g_LogSink; extern std::shared_ptr<spdlog::sinks::ostream_sink_st> g_LogSink;
void SpdLog_Init(const bool bAnsiColor); void SpdLog_Init(const bool bAnsiColor);
void SpdLog_Create(void);
void SpdLog_Shutdown(void); void SpdLog_Shutdown(void);
#ifdef _TOOLS
void SpdLog_InstallSupplementalLogger(const char* pszLoggerName, const char* pszLogFileName,
const char* pszPattern = "[%Y-%m-%d %H:%M:%S.%e] %v", const bool bTruncate = true);
#endif // _TOOLS

View File

@ -9,13 +9,13 @@
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
#include "engine/server/sv_rcon.h" #include "engine/server/sv_rcon.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
#ifndef NETCONSOLE #ifndef _TOOLS
#include "vscript/languages/squirrel_re/include/sqstdaux.h" #include "vscript/languages/squirrel_re/include/sqstdaux.h"
#endif // !NETCONSOLE #endif // !_TOOLS
static const std::regex s_AnsiRowRegex("\\\033\\[.*?m"); static const std::regex s_AnsiRowRegex("\\\033\\[.*?m");
std::mutex g_LogMutex; std::mutex g_LogMutex;
#if !defined (DEDICATED) && !defined (NETCONSOLE) #if !defined (DEDICATED) && !defined (_TOOLS)
ImVec4 CheckForWarnings(LogType_t type, eDLL_T context, const ImVec4& defaultCol) ImVec4 CheckForWarnings(LogType_t type, eDLL_T context, const ImVec4& defaultCol)
{ {
ImVec4 color = defaultCol; ImVec4 color = defaultCol;
@ -67,7 +67,7 @@ ImVec4 GetColorForContext(LogType_t type, eDLL_T context)
return CheckForWarnings(type, context, ImVec4(0.81f, 0.81f, 0.81f, 1.00f)); return CheckForWarnings(type, context, ImVec4(0.81f, 0.81f, 0.81f, 1.00f));
} }
} }
#endif // !DEDICATED && !NETCONSOLE #endif // !DEDICATED && !_TOOLS
const char* GetContextNameByIndex(eDLL_T context, const bool ansiColor = false) const char* GetContextNameByIndex(eDLL_T context, const bool ansiColor = false)
{ {
@ -150,18 +150,18 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
const char* pszContext = GetContextNameByIndex(context, bUseColor); const char* pszContext = GetContextNameByIndex(context, bUseColor);
message.append(pszContext); message.append(pszContext);
#if !defined (DEDICATED) && !defined (NETCONSOLE) #if !defined (DEDICATED) && !defined (_TOOLS)
ImVec4 overlayColor = GetColorForContext(logType, context); ImVec4 overlayColor = GetColorForContext(logType, context);
eDLL_T overlayContext = context; eDLL_T overlayContext = context;
#endif // !DEDICATED && !NETCONSOLE #endif // !DEDICATED && !_TOOLS
#if !defined (NETCONSOLE) #if !defined (_TOOLS)
bool bSquirrel = false; bool bSquirrel = false;
bool bWarning = false; bool bWarning = false;
bool bError = false; bool bError = false;
#else #else
NOTE_UNUSED(pszLogger); NOTE_UNUSED(pszLogger);
#endif // !NETCONSOLE #endif // !_TOOLS
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Setup logger and context // Setup logger and context
@ -169,24 +169,24 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
switch (logType) switch (logType)
{ {
case LogType_t::LOG_WARNING: case LogType_t::LOG_WARNING:
#if !defined (DEDICATED) && !defined (NETCONSOLE) #if !defined (DEDICATED) && !defined (_TOOLS)
overlayContext = eDLL_T::SYSTEM_WARNING; overlayContext = eDLL_T::SYSTEM_WARNING;
#endif // !DEDICATED && !NETCONSOLE #endif // !DEDICATED && !_TOOLS
if (bUseColor) if (bUseColor)
{ {
message.append(g_svYellowF); message.append(g_svYellowF);
} }
break; break;
case LogType_t::LOG_ERROR: case LogType_t::LOG_ERROR:
#if !defined (DEDICATED) && !defined (NETCONSOLE) #if !defined (DEDICATED) && !defined (_TOOLS)
overlayContext = eDLL_T::SYSTEM_ERROR; overlayContext = eDLL_T::SYSTEM_ERROR;
#endif // !DEDICATED && !NETCONSOLE #endif // !DEDICATED && !_TOOLS
if (bUseColor) if (bUseColor)
{ {
message.append(g_svRedF); message.append(g_svRedF);
} }
break; break;
#ifndef NETCONSOLE #ifndef _TOOLS
case LogType_t::SQ_INFO: case LogType_t::SQ_INFO:
bSquirrel = true; bSquirrel = true;
break; break;
@ -198,7 +198,7 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
bSquirrel = true; bSquirrel = true;
bWarning = true; bWarning = true;
break; break;
#endif // !NETCONSOLE #endif // !_TOOLS
default: default:
break; break;
} }
@ -211,7 +211,7 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
const string formatted = FormatV(pszFormat, argsCopy); const string formatted = FormatV(pszFormat, argsCopy);
va_end(argsCopy); va_end(argsCopy);
#ifndef NETCONSOLE #ifndef _TOOLS
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Colorize script warnings and errors // Colorize script warnings and errors
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -253,7 +253,7 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
message.append(g_svYellowF); message.append(g_svYellowF);
} }
} }
#endif // !NETCONSOLE #endif // !_TOOLS
message.append(formatted); message.append(formatted);
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -271,7 +271,11 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
} }
} }
#ifndef NETCONSOLE // If a debugger is attached, emit the text there too
if (Plat_IsInDebugSession())
Plat_DebugString(message.c_str());
#ifndef _TOOLS
// Output is always logged to the file. // Output is always logged to the file.
std::shared_ptr<spdlog::logger> ntlogger = spdlog::get(pszLogger); // <-- Obtain by 'pszLogger'. std::shared_ptr<spdlog::logger> ntlogger = spdlog::get(pszLogger); // <-- Obtain by 'pszLogger'.
assert(ntlogger.get() != nullptr); assert(ntlogger.get() != nullptr);
@ -290,14 +294,14 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
g_ImGuiLogger->debug(message); g_ImGuiLogger->debug(message);
const string logStreamBuf = g_LogStream.str(); const string logStreamBuf = g_LogStream.str();
g_pConsole->AddLog(ConLog_t(logStreamBuf, overlayColor)); g_Console.AddLog(logStreamBuf.c_str(), ImGui::ColorConvertFloat4ToU32(overlayColor));
// We can only log to the in-game overlay console when the SDK has // We can only log to the in-game overlay console when the SDK has
// been fully initialized, due to the use of ConVar's. // been fully initialized, due to the use of ConVar's.
if (g_bSdkInitialized && logLevel >= LogLevel_t::LEVEL_NOTIFY) if (g_bSdkInitialized && logLevel >= LogLevel_t::LEVEL_NOTIFY)
{ {
// Draw to mini console. // Draw to mini console.
g_pOverlay->AddLog(overlayContext, logStreamBuf.c_str()); g_TextOverlay.AddLog(overlayContext, logStreamBuf.c_str());
} }
#endif // !DEDICATED #endif // !DEDICATED
} }
@ -307,7 +311,12 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
g_LogStream.clear(); g_LogStream.clear();
#endif // !DEDICATED #endif // !DEDICATED
#endif // !NETCONSOLE #else
if (g_SuppementalToolsLogger)
{
g_SuppementalToolsLogger->debug(message);
}
#endif
if (exitCode) // Terminate the process if an exit code was passed. if (exitCode) // Terminate the process if an exit code was passed.
{ {

View File

@ -8,10 +8,10 @@ __declspec(dllexport) void DummyExport()
static const char* const R5R_EMBLEM[] = static const char* const R5R_EMBLEM[] =
{ {
R"(+-------------------------------------------------------------+)", R"(+-------------------------------------------------------------+)",
R"(| ___ ___ ___ _ _ _ ___ ___ |)", R"(| ___ ___ ___ _ _ _ ___ _ _ |)",
R"(| | _ \ __| _ \___| |___ __ _ __| |___ __| | __ _|_ ) |_ ) |)", R"(| | _ \ __| _ \___| |___ __ _ __| |___ __| | __ _|_ )| | | |)",
R"(| | /__ \ / -_) / _ \/ _` / _` / -_) _` | \ V // / _ / / |)", R"(| | /__ \ / -_) / _ \/ _` / _` / -_) _` | \ V // / |_ _| |)",
R"(| |_|_\___/_|_\___|_\___/\__,_\__,_\___\__,_| \_//___(_)___| |)", R"(| |_|_\___/_|_\___|_\___/\__,_\__,_\___\__,_| \_//___(_)|_| |)",
R"(| |)"/*, R"(| |)"/*,
R"(+-------------------------------------------------------------+)"*/ R"(+-------------------------------------------------------------+)"*/
}; };

View File

@ -23,7 +23,6 @@
#include <shellapi.h> #include <shellapi.h>
#include <Psapi.h> #include <Psapi.h>
#include <setjmp.h> #include <setjmp.h>
#include <tchar.h>
#include <stdio.h> #include <stdio.h>
#include <shlobj.h> #include <shlobj.h>
#include <objbase.h> #include <objbase.h>

View File

@ -18,8 +18,18 @@
#include "thirdparty/lzham/include/lzham_types.h" #include "thirdparty/lzham/include/lzham_types.h"
#include "thirdparty/lzham/include/lzham.h" #include "thirdparty/lzham/include/lzham.h"
#include "thirdparty/zstd/zstd.h"
#include "thirdparty/zstd/decompress/zstd_decompress_internal.h"
#include "thirdparty/lz4/lz4.h"
#include "thirdparty/curl/include/curl/curl.h" #include "thirdparty/curl/include/curl/curl.h"
#include "thirdparty/nlohmann/json.hpp"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/error/en.h"
#if !defined(DEDICATED) && !defined(PLUGINSDK) #if !defined(DEDICATED) && !defined(PLUGINSDK)
#include "thirdparty/imgui/imgui.h" #include "thirdparty/imgui/imgui.h"
@ -30,6 +40,10 @@
#include "thirdparty/imgui/misc/cpp/imgui_stdlib.h" #include "thirdparty/imgui/misc/cpp/imgui_stdlib.h"
#include "thirdparty/imgui/backends/imgui_impl_dx11.h" #include "thirdparty/imgui/backends/imgui_impl_dx11.h"
#include "thirdparty/imgui/backends/imgui_impl_win32.h" #include "thirdparty/imgui/backends/imgui_impl_win32.h"
#include "thirdparty/nvapi/pclstats.h"
#include "thirdparty/nvapi/nvapi.h"
#include "thirdparty/nvapi/nvapi_lite_common.h"
#endif // !DEDICATED && !PLUGINSDK #endif // !DEDICATED && !PLUGINSDK
@ -46,11 +60,13 @@
#pragma warning(pop) #pragma warning(pop)
// Tier0 includes. // Tier0 includes.
#include "tier0/basetypes.h"
#include "tier0/wchartypes.h"
#include "tier0/memaddr.h" #include "tier0/memaddr.h"
#include "tier0/utility.h" #include "tier0/utility.h"
#include "tier0/module.h" #include "tier0/module.h"
#include "tier0/basetypes.h"
#include "tier0/platform.h" #include "tier0/platform.h"
#include "tier0/platwindow.h"
#include "tier0/annotations.h" #include "tier0/annotations.h"
#include "tier0/commonmacros.h" #include "tier0/commonmacros.h"
#include "tier0/memalloc.h" #include "tier0/memalloc.h"
@ -58,6 +74,7 @@
#include "tier0/dbg.h" #include "tier0/dbg.h"
// Tier1 includes. // Tier1 includes.
#include "tier1/tier1.h"
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "tier1/cmd.h" #include "tier1/cmd.h"
#include "common/global.h" #include "common/global.h"

View File

@ -12,12 +12,11 @@
#include "datacache/mdlcache.h" #include "datacache/mdlcache.h"
#include "datacache/imdlcache.h" #include "datacache/imdlcache.h"
#include "datacache/idatacache.h" #include "datacache/idatacache.h"
#include "rtech/rtech_utils.h" #include "rtech/pak/paktools.h"
#include "public/studio.h" #include "public/studio.h"
RMDLFallBack_t* g_pMDLFallback = new RMDLFallBack_t(); CStudioFallbackHandler g_StudioMdlFallbackHandler;
std::unordered_set<MDLHandle_t> g_vBadMDLHandles; #define IS_VALID_DATACACHE_HANDLE(cacheHandle) (cacheHandle && cacheHandle != DC_INVALID_HANDLE)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: finds an MDL // Purpose: finds an MDL
@ -26,33 +25,13 @@ std::unordered_set<MDLHandle_t> g_vBadMDLHandles;
// *a3 - // *a3 -
// Output : a pointer to the studiohdr_t object // Output : a pointer to the studiohdr_t object
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
studiohdr_t* CMDLCache::FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3) studiohdr_t* CMDLCache::FindMDL(CMDLCache* const cache, const MDLHandle_t handle, void* a3)
{ {
studiodata_t* pStudioData = cache->GetStudioData(handle); studiodata_t* const studioData = cache->GetStudioData(handle);
studiohdr_t* pStudioHdr;
if (pStudioData) if (!studioData)
{ {
if (pStudioData->m_MDLCache && studiohdr_t* const pStudioHdr = GetErrorModel();
pStudioData->m_MDLCache != DC_INVALID_HANDLE)
{
studiohdr_t* pStudioHDR = **reinterpret_cast<studiohdr_t***>(pStudioData);
if (!g_pMDLFallback->m_hErrorMDL && V_ComparePath(pStudioHDR->name, ERROR_MODEL))
{
g_pMDLFallback->m_pErrorHDR = pStudioHDR;
g_pMDLFallback->m_hErrorMDL = handle;
}
else if (!g_pMDLFallback->m_hEmptyMDL && V_ComparePath(pStudioHDR->name, EMPTY_MODEL))
{
g_pMDLFallback->m_pEmptyHDR = pStudioHDR;
g_pMDLFallback->m_hEmptyMDL = handle;
}
}
}
else
{
pStudioHdr = GetErrorModel();
if (!IsKnownBadModel(handle)) if (!IsKnownBadModel(handle))
{ {
@ -65,33 +44,56 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3)
return pStudioHdr; return pStudioHdr;
} }
int nFlags = STUDIOHDR_FLAGS_NEEDS_DEFERRED_ADDITIVE | STUDIOHDR_FLAGS_OBSOLETE; studiomodelcache_t* modelCache = studioData->GetModelCache();
if ((pStudioData->m_nFlags & nFlags))
// Store error and empty fallback models.
if (IS_VALID_DATACACHE_HANDLE(modelCache))
{ {
void* pMDLCache = *reinterpret_cast<void**>(pStudioData); studiohdr_t* const studioHdr = studioData->GetModelCache()->GetStudioHdr();
if (pStudioData->m_MDLCache)
if (studioHdr)
{
// Typically, you would only check for '(m_nFlags & STUDIODATA_ERROR_MODEL)',
// but for some reason this game doesn't have this flag set on that model.
if (!HasErrorModel() && ((studioData->flags & STUDIODATA_ERROR_MODEL)
|| V_ComparePath(studioHdr->name, ERROR_MODEL)))
{
g_StudioMdlFallbackHandler.SetFallbackModel(studioHdr, handle);
}
}
}
const int nFlags = STUDIOHDR_FLAGS_NEEDS_DEFERRED_ADDITIVE | STUDIOHDR_FLAGS_OBSOLETE;
if ((studioData->flags & nFlags))
{
if (IS_VALID_DATACACHE_HANDLE(modelCache))
{ {
if (a3) if (a3)
{ {
FindCachedMDL(cache, pStudioData, a3); FindCachedMDL(cache, studioData, a3);
pMDLCache = *reinterpret_cast<void**>(pStudioData); modelCache = studioData->GetModelCache();
} }
pStudioHdr = *reinterpret_cast<studiohdr_t**>(pMDLCache); studiohdr_t* const pStudioHdr = modelCache->GetStudioHdr();
if (pStudioHdr) if (pStudioHdr)
return pStudioHdr; return pStudioHdr;
return FindUncachedMDL(cache, handle, pStudioData, a3); return FindUncachedMDL(cache, handle, studioData, a3);
} }
pMDLCache = pStudioData->m_pAnimData;
if (pMDLCache) studioanimcache_t* const animCache = studioData->GetAnimCache();
if (IS_VALID_DATACACHE_HANDLE(animCache))
{ {
pStudioHdr = *reinterpret_cast<studiohdr_t**>(pMDLCache); studiohdr_t* const pStudioHdr = animCache->GetStudioHdr();
if (pStudioHdr) if (pStudioHdr)
return pStudioHdr; return pStudioHdr;
} }
} }
return FindUncachedMDL(cache, handle, pStudioData, a3); return FindUncachedMDL(cache, handle, studioData, a3);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -100,11 +102,11 @@ studiohdr_t* CMDLCache::FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3)
// *pStudioData - // *pStudioData -
// *a3 - // *a3 -
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CMDLCache::FindCachedMDL(CMDLCache* cache, studiodata_t* pStudioData, void* a3) void CMDLCache::FindCachedMDL(CMDLCache* const cache, studiodata_t* const pStudioData, void* a3)
{ {
if (a3) if (a3)
{ {
AUTO_LOCK(pStudioData->m_Mutex); AUTO_LOCK(pStudioData->mutex);
*(_QWORD*)((int64_t)a3 + 0x880) = *(_QWORD*)&pStudioData->pad[0x24]; *(_QWORD*)((int64_t)a3 + 0x880) = *(_QWORD*)&pStudioData->pad[0x24];
int64_t v6 = *(_QWORD*)&pStudioData->pad[0x24]; int64_t v6 = *(_QWORD*)&pStudioData->pad[0x24];
@ -112,7 +114,7 @@ void CMDLCache::FindCachedMDL(CMDLCache* cache, studiodata_t* pStudioData, void*
*(_QWORD*)(v6 + 0x878) = (int64_t)a3; *(_QWORD*)(v6 + 0x878) = (int64_t)a3;
*(_QWORD*)&pStudioData->pad[0x24] = (int64_t)a3; *(_QWORD*)&pStudioData->pad[0x24] = (int64_t)a3;
*(_QWORD*)((int64_t)a3 + 0x870) = (int64_t)cache; *(_QWORD*)((int64_t)a3 + 0x870) = (int64_t)cache;
*(_WORD*)((int64_t)a3 + 0x888) = pStudioData->m_Handle; *(_WORD*)((int64_t)a3 + 0x888) = pStudioData->modelHandle;
} }
} }
@ -124,124 +126,145 @@ void CMDLCache::FindCachedMDL(CMDLCache* cache, studiodata_t* pStudioData, void*
// *a4 - // *a4 -
// Output : a pointer to the studiohdr_t object // Output : a pointer to the studiohdr_t object
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, studiodata_t* pStudioData, void* a4) studiohdr_t* CMDLCache::FindUncachedMDL(CMDLCache* const cache, const MDLHandle_t handle, studiodata_t* pStudioData, void* a4)
{ {
AUTO_LOCK(pStudioData->m_Mutex); AUTO_LOCK(pStudioData->mutex);
const char* szModelName = cache->GetModelName(handle); const char* modelName = cache->GetModelName(handle);
size_t nFileNameLen = strlen(szModelName); const size_t fileNameLen = strlen(modelName);
studiohdr_t* pStudioHdr; studiohdr_t* studioHdr = nullptr;
if (nFileNameLen < 5 || if (fileNameLen < 5 ||
(Q_stricmp(&szModelName[nFileNameLen - 5], ".rmdl") != 0) && (Q_stricmp(&modelName[fileNameLen - 5], ".rmdl") != 0) &&
(Q_stricmp(&szModelName[nFileNameLen - 5], ".rrig") != 0) && (Q_stricmp(&modelName[fileNameLen - 5], ".rrig") != 0) &&
(Q_stricmp(&szModelName[nFileNameLen - 5], ".rpak") != 0)) (Q_stricmp(&modelName[fileNameLen - 5], ".rpak") != 0))
{ {
pStudioHdr = GetErrorModel(); studioHdr = GetErrorModel();
if (!IsKnownBadModel(handle)) if (!IsKnownBadModel(handle))
{ {
if (!pStudioHdr) if (!studioHdr)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Attempted to load old model \"%s\" and \"%s\" couldn't be loaded.\n", szModelName, ERROR_MODEL); Error(eDLL_T::ENGINE, EXIT_FAILURE, "Attempted to load old model \"%s\" and \"%s\" couldn't be loaded.\n", modelName, ERROR_MODEL);
else else
Error(eDLL_T::ENGINE, NO_ERROR, "Attempted to load old model \"%s\"; replacing with \"%s\".\n", szModelName, ERROR_MODEL); Error(eDLL_T::ENGINE, NO_ERROR, "Attempted to load old model \"%s\"; replacing with \"%s\".\n", modelName, ERROR_MODEL);
} }
return pStudioHdr; return studioHdr;
} }
LOBYTE(pStudioData->m_nGuidLock) = 1; pStudioData->processing = true;
g_pRTech->StringToGuid(szModelName); Pak_StringToGuid(modelName);
LOBYTE(pStudioData->m_nGuidLock) = 0; pStudioData->processing = false;
if (!pStudioData->m_MDLCache) studiomodelcache_t* const modelCache = pStudioData->GetModelCache();
if (IS_VALID_DATACACHE_HANDLE(modelCache))
{ {
studiohdr_t** pAnimData = (studiohdr_t**)pStudioData->m_pAnimData; FindCachedMDL(cache, pStudioData, a4);
if (pAnimData) studioHdr = modelCache->GetStudioHdr();
{
pStudioHdr = *pAnimData;
}
else
{
pStudioHdr = GetErrorModel();
if (!IsKnownBadModel(handle))
{
if (!pStudioHdr)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Model \"%s\" not found and \"%s\" couldn't be loaded.\n", szModelName, ERROR_MODEL);
else
Error(eDLL_T::ENGINE, NO_ERROR, "Model \"%s\" not found; replacing with \"%s\".\n", szModelName, ERROR_MODEL);
}
return pStudioHdr;
}
} }
else else
{ {
FindCachedMDL(cache, pStudioData, a4); // Attempt to get studio header from anim cache.
DataCacheHandle_t dataHandle = pStudioData->m_MDLCache; studioanimcache_t* const animCache = pStudioData->GetAnimCache();
if (dataHandle) if (IS_VALID_DATACACHE_HANDLE(animCache))
{ {
if (dataHandle == DC_INVALID_HANDLE) studioHdr = animCache->GetStudioHdr();
{
pStudioHdr = GetErrorModel();
if (!IsKnownBadModel(handle))
{
if (!pStudioHdr)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Model \"%s\" has bad studio data and \"%s\" couldn't be loaded.\n", szModelName, ERROR_MODEL);
else
Error(eDLL_T::ENGINE, NO_ERROR, "Model \"%s\" has bad studio data; replacing with \"%s\".\n", szModelName, ERROR_MODEL);
}
}
else
pStudioHdr = *(studiohdr_t**)dataHandle;
} }
else else
{ {
pStudioHdr = GetErrorModel(); studioHdr = GetErrorModel();
if (!IsKnownBadModel(handle)) if (!IsKnownBadModel(handle))
{ {
if (!pStudioHdr) if (!studioHdr)
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Model \"%s\" has no studio data and \"%s\" couldn't be loaded.\n", szModelName, ERROR_MODEL); Error(eDLL_T::ENGINE, EXIT_FAILURE, "Model \"%s\" not found and \"%s\" couldn't be loaded.\n", modelName, ERROR_MODEL);
else else
Error(eDLL_T::ENGINE, NO_ERROR, "Model \"%s\" has no studio data; replacing with \"%s\".\n", szModelName, ERROR_MODEL); Error(eDLL_T::ENGINE, NO_ERROR, "Model \"%s\" not found; replacing with \"%s\".\n", modelName, ERROR_MODEL);
} }
} }
} }
return pStudioHdr; assert(studioHdr);
return studioHdr;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: gets the studiohdr from cache pool by handle // Purpose: gets the model cache by handle
// Input : handle -
// Output : a pointer to the studiomodelcache_t object
//-----------------------------------------------------------------------------
studiomodelcache_t* CMDLCache::GetModelCache(const MDLHandle_t handle)
{
if (handle == MDLHANDLE_INVALID)
return nullptr;
const studiodata_t* const studioData = GetStudioData(handle);
if (!studioData)
return nullptr;
studiomodelcache_t* const modelCache = studioData->GetModelCache();
return modelCache;
}
//-----------------------------------------------------------------------------
// Purpose: gets the vcollide data from cache pool by handle
// Input : *this - // Input : *this -
// handle - // handle -
// Output : a pointer to the studiohdr_t object // Output : a pointer to the vcollide_t object
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* cache, MDLHandle_t handle) vcollide_t* CMDLCache::GetVCollide(CMDLCache* const cache, const MDLHandle_t handle)
{ {
studiohdr_t* pStudioHdr = nullptr; // rax studiomodelcache_t* const modelCache = cache->GetModelCache(handle);
if (!handle) if (!IS_VALID_DATACACHE_HANDLE(modelCache))
{ {
pStudioHdr = GetErrorModel(); Warning(eDLL_T::ENGINE, "Attempted to load collision data on model \"%s\" with invalid studio data!\n", cache->GetModelName(handle));
if (!pStudioHdr) return nullptr;
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Attempted to load model with no handle and \"%s\" couldn't be loaded.\n", ERROR_MODEL);
return pStudioHdr;
} }
studiodata_t* pStudioData = cache->GetStudioData(handle); studiophysicsref_t* const physicsCache = modelCache->GetPhysicsCache();
DataCacheHandle_t dataCache = pStudioData->m_MDLCache;
if (dataCache && if (!physicsCache)
dataCache != DC_INVALID_HANDLE) return nullptr;
CStudioVCollide* const pVCollide = physicsCache->GetStudioVCollide();
if (!pVCollide)
return nullptr;
return pVCollide->GetVCollide();
}
//-----------------------------------------------------------------------------
// Purpose: gets the physics geometry data from cache pool by handle
// Input : *this -
// handle -
// Output : a pointer to the physics geometry descriptor
//-----------------------------------------------------------------------------
void* CMDLCache::GetPhysicsGeometry(CMDLCache* const cache, const MDLHandle_t handle)
{
studiomodelcache_t* const modelCache = cache->GetModelCache(handle);
if (!IS_VALID_DATACACHE_HANDLE(modelCache))
{ {
void* v4 = *(void**)(*((_QWORD*)dataCache + 1) + 24i64); Warning(eDLL_T::ENGINE, "Attempted to load physics geometry on model \"%s\" with invalid studio data!\n", cache->GetModelName(handle));
if (v4) return nullptr;
pStudioHdr = (studiohdr_t*)((char*)v4 + 0x10);
} }
return pStudioHdr;
studiophysicsref_t* const physicsRef = modelCache->GetPhysicsCache();
if (!physicsRef)
return nullptr;
CStudioPhysicsGeoms* const physicsGeoms = physicsRef->GetPhysicsGeoms();
if (!physicsGeoms)
return nullptr;
return physicsGeoms->GetGeometryData();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -250,52 +273,72 @@ studiohdr_t* CMDLCache::GetStudioHDR(CMDLCache* cache, MDLHandle_t handle)
// handle - // handle -
// Output : a pointer to the studiohwdata_t object // Output : a pointer to the studiohwdata_t object
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
studiohwdata_t* CMDLCache::GetHardwareData(CMDLCache* cache, MDLHandle_t handle) studiohwdata_t* CMDLCache::GetHardwareData(CMDLCache* const cache, const MDLHandle_t handle)
{ {
studiodata_t* pStudioData = cache->GetStudioData(handle); const studiodata_t* studioData = nullptr; cache->GetStudioData(handle);
const studiomodelcache_t* modelCache = cache->GetModelCache(handle);
if (!pStudioData) if (!IS_VALID_DATACACHE_HANDLE(modelCache))
{ {
if (!g_pMDLFallback->m_hErrorMDL) if (!HasErrorModel())
{ {
Error(eDLL_T::ENGINE, EXIT_FAILURE, "Studio hardware with handle \"%hu\" not found and \"%s\" couldn't be loaded.\n", handle, ERROR_MODEL); Error(eDLL_T::ENGINE, NO_ERROR, "Studio hardware for model \"%s\" not found and \"%s\" couldn't be loaded!\n",
cache->GetModelName(handle), ERROR_MODEL);
assert(0); // Should never be hit!
return nullptr; return nullptr;
} }
pStudioData = cache->GetStudioData(g_pMDLFallback->m_hErrorMDL); else
{
// Only spew the message once.
if (g_StudioMdlFallbackHandler.AddToSuppressionList(handle))
{
Warning(eDLL_T::ENGINE, "Studio hardware for model \"%s\" not found; replacing with \"%s\".\n",
cache->GetModelName(handle), ERROR_MODEL);
}
}
studioData = cache->GetStudioData(GetErrorModelHandle());
modelCache = studioData->GetModelCache();
} }
DataCacheHandle_t dataCache = pStudioData->m_MDLCache;
if (dataCache)
{
if (dataCache == DC_INVALID_HANDLE)
return nullptr;
void* pAnimData = (void*)*((_QWORD*)dataCache + 1);
AcquireSRWLockExclusive(g_pMDLLock);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
v_CStudioHWDataRef__SetFlags(reinterpret_cast<CStudioHWDataRef*>(pAnimData), 1i64); // !!! DECLARED INLINE IN < S3 !!!
#endif
ReleaseSRWLockExclusive(g_pMDLLock);
}
if ((pStudioData->m_nFlags & STUDIODATA_FLAGS_STUDIOMESH_LOADED))
return &pStudioData->m_pHardwareRef->m_HardwareData;
else else
return nullptr; {
studioData = cache->GetStudioData(handle);
}
studiophysicsref_t* const physicsRef = modelCache->GetPhysicsCache();
AcquireSRWLockExclusive(g_pMDLLock);
CMDLCache__CheckData(physicsRef, 1i64); // !!! DECLARED INLINE IN < S3 !!!
ReleaseSRWLockExclusive(g_pMDLLock);
if ((studioData->flags & STUDIODATA_FLAGS_STUDIOMESH_LOADED))
return studioData->GetHardwareDataRef()->GetHardwareData();
return nullptr;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: gets the error model // Purpose: gets the error model
// Output : *studiohdr_t
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
studiohdr_t* CMDLCache::GetErrorModel(void) studiohdr_t* CMDLCache::GetErrorModel(void)
{ {
// !TODO [AMOS]: mdl/error.rmdl fallback is not supported (yet) in the new GatherProps solution! return g_StudioMdlFallbackHandler.GetFallbackModelHeader();
if (!old_gather_props->GetBool()) }
old_gather_props->SetValue(true); const char* CMDLCache::GetErrorModelName(void)
{
const studiohdr_t* const errorStudioHdr = g_StudioMdlFallbackHandler.GetFallbackModelHeader();
assert(errorStudioHdr);
return g_pMDLFallback->m_pErrorHDR; return errorStudioHdr ? errorStudioHdr->name : "(invalid)";
}
MDLHandle_t CMDLCache::GetErrorModelHandle(void)
{
return g_StudioMdlFallbackHandler.GetFallbackModelHandle();
}
bool CMDLCache::HasErrorModel(void)
{
return g_StudioMdlFallbackHandler.HasFallbackModel();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -303,34 +346,20 @@ studiohdr_t* CMDLCache::GetErrorModel(void)
// Input : handle - // Input : handle -
// Output : true if exist, false otherwise // Output : true if exist, false otherwise
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool CMDLCache::IsKnownBadModel(MDLHandle_t handle) bool CMDLCache::IsKnownBadModel(const MDLHandle_t handle)
{ {
auto p = g_vBadMDLHandles.insert(handle); // Only adds if it didn't exist yet, else it returns false.
return !p.second; return g_StudioMdlFallbackHandler.AddBadModelHandle(handle);
} }
void VMDLCache::Attach() const void VMDLCache::Detour(const bool bAttach) const
{ {
DetourAttach((LPVOID*)&v_CMDLCache__FindMDL, &CMDLCache::FindMDL); DetourSetup(&CMDLCache__FindMDL, &CMDLCache::FindMDL, bAttach);
#ifdef GAMEDLL_S3 // !!! DECLARED INLINE WITH FINDMDL IN < S3 !!! DetourSetup(&CMDLCache__FindCachedMDL, &CMDLCache::FindCachedMDL, bAttach);
DetourAttach((LPVOID*)&v_CMDLCache__FindCachedMDL, &CMDLCache::FindCachedMDL); DetourSetup(&CMDLCache__FindUncachedMDL, &CMDLCache::FindUncachedMDL, bAttach);
DetourAttach((LPVOID*)&v_CMDLCache__FindUncachedMDL, &CMDLCache::FindUncachedMDL);
#endif // GAMEDLL_S3
#ifdef GAMEDLL_S3 // !TODO:
DetourAttach((LPVOID*)&v_CMDLCache__GetHardwareData, &CMDLCache::GetHardwareData);
DetourAttach((LPVOID*)&v_CMDLCache__GetStudioHDR, &CMDLCache::GetStudioHDR);
#endif
}
void VMDLCache::Detach() const DetourSetup(&CMDLCache__GetVCollide, &CMDLCache::GetVCollide, bAttach);
{ DetourSetup(&CMDLCache__GetPhysicsGeometry, &CMDLCache::GetPhysicsGeometry, bAttach);
DetourDetach((LPVOID*)&v_CMDLCache__FindMDL, &CMDLCache::FindMDL);
#ifdef GAMEDLL_S3 // !!! DECLARED INLINE WITH FINDMDL IN < S3 !!! DetourSetup(&CMDLCache__GetHardwareData, &CMDLCache::GetHardwareData, bAttach);
DetourDetach((LPVOID*)&v_CMDLCache__FindCachedMDL, &CMDLCache::FindCachedMDL); }
DetourDetach((LPVOID*)&v_CMDLCache__FindUncachedMDL, &CMDLCache::FindUncachedMDL);
#endif // GAMEDLL_S3
#ifdef GAMEDLL_S3 // !TODO:
DetourDetach((LPVOID*)&v_CMDLCache__GetHardwareData, &CMDLCache::GetHardwareData);
DetourDetach((LPVOID*)&v_CMDLCache__GetStudioHDR, &CMDLCache::GetStudioHDR);
#endif
}

View File

@ -2,104 +2,254 @@
#define MDLCACHE_H #define MDLCACHE_H
#include "tier0/threadtools.h" #include "tier0/threadtools.h"
#include "tier1/utldict.h" #include "tier1/utldict.h"
#include "tier1/refcount.h"
#include "datacache/idatacache.h" #include "datacache/idatacache.h"
#include "datacache/imdlcache.h" #include "datacache/imdlcache.h"
#include "public/studio.h" #include "public/studio.h"
#include "public/vphysics/phyfile.h"
#include "vphysics/physics_collide.h"
#include "public/rtech/ipakfile.h"
struct RStaticProp_t class CStudioFallbackHandler
{ {
studiohdr_t* m_pStudioHDR{}; public:
CStudioHWDataRef* m_pHardWareData{}; CStudioFallbackHandler(void)
const char* m_szPropName{}; : m_pFallbackHDR(nullptr)
uint8_t m_pUnknown[0x62]{}; , m_hFallbackMDL(NULL)
{}
// This must be cleared if 'common.rpak' is getting unloaded, as this pak
// contains the default fallback models!!!
inline void Clear(void)
{
m_pFallbackHDR = nullptr;
m_hFallbackMDL = NULL;
m_BadMdlHandles.clear();
}
inline bool HasFallbackModel() const
{
return !!m_hFallbackMDL;
}
inline void SetFallbackModel(studiohdr_t* const studioHdr, const MDLHandle_t handle)
{
m_pFallbackHDR = studioHdr;
m_hFallbackMDL = handle;
}
inline studiohdr_t* GetFallbackModelHeader() const
{
return m_pFallbackHDR;
}
inline MDLHandle_t GetFallbackModelHandle() const
{
return m_hFallbackMDL;
}
inline void EnableLegacyGatherProps()
{
if (!old_gather_props->GetBool())
old_gather_props->SetValue(true);
}
inline void DisableLegacyGatherProps()
{
if (old_gather_props->GetBool())
old_gather_props->SetValue(false);
}
inline bool AddBadModelHandle(const MDLHandle_t handle)
{
auto p = m_BadMdlHandles.insert(handle);
return !p.second;
}
inline void ClearBadModelHandleCache()
{
m_BadMdlHandles.clear();
}
inline bool HasInvalidModelHandles()
{
return !m_BadMdlHandles.empty();
}
inline bool AddToSuppressionList(const MDLHandle_t handle)
{
auto p = m_SuppressedHandles.insert(handle);
return p.second;
}
inline void ClearSuppresionList()
{
m_SuppressedHandles.clear();
}
private:
studiohdr_t* m_pFallbackHDR;
MDLHandle_t m_hFallbackMDL;
// Keep track of bad model handles so we don't log the
// same one twice or more to the console and cause a
// significant performance impact.
std::unordered_set<MDLHandle_t> m_BadMdlHandles;
// Don't spam on these handles when trying to get
// cache data.
std::unordered_set<MDLHandle_t> m_SuppressedHandles;
}; };
struct RMDLFallBack_t
struct CStudioVCollide : public CRefCounted<>
{ {
studiohdr_t* m_pErrorHDR; public:
studiohdr_t* m_pEmptyHDR; ~CStudioVCollide()
MDLHandle_t m_hErrorMDL;
MDLHandle_t m_hEmptyMDL;
RMDLFallBack_t(void)
: m_pErrorHDR(nullptr)
, m_pEmptyHDR(nullptr)
, m_hErrorMDL(NULL)
, m_hEmptyMDL(NULL)
{ {
PhysicsCollision()->VCollideUnload(&m_vcollide);
} }
vcollide_t* GetVCollide()
// This must be cleared if 'common.rpak' is getting unloaded!
void Clear(void)
{ {
m_pErrorHDR = nullptr; return &m_vcollide;
m_pEmptyHDR = nullptr;
m_hErrorMDL = NULL;
m_hEmptyMDL = NULL;
} }
private:
vcollide_t m_vcollide;
};
class CStudioPhysicsGeoms : public CRefCounted<>
{
public:
void* GetGeometryData() { return m_pGeomDataDesc; }
private:
// TODO: ptr to another ptr to geometry data; requires reversing.
void* m_pGeomDataDesc;
int unk2;
short unk3;
short unk4;
};
struct studiophysicsref_t
{
inline CStudioVCollide* GetStudioVCollide() const { return vCollide; }
inline CStudioPhysicsGeoms* GetPhysicsGeoms() const { return physicsGeoms; }
int unk0;
int unk1;
int unk2;
int unk3;
int unk4;
int unk5;
CStudioVCollide* vCollide;
CStudioPhysicsGeoms* physicsGeoms;
};
struct studiomodelcache_t
{
inline studiohdr_t* GetStudioHdr() const { return studioHeader; }
inline studiophysicsref_t* GetPhysicsCache() const { return physicsCache; }
studiohdr_t* studioHeader;
studiophysicsref_t* physicsCache;
const char* modelName;
char gap_18[8];
phyheader_t* physicsHeader;
void* unk_28;
void* staticPropData;
void* animRigs;
int numAnimRigs;
int unk_44;
int streamedDataSize;
char gap_4C[8];
int numAnimSeqs;
void* m_pAnimSeqs;
char gap_60[24];
};
struct studioanimcache_t
{
inline studiohdr_t* GetStudioHdr() const { return studioHdr; }
studiohdr_t* studioHdr;
const char* rigName;
int unk0;
int numSequences;
PakPage_t sequences;
int unk1;
int unk2;
}; };
// only models with type "mod_studio" have this data // only models with type "mod_studio" have this data
struct studiodata_t struct studiodata_t
{ {
DataCacheHandle_t m_MDLCache; inline studiomodelcache_t* GetModelCache() const { return modelCache; }
void* m_pAnimData; // !TODO: reverse struct. inline studioanimcache_t* GetAnimCache() const { return animCache; }
unsigned short m_nRefCount; inline CStudioHWDataRef* GetHardwareDataRef() const { return hardwareRef; }
unsigned short m_nFlags;
MDLHandle_t m_Handle; studiomodelcache_t* modelCache;
#ifndef GAMEDLL_S3 studioanimcache_t* animCache;
void* Unk1; // TODO: unverified! unsigned short refCount;
void* Unk2; // TODO: unverified! unsigned short flags;
#endif // !GAMEDLL_S3 MDLHandle_t modelHandle;
void* Unk3; // ptr to flags and model string. void* unkStruct; // TODO: reverse structure
CStudioHWDataRef* m_pHardwareRef; CStudioHWDataRef* hardwareRef;
void* m_pMaterialTable; // contains a large table of CMaterialGlue objects. void* materialTable; // contains a large table of CMaterialGlue objects.
int Unk5; int Unk5;
char pad[72]; char pad[72];
CThreadFastMutex m_Mutex; CThreadFastMutex mutex;
int m_nGuidLock; // always -1, set to 1 and 0 in CMDLCache::FindUncachedMDL. bool processing;
PakHandle_t pakHandle;
}; };
extern RMDLFallBack_t* g_pMDLFallback; extern CStudioFallbackHandler g_StudioMdlFallbackHandler;
extern std::unordered_set<MDLHandle_t> g_vBadMDLHandles;
class CMDLCache : public IMDLCache class CMDLCache : public CTier1AppSystem<IMDLCache>
{ {
public: public:
static studiohdr_t* FindMDL(CMDLCache* cache, MDLHandle_t handle, void* a3); static studiohdr_t* FindMDL(CMDLCache* const cache, const MDLHandle_t handle, void* a3);
static void FindCachedMDL(CMDLCache* cache, studiodata_t* pStudioData, void* a3); static void FindCachedMDL(CMDLCache* const cache, studiodata_t* const pStudioData, void* a3);
static studiohdr_t* FindUncachedMDL(CMDLCache* cache, MDLHandle_t handle, studiodata_t* pStudioData, void* a4); static studiohdr_t* FindUncachedMDL(CMDLCache* const cache, const MDLHandle_t handle, studiodata_t* const pStudioData, void* a4);
static studiohdr_t* GetStudioHDR(CMDLCache* cache, MDLHandle_t handle);
static studiohwdata_t* GetHardwareData(CMDLCache* cache, MDLHandle_t handle); studiomodelcache_t* GetModelCache(const MDLHandle_t handle);
static vcollide_t* GetVCollide(CMDLCache* const cache, const MDLHandle_t handle);
static void* GetPhysicsGeometry(CMDLCache* const cache, const MDLHandle_t handle);
static studiohwdata_t* GetHardwareData(CMDLCache* const cache, const MDLHandle_t handle);
static studiohdr_t* GetErrorModel(void); static studiohdr_t* GetErrorModel(void);
static bool IsKnownBadModel(MDLHandle_t handle); static const char* GetErrorModelName(void);
static MDLHandle_t GetErrorModelHandle(void);
static bool HasErrorModel(void);
static bool IsKnownBadModel(const MDLHandle_t handle);
studiodata_t* GetStudioData(MDLHandle_t handle) inline studiodata_t* GetStudioData(const MDLHandle_t handle)
{ {
EnterCriticalSection(&m_MDLMutex); EnterCriticalSection(&m_MDLMutex);
studiodata_t* pStudioData = m_MDLDict.Element(handle); studiodata_t* const studioData = m_MDLDict.Element(handle);
LeaveCriticalSection(&m_MDLMutex); LeaveCriticalSection(&m_MDLMutex);
return pStudioData; return studioData;
} }
const char* GetModelName(MDLHandle_t handle) inline const char* GetModelName(const MDLHandle_t handle)
{ {
EnterCriticalSection(&m_MDLMutex); EnterCriticalSection(&m_MDLMutex);
const char* szModelName = m_MDLDict.GetElementName(handle); const char* const modelName = m_MDLDict.GetElementName(handle);
LeaveCriticalSection(&m_MDLMutex); LeaveCriticalSection(&m_MDLMutex);
return szModelName; return modelName;
} }
void* GetMaterialTable(MDLHandle_t handle) inline void* GetMaterialTable(const MDLHandle_t handle)
{ {
EnterCriticalSection(&m_MDLMutex); EnterCriticalSection(&m_MDLMutex);
studiodata_t* pStudioData = m_MDLDict.Element(handle); studiodata_t* const studioData = m_MDLDict.Element(handle);
LeaveCriticalSection(&m_MDLMutex); LeaveCriticalSection(&m_MDLMutex);
return &pStudioData->m_pMaterialTable; return &studioData->materialTable;
} }
private: private:
@ -108,24 +258,16 @@ private:
// !TODO: reverse the rest // !TODO: reverse the rest
}; };
inline CMemory p_CMDLCache__FindMDL; inline studiohdr_t*(*CMDLCache__FindMDL)(CMDLCache* const pCache, const MDLHandle_t handle, void* a3);
inline studiohdr_t*(*v_CMDLCache__FindMDL)(CMDLCache* pCache, void* a2, void* a3); inline void(*CMDLCache__FindCachedMDL)(CMDLCache* const pCache, studiodata_t* const pStudioData, void* a3);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2) inline studiohdr_t*(*CMDLCache__FindUncachedMDL)(CMDLCache* const pCache, MDLHandle_t handle, studiodata_t* const pStudioData, void* a4);
inline CMemory p_CMDLCache__FindCachedMDL;
inline void(*v_CMDLCache__FindCachedMDL)(CMDLCache* pCache, void* a2, void* a3);
inline CMemory p_CMDLCache__FindUncachedMDL; inline vcollide_t*(*CMDLCache__GetVCollide)(CMDLCache* const pCache, const MDLHandle_t handle);
inline studiohdr_t*(*v_CMDLCache__FindUncachedMDL)(CMDLCache* pCache, MDLHandle_t handle, void* a3, void* a4); inline void* (*CMDLCache__GetPhysicsGeometry)(CMDLCache* const pCache, const MDLHandle_t handle);
#endif
inline CMemory p_CMDLCache__GetStudioHDR; inline studiohwdata_t* (*CMDLCache__GetHardwareData)(CMDLCache* const pCache, const MDLHandle_t handle);
inline studiohdr_t*(*v_CMDLCache__GetStudioHDR)(CMDLCache* pCache, MDLHandle_t handle); inline bool(*CMDLCache__CheckData)(void* const ref, const int64_t type); // Probably incorrect name.
inline CMemory p_CMDLCache__GetHardwareData;
inline studiohwdata_t*(*v_CMDLCache__GetHardwareData)(CMDLCache* pCache, MDLHandle_t handle);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
inline CMemory p_CStudioHWDataRef__SetFlags; // Probably incorrect.
inline bool(*v_CStudioHWDataRef__SetFlags)(CStudioHWDataRef* ref, int64_t flags);
#endif
inline CMDLCache* g_pMDLCache = nullptr; inline CMDLCache* g_pMDLCache = nullptr;
inline PSRWLOCK g_pMDLLock = nullptr; // Possibly a member? research required. inline PSRWLOCK g_pMDLLock = nullptr; // Possibly a member? research required.
@ -134,54 +276,26 @@ class VMDLCache : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CMDLCache::FindMDL", p_CMDLCache__FindMDL.GetPtr()); LogFunAdr("CMDLCache::FindMDL", CMDLCache__FindMDL);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2) LogFunAdr("CMDLCache::FindCachedMDL", CMDLCache__FindCachedMDL);
LogFunAdr("CMDLCache::FindCachedMDL", p_CMDLCache__FindCachedMDL.GetPtr()); LogFunAdr("CMDLCache::FindUncachedMDL", CMDLCache__FindUncachedMDL);
LogFunAdr("CMDLCache::FindUncachedMDL", p_CMDLCache__FindUncachedMDL.GetPtr()); LogFunAdr("CMDLCache::GetVCollide", CMDLCache__GetVCollide);
#endif LogFunAdr("CMDLCache::GetPhysicsGeometry", CMDLCache__GetPhysicsGeometry);
LogFunAdr("CMDLCache::GetStudioHDR", p_CMDLCache__GetStudioHDR.GetPtr()); LogFunAdr("CMDLCache::GetHardwareData", CMDLCache__GetHardwareData);
LogFunAdr("CMDLCache::GetHardwareData", p_CMDLCache__GetHardwareData.GetPtr()); LogFunAdr("CMDLCache::CheckData", CMDLCache__CheckData);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
LogFunAdr("CStudioHWDataRef::SetFlags", p_CStudioHWDataRef__SetFlags.GetPtr()); LogVarAdr("g_MDLCache", g_pMDLCache);
#endif LogVarAdr("g_MDLLock", g_pMDLLock);
LogVarAdr("g_MDLCache", reinterpret_cast<uintptr_t>(g_pMDLCache));
LogVarAdr("g_MDLLock", reinterpret_cast<uintptr_t>(g_pMDLLock));
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2) g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F1 0F B7 EA").GetPtr(CMDLCache__FindMDL);
p_CMDLCache__FindMDL = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 20 4C 8B F1 0F B7 DA"); g_GameDll.FindPatternSIMD("4D 85 C0 74 7A 48 89 6C 24 ??").GetPtr(CMDLCache__FindCachedMDL);
v_CMDLCache__FindMDL = p_CMDLCache__FindMDL.RCast<studiohdr_t* (*)(CMDLCache*, void*, void*)>(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC 20 4C 8B F1 0F B7 DA*/ g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 20 48 8B E9 0F B7 FA").GetPtr(CMDLCache__FindUncachedMDL);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8D 0D ?? ?? ?? ?? 0F B7 DA FF 15 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8D 14 5B 48 8D 0D ?? ?? ?? ?? 48 8B 7C D0 ?? FF 15 ?? ?? ?? ?? 48 8B 1F").GetPtr(CMDLCache__GetHardwareData);
p_CMDLCache__GetStudioHDR = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F1 0F B7 FA 48 8D 0D ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8D 0D ?? ?? ?? ?? 0F B7 DA FF 15 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8D 14 5B 48 8D 0D ?? ?? ?? ?? 48 8B 5C D0 ?? FF 15 ?? ?? ?? ?? 48 8B 03 48 8B 48 08").GetPtr(CMDLCache__GetVCollide);
v_CMDLCache__GetStudioHDR = p_CMDLCache__GetStudioHDR.RCast<studiohdr_t* (*)(CMDLCache*, MDLHandle_t)>(); /*48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B F1 0F B7 FA 48 8D 0D ? ? ? ?*/ g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 B8 ?? ?? ?? ?? 0F B7 DA").GetPtr(CMDLCache__GetPhysicsGeometry);
g_GameDll.FindPatternSIMD("48 83 EC 08 4C 8D 14 12").GetPtr(CMDLCache__CheckData);
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
p_CMDLCache__GetHardwareData = g_GameDll.FindPatternSIMD("40 56 48 83 EC 20 48 89 5C 24 ?? 48 8D 0D ?? ?? ?? ??");
v_CMDLCache__GetHardwareData = p_CMDLCache__GetHardwareData.RCast<studiohwdata_t* (*)(CMDLCache*, MDLHandle_t)>(); /*40 56 48 83 EC 20 48 89 5C 24 ? 48 8D 0D ? ? ? ?*/
#else
p_CMDLCache__GetHardwareData = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8D 0D ?? ?? ?? ?? 0F B7 DA FF 15 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8D 14 5B 48 8D 0D ?? ?? ?? ?? 48 8B 7C D0 ?? FF 15 ?? ?? ?? ?? 48 8B 1F");
v_CMDLCache__GetHardwareData = p_CMDLCache__GetHardwareData.RCast<studiohwdata_t* (*)(CMDLCache*, MDLHandle_t)>(); /*48 89 5C 24 ? 57 48 83 EC 20 48 8D 0D ? ? ? ? 0F B7 DA FF 15 ? ? ? ? 48 8B 05 ? ? ? ? 48 8D 14 5B 48 8D 0D ? ? ? ? 48 8B 7C D0 ? FF 15 ? ? ? ? 48 8B 1F*/
#endif
#else
p_CMDLCache__FindMDL = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F1 0F B7 EA");
v_CMDLCache__FindMDL = p_CMDLCache__FindMDL.RCast<studiohdr_t* (*)(CMDLCache*, void*, void*)>(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B F1 0F B7 EA*/
p_CMDLCache__FindCachedMDL = g_GameDll.FindPatternSIMD("4D 85 C0 74 7A 48 89 6C 24 ??");
v_CMDLCache__FindCachedMDL = p_CMDLCache__FindCachedMDL.RCast<void(*)(CMDLCache*, void*, void*)>(); /*4D 85 C0 74 7A 48 89 6C 24 ?*/
p_CMDLCache__FindUncachedMDL = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 20 48 8B E9 0F B7 FA");
v_CMDLCache__FindUncachedMDL = p_CMDLCache__FindUncachedMDL.RCast<studiohdr_t* (*)(CMDLCache*, MDLHandle_t, void*, void*)>(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC 20 48 8B E9 0F B7 FA*/
p_CMDLCache__GetStudioHDR = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8D 0D ?? ?? ?? ?? 0F B7 DA FF 15 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8D 14 5B 48 8D 0D ?? ?? ?? ?? 48 8B 5C D0 ?? FF 15 ?? ?? ?? ?? 48 8B 03 48 8B 48 08");
v_CMDLCache__GetStudioHDR = p_CMDLCache__GetStudioHDR.RCast<studiohdr_t* (*)(CMDLCache*, MDLHandle_t)>(); /*40 53 48 83 EC 20 48 8D 0D ? ? ? ? 0F B7 DA FF 15 ? ? ? ? 48 8B 05 ? ? ? ? 48 8D 14 5B 48 8D 0D ? ? ? ? 48 8B 5C D0 ? FF 15 ? ? ? ? 48 8B 03 48 8B 48 08*/
p_CMDLCache__GetHardwareData = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8D 0D ?? ?? ?? ?? 0F B7 DA FF 15 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8D 14 5B 48 8D 0D ?? ?? ?? ?? 48 8B 7C D0 ?? FF 15 ?? ?? ?? ?? 48 8B 1F");
v_CMDLCache__GetHardwareData = p_CMDLCache__GetHardwareData.RCast<studiohwdata_t* (*)(CMDLCache*, MDLHandle_t)>(); /*48 89 5C 24 ? 57 48 83 EC 20 48 8D 0D ? ? ? ? 0F B7 DA FF 15 ? ? ? ? 48 8B 05 ? ? ? ? 48 8D 14 5B 48 8D 0D ? ? ? ? 48 8B 7C D0 ? FF 15 ? ? ? ? 48 8B 1F*/
p_CStudioHWDataRef__SetFlags = g_GameDll.FindPatternSIMD("48 83 EC 08 4C 8D 14 12");
v_CStudioHWDataRef__SetFlags = p_CStudioHWDataRef__SetFlags.RCast<bool (*)(CStudioHWDataRef*, int64_t)>(); /*48 83 EC 08 4C 8D 14 12*/
#endif
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
@ -189,11 +303,10 @@ class VMDLCache : public IDetour
g_pMDLCache = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 0F 45 C8 FF 05 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ??") g_pMDLCache = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 0F 45 C8 FF 05 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ??")
.FindPatternSelf("48 8D 05").ResolveRelativeAddressSelf(0x3, 0x7).RCast<CMDLCache*>(); .FindPatternSelf("48 8D 05").ResolveRelativeAddressSelf(0x3, 0x7).RCast<CMDLCache*>();
g_pMDLLock = p_CMDLCache__GetHardwareData.Offset(0x35).FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<PSRWLOCK>(); g_pMDLLock = CMemory(CMDLCache__GetHardwareData).Offset(0x35).FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<PSRWLOCK>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -1,12 +1,7 @@
#pragma once #pragma once
inline CMemory p_EbisuSDK_Tier0_Init;
inline void(*EbisuSDK_Tier0_Init)(void); inline void(*EbisuSDK_Tier0_Init)(void);
inline CMemory p_EbisuSDK_CVar_Init;
inline void(*EbisuSDK_CVar_Init)(void); inline void(*EbisuSDK_CVar_Init)(void);
inline CMemory p_EbisuSDK_SetState;
inline void(*EbisuSDK_SetState)(void); inline void(*EbisuSDK_SetState)(void);
inline uint64_t* g_NucleusID = nullptr; inline uint64_t* g_NucleusID = nullptr;
@ -26,42 +21,32 @@ class VEbisuSDK : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("EbisuSDK_Tier0_Init", p_EbisuSDK_Tier0_Init.GetPtr()); LogFunAdr("EbisuSDK_Tier0_Init", EbisuSDK_Tier0_Init);
LogFunAdr("EbisuSDK_CVar_Init", p_EbisuSDK_CVar_Init.GetPtr()); LogFunAdr("EbisuSDK_CVar_Init", EbisuSDK_CVar_Init);
LogFunAdr("EbisuSDK_SetState", p_EbisuSDK_SetState.GetPtr()); LogFunAdr("EbisuSDK_SetState", EbisuSDK_SetState);
LogVarAdr("g_NucleusID", reinterpret_cast<uintptr_t>(g_NucleusID)); LogVarAdr("g_NucleusID", g_NucleusID);
LogVarAdr("g_NucleusToken", reinterpret_cast<uintptr_t>(g_NucleusToken)); LogVarAdr("g_NucleusToken", g_NucleusToken);
LogVarAdr("g_OriginAuthCode", reinterpret_cast<uintptr_t>(g_OriginAuthCode)); LogVarAdr("g_OriginAuthCode", g_OriginAuthCode);
LogVarAdr("g_OriginErrorLevel", reinterpret_cast<uintptr_t>(g_OriginErrorLevel)); LogVarAdr("g_OriginErrorLevel", g_OriginErrorLevel);
LogVarAdr("g_EbisuProfileInit", reinterpret_cast<uintptr_t>(g_EbisuProfileInit)); LogVarAdr("g_EbisuProfileInit", g_EbisuProfileInit);
LogVarAdr("g_EbisuSDKInit", reinterpret_cast<uintptr_t>(g_EbisuSDKInit)); LogVarAdr("g_EbisuSDKInit", g_EbisuSDKInit);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_EbisuSDK_Tier0_Init = g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 0F 85 ?? 02 ?? ?? 48 89 5C 24 20"); g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 0F 85 ?? 02 ?? ?? 48 89 5C 24 20").GetPtr(EbisuSDK_Tier0_Init);
EbisuSDK_Tier0_Init = p_EbisuSDK_Tier0_Init.RCast<void(*)(void)>(); /*48 83 EC 28 80 3D ?? ?? ?? ?? 00 0F 85 ?? 02 00 00 48 89 5C 24 20*/ g_GameDll.FindPatternSIMD("40 57 48 83 EC 40 83 3D").GetPtr(EbisuSDK_CVar_Init);
g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 5B").GetPtr(EbisuSDK_SetState);
p_EbisuSDK_CVar_Init = g_GameDll.FindPatternSIMD("40 57 48 83 EC 40 83 3D");
EbisuSDK_CVar_Init = p_EbisuSDK_CVar_Init.RCast<void(*)(void)>(); /*40 57 48 83 EC 40 83 3D*/
p_EbisuSDK_SetState = g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 5B");
EbisuSDK_SetState = p_EbisuSDK_SetState.RCast<void(*)(void)>(); /*48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 5B*/
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
g_NucleusID = p_EbisuSDK_CVar_Init.Offset(0x20).FindPatternSelf("4C 89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<uint64_t*>(); g_NucleusID = CMemory(EbisuSDK_CVar_Init).Offset(0x20).FindPatternSelf("4C 89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<uint64_t*>();
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_NucleusToken = CMemory(EbisuSDK_SetState).Offset(0x1EF).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<char*>();
g_NucleusToken = p_EbisuSDK_SetState.Offset(0x1EF).FindPatternSelf("38 1D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<char*>(); // !TODO: TEST! g_OriginAuthCode = CMemory(EbisuSDK_SetState).Offset(0x1BF).FindPatternSelf("0F B6", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<char*>();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) g_OriginErrorLevel = CMemory(EbisuSDK_SetState).Offset(0x20).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
g_NucleusToken = p_EbisuSDK_SetState.Offset(0x1EF).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<char*>(); g_EbisuProfileInit = CMemory(EbisuSDK_CVar_Init).Offset(0x12A).FindPatternSelf("C6 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
#endif g_EbisuSDKInit = CMemory(EbisuSDK_Tier0_Init).Offset(0x0).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
g_OriginAuthCode = p_EbisuSDK_SetState.Offset(0x1BF).FindPatternSelf("0F B6", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<char*>();
g_OriginErrorLevel = p_EbisuSDK_SetState.Offset(0x20).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
g_EbisuProfileInit = p_EbisuSDK_CVar_Init.Offset(0x12A).FindPatternSelf("C6 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
g_EbisuSDKInit = p_EbisuSDK_Tier0_Init.Offset(0x0).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -26,7 +26,16 @@ add_sources( SOURCE_GROUP "Debug"
"debugoverlay.h" "debugoverlay.h"
) )
add_sources( SOURCE_GROUP "Input"
"keys.cpp"
"keys.h"
)
add_sources( SOURCE_GROUP "Render" add_sources( SOURCE_GROUP "Render"
"framelimit.cpp"
"framelimit.h"
"gl_drawlights.cpp"
"gl_drawlights.h"
"gl_matsysiface.h" "gl_matsysiface.h"
"gl_model_private.h" "gl_model_private.h"
"gl_rmain.cpp" "gl_rmain.cpp"
@ -127,6 +136,8 @@ add_sources( SOURCE_GROUP "Shared"
"shared/base_rcon.h" "shared/base_rcon.h"
"shared/shared_rcon.cpp" "shared/shared_rcon.cpp"
"shared/shared_rcon.h" "shared/shared_rcon.h"
"shared/datablock.cpp"
"shared/datablock.h"
) )
if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" ) if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" )
@ -150,6 +161,11 @@ add_sources( SOURCE_GROUP "GameUI"
"${ENGINE_SOURCE_DIR}/gameui/IBrowser.h" "${ENGINE_SOURCE_DIR}/gameui/IBrowser.h"
"${ENGINE_SOURCE_DIR}/gameui/IConsole.cpp" "${ENGINE_SOURCE_DIR}/gameui/IConsole.cpp"
"${ENGINE_SOURCE_DIR}/gameui/IConsole.h" "${ENGINE_SOURCE_DIR}/gameui/IConsole.h"
"${ENGINE_SOURCE_DIR}/gameui/imgui_system.cpp"
"${ENGINE_SOURCE_DIR}/gameui/imgui_system.h"
"${ENGINE_SOURCE_DIR}/gameui/imgui_surface.cpp"
"${ENGINE_SOURCE_DIR}/gameui/imgui_surface.h"
) )
endif() endif()
@ -185,6 +201,7 @@ add_sources( SOURCE_GROUP "Common"
"${ENGINE_SOURCE_DIR}/common/qlimits.h" "${ENGINE_SOURCE_DIR}/common/qlimits.h"
"${ENGINE_SOURCE_DIR}/common/sdkdefs.h" "${ENGINE_SOURCE_DIR}/common/sdkdefs.h"
"${ENGINE_SOURCE_DIR}/common/x86defs.h" "${ENGINE_SOURCE_DIR}/common/x86defs.h"
"${ENGINE_SOURCE_DIR}/common/xbox/xboxstubs.h"
) )
file( GLOB ENGINE_PUBLIC_HEADERS file( GLOB ENGINE_PUBLIC_HEADERS
@ -197,10 +214,8 @@ add_sources( SOURCE_GROUP "Public"
"${ENGINE_SOURCE_DIR}/public/dt_send.h" "${ENGINE_SOURCE_DIR}/public/dt_send.h"
"${ENGINE_SOURCE_DIR}/public/dt_recv.h" "${ENGINE_SOURCE_DIR}/public/dt_recv.h"
"${ENGINE_SOURCE_DIR}/public/datamap.h" "${ENGINE_SOURCE_DIR}/public/datamap.h"
"${ENGINE_SOURCE_DIR}/public/idatablock.h"
"${ENGINE_SOURCE_DIR}/public/idebugoverlay.h" "${ENGINE_SOURCE_DIR}/public/idebugoverlay.h"
"${ENGINE_SOURCE_DIR}/public/iengine.h" "${ENGINE_SOURCE_DIR}/public/iengine.h"
"${ENGINE_SOURCE_DIR}/public/igame.h"
"${ENGINE_SOURCE_DIR}/public/iserver.h" "${ENGINE_SOURCE_DIR}/public/iserver.h"
"${ENGINE_SOURCE_DIR}/public/isnapshotmgr.h" "${ENGINE_SOURCE_DIR}/public/isnapshotmgr.h"
"${ENGINE_SOURCE_DIR}/public/inetchannel.h" "${ENGINE_SOURCE_DIR}/public/inetchannel.h"
@ -220,7 +235,6 @@ if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" )
add_sources( SOURCE_GROUP "Public" add_sources( SOURCE_GROUP "Public"
"${ENGINE_SOURCE_DIR}/public/client_class.h" "${ENGINE_SOURCE_DIR}/public/client_class.h"
"${ENGINE_SOURCE_DIR}/public/ivrenderview.h" "${ENGINE_SOURCE_DIR}/public/ivrenderview.h"
"${ENGINE_SOURCE_DIR}/public/isurfacesystem.h" # ImGui surface
) )
endif() endif()
@ -236,6 +250,11 @@ target_compile_definitions( ${PROJECT_NAME} PRIVATE
) )
endif() endif()
target_include_directories( ${PROJECT_NAME} PRIVATE
"${THIRDPARTY_SOURCE_DIR}/recast/"
"${THIRDPARTY_SOURCE_DIR}/mbedtls/include"
)
endmacro() endmacro()
add_engine_project( "engine" ) add_engine_project( "engine" )

View File

@ -10,18 +10,78 @@
#include "engine/net_chan.h" #include "engine/net_chan.h"
#include "engine/client/cl_rcon.h" #include "engine/client/cl_rcon.h"
#include "networksystem/bansystem.h" #include "networksystem/bansystem.h"
#include "vpc/keyvalues.h" #include "tier1/keyvalues.h"
#include "windows/id3dx.h"
#include "geforce/reflex.h"
#include "vengineclient_impl.h" #include "vengineclient_impl.h"
#include "cdll_engine_int.h" #include "cdll_engine_int.h"
#ifndef DEDICATED
#include "materialsystem/cmaterialsystem.h"
#endif // !DEDICATED
/*****************************************************************************/ /*****************************************************************************/
#ifndef DEDICATED #ifndef DEDICATED
//-----------------------------------------------------------------------------
// Purpose: pre frame stage notify hook
//-----------------------------------------------------------------------------
void FrameStageNotify_Pre(const ClientFrameStage_t frameStage)
{
switch (frameStage)
{
case ClientFrameStage_t::FRAME_START:
break;
case ClientFrameStage_t::FRAME_NET_UPDATE_START:
break;
case ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_START:
break;
case ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_END:
break;
case ClientFrameStage_t::FRAME_NET_UPDATE_END:
break;
case ClientFrameStage_t::FRAME_RENDER_START:
break;
case ClientFrameStage_t::FRAME_RENDER_END:
break;
case ClientFrameStage_t::FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE:
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: post frame stage notify hook
//-----------------------------------------------------------------------------
void FrameStageNotify_Post(const ClientFrameStage_t frameStage)
{
switch (frameStage)
{
case ClientFrameStage_t::FRAME_START:
break;
case ClientFrameStage_t::FRAME_NET_UPDATE_START:
break;
case ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_START:
break;
case ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_END:
break;
case ClientFrameStage_t::FRAME_NET_UPDATE_END:
break;
case ClientFrameStage_t::FRAME_RENDER_START:
break;
case ClientFrameStage_t::FRAME_RENDER_END:
GFX_SetLatencyMarker(D3D11Device(), SIMULATION_END, MaterialSystem()->GetCurrentFrameCount());
break;
case ClientFrameStage_t::FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE:
break;
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: // Purpose:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CHLClient::FrameStageNotify(CHLClient* pHLClient, ClientFrameStage_t frameStage) void CHLClient::FrameStageNotify(CHLClient* pHLClient, ClientFrameStage_t frameStage)
{ {
CHLClient_FrameStageNotify(pHLClient, frameStage); FrameStageNotify_Pre(frameStage);
CHLClient__FrameStageNotify(pHLClient, frameStage);
FrameStageNotify_Post(frameStage);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -31,21 +91,14 @@ void CHLClient::FrameStageNotify(CHLClient* pHLClient, ClientFrameStage_t frameS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ClientClass* CHLClient::GetAllClasses() ClientClass* CHLClient::GetAllClasses()
{ {
return CHLClient_GetAllClasses(); return CHLClient__GetAllClasses();
} }
#endif // !DEDICATED #endif // !DEDICATED
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VDll_Engine_Int::Attach() const void VDll_Engine_Int::Detour(const bool bAttach) const
{ {
#ifndef DEDICATED #ifndef DEDICATED
DetourAttach((LPVOID*)&CHLClient_FrameStageNotify, &CHLClient::FrameStageNotify); DetourSetup(&CHLClient__FrameStageNotify, &CHLClient::FrameStageNotify, bAttach);
#endif // !DEDICATED
}
void VDll_Engine_Int::Detach() const
{
#ifndef DEDICATED
DetourDetach((LPVOID*)&CHLClient_FrameStageNotify, &CHLClient::FrameStageNotify);
#endif // !DEDICATED #endif // !DEDICATED
} }

View File

@ -10,7 +10,7 @@ enum class ClientFrameStage_t : int
FRAME_UNDEFINED = -1, // (haven't run any frames yet) FRAME_UNDEFINED = -1, // (haven't run any frames yet)
FRAME_START, FRAME_START,
// A network packet is being recieved // A network packet is being received
FRAME_NET_UPDATE_START, FRAME_NET_UPDATE_START,
// Data has been received and we're going to start calling PostDataUpdate // Data has been received and we're going to start calling PostDataUpdate
FRAME_NET_UPDATE_POSTDATAUPDATE_START, FRAME_NET_UPDATE_POSTDATAUPDATE_START,
@ -51,20 +51,11 @@ public:
/* ==== CHLCLIENT ======================================================================================================================================================= */ /* ==== CHLCLIENT ======================================================================================================================================================= */
#ifndef DEDICATED #ifndef DEDICATED
inline CMemory p_CHLClient_PostInit; inline void*(*CHLClient__PostInit)(void);
inline void*(*CHLClient_PostInit)(void); inline void*(*CHLClient__LevelShutdown)(CHLClient* thisptr);
inline void(*CHLClient__HudProcessInput)(CHLClient* thisptr, bool bActive);
inline CMemory p_CHLClient_LevelShutdown; inline void(*CHLClient__FrameStageNotify)(CHLClient* thisptr, ClientFrameStage_t frameStage);
inline void*(*CHLClient_LevelShutdown)(CHLClient* thisptr); inline ClientClass*(*CHLClient__GetAllClasses)();
inline CMemory p_CHLClient_HudProcessInput;
inline void(*CHLClient_HudProcessInput)(CHLClient* thisptr, bool bActive);
inline CMemory p_CHLClient_FrameStageNotify;
inline void(*CHLClient_FrameStageNotify)(CHLClient* thisptr, ClientFrameStage_t frameStage);
inline CMemory p_CHLClient_GetAllClasses;
inline ClientClass*(*CHLClient_GetAllClasses)();
#endif // !DEDICATED #endif // !DEDICATED
inline CHLClient* g_pHLClient = nullptr; inline CHLClient* g_pHLClient = nullptr;
@ -76,39 +67,25 @@ class VDll_Engine_Int : public IDetour
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
#ifndef DEDICATED #ifndef DEDICATED
LogFunAdr("CHLClient::PostInit", p_CHLClient_PostInit.GetPtr()); LogFunAdr("CHLClient::PostInit", CHLClient__PostInit);
LogFunAdr("CHLClient::LevelShutdown", p_CHLClient_LevelShutdown.GetPtr()); LogFunAdr("CHLClient::LevelShutdown", CHLClient__LevelShutdown);
LogFunAdr("CHLClient::HudProcessInput", p_CHLClient_HudProcessInput.GetPtr()); LogFunAdr("CHLClient::HudProcessInput", CHLClient__HudProcessInput);
LogFunAdr("CHLClient::FrameStageNotify", p_CHLClient_FrameStageNotify.GetPtr()); LogFunAdr("CHLClient::FrameStageNotify", CHLClient__FrameStageNotify);
LogFunAdr("CHLClient::GetAllClasses", p_CHLClient_GetAllClasses.GetPtr()); LogFunAdr("CHLClient::GetAllClasses", CHLClient__GetAllClasses);
#endif // !DEDICATED #endif // !DEDICATED
LogVarAdr("g_HLClient", reinterpret_cast<uintptr_t>(g_pHLClient)); LogVarAdr("g_HLClient", g_pHLClient);
LogVarAdr("g_pHLClient", reinterpret_cast<uintptr_t>(g_ppHLClient)); LogVarAdr("g_pHLClient", g_ppHLClient);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
p_CHLClient_LevelShutdown = g_GameDll.FindPatternSIMD("40 53 56 41 54 41 56 48 83 EC 28 48 8B F1");
#ifndef DEDICATED #ifndef DEDICATED
p_CHLClient_PostInit = g_GameDll.FindPatternSIMD("48 83 3D ?? ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 48 8D 0D ?? ?? ?? ??").GetPtr(CHLClient__LevelShutdown);
p_CHLClient_FrameStageNotify = g_GameDll.FindPatternSIMD("48 83 EC 38 89 15 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 83 EC 28 48 83 3D ?? ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ??").GetPtr(CHLClient__PostInit);
p_CHLClient_GetAllClasses = g_GameDll.FindPatternSIMD("48 8B 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 89 74 24 ??"); g_GameDll.FindPatternSIMD("48 83 EC 28 89 15 ?? ?? ?? ??").GetPtr(CHLClient__FrameStageNotify);
g_GameDll.FindPatternSIMD("48 8B 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ??").GetPtr(CHLClient__GetAllClasses);
#endif // !DEDICATED #endif // !DEDICATED
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
#ifndef DEDICATED #ifndef DEDICATED
p_CHLClient_LevelShutdown = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 48 8D 0D ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 83 EC 28 0F B6 0D ?? ?? ?? ?? 88 15 ?? ?? ?? ??").GetPtr(CHLClient__HudProcessInput);
p_CHLClient_PostInit = g_GameDll.FindPatternSIMD("48 83 EC 28 48 83 3D ?? ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ??");
p_CHLClient_FrameStageNotify = g_GameDll.FindPatternSIMD("48 83 EC 28 89 15 ?? ?? ?? ??");
p_CHLClient_GetAllClasses = g_GameDll.FindPatternSIMD("48 8B 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ??");
#endif // !DEDICATED
#endif
#ifndef DEDICATED
p_CHLClient_HudProcessInput = g_GameDll.FindPatternSIMD("48 83 EC 28 0F B6 0D ?? ?? ?? ?? 88 15 ?? ?? ?? ??");
CHLClient_LevelShutdown = p_CHLClient_LevelShutdown.RCast<void*(*)(CHLClient*)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 48 8D 0D ?? ?? ?? ??*/
CHLClient_PostInit = p_CHLClient_PostInit.RCast<void*(*)(void)>(); /*48 83 EC 28 48 83 3D ?? ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ??*/
CHLClient_FrameStageNotify = p_CHLClient_FrameStageNotify.RCast<void(*)(CHLClient*, ClientFrameStage_t)>(); /*48 83 EC 28 89 15 ?? ?? ?? ??*/
CHLClient_HudProcessInput = p_CHLClient_HudProcessInput.RCast<void(*)(CHLClient*, bool)>(); /*48 83 EC 28 0F B6 0D ?? ?? ?? ?? 88 15 ?? ?? ?? ??*/
CHLClient_GetAllClasses = p_CHLClient_GetAllClasses.RCast<ClientClass*(*)()>(); /*48 8B 05 ? ? ? ? C3 CC CC CC CC CC CC CC CC 48 8B 05 ? ? ? ? 48 8D 0D ? ? ? ?*/
#endif // !DEDICATED #endif // !DEDICATED
} }
virtual void GetVar(void) const virtual void GetVar(void) const
@ -120,7 +97,6 @@ class VDll_Engine_Int : public IDetour
.FindPatternSelf("4C 8B", CMemory::Direction::DOWN, 512, 2).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CHLClient**>(); .FindPatternSelf("4C 8B", CMemory::Direction::DOWN, 512, 2).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CHLClient**>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -1,7 +1,6 @@
#ifndef CL_ENTS_PARSE_H #ifndef CL_ENTS_PARSE_H
#define CL_ENTS_PARSE_H #define CL_ENTS_PARSE_H
inline CMemory p_CL_CopyExistingEntity;
inline bool(*v_CL_CopyExistingEntity)(__int64 a1, unsigned int* a2, char* a3); inline bool(*v_CL_CopyExistingEntity)(__int64 a1, unsigned int* a2, char* a3);
bool CL_CopyExistingEntity(__int64 a1, unsigned int* a2, char* a3); bool CL_CopyExistingEntity(__int64 a1, unsigned int* a2, char* a3);
@ -10,22 +9,17 @@ class V_CL_Ents_Parse : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CL_CopyExistingEntity", p_CL_CopyExistingEntity.GetPtr()); LogFunAdr("CL_CopyExistingEntity", v_CL_CopyExistingEntity);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_CL_CopyExistingEntity = g_GameDll.FindPatternSIMD("40 53 48 83 EC 70 4C 63 51 28"); g_GameDll.FindPatternSIMD("40 53 48 83 EC 70 4C 63 51 28").GetPtr(v_CL_CopyExistingEntity);
v_CL_CopyExistingEntity = p_CL_CopyExistingEntity.RCast<bool (*)(__int64, unsigned int*, char*)>(); /*40 53 48 83 EC 70 4C 63 51 28*/
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const virtual void Detour(const bool bAttach) const
{ {
DetourAttach((LPVOID*)&v_CL_CopyExistingEntity, &CL_CopyExistingEntity); DetourSetup(&v_CL_CopyExistingEntity, &CL_CopyExistingEntity, bAttach);
}
virtual void Detach(void) const
{
DetourDetach((LPVOID*)&v_CL_CopyExistingEntity, &CL_CopyExistingEntity);
} }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -10,6 +10,8 @@
#include "cl_main.h" #include "cl_main.h"
#include "engine/net.h" #include "engine/net.h"
#include "cdll_engine_int.h" #include "cdll_engine_int.h"
#include "windows/id3dx.h"
#include "geforce/reflex.h"
static float s_lastMovementCall = 0.0; static float s_lastMovementCall = 0.0;
static float s_LastFrameTime = 0.0; static float s_LastFrameTime = 0.0;
@ -17,9 +19,9 @@ static float s_LastFrameTime = 0.0;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: run client's movement frame // Purpose: run client's movement frame
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void H_CL_Move() void CL_MoveEx()
{ {
CClientState* cl = GetBaseLocalClient(); CClientState* const cl = GetBaseLocalClient();
if (!cl->IsConnected()) if (!cl->IsConnected())
return; return;
@ -40,15 +42,15 @@ void H_CL_Move()
const float hostTimeScale = host_timescale->GetFloat(); const float hostTimeScale = host_timescale->GetFloat();
const bool isTimeScaleDefault = hostTimeScale == 1.0; const bool isTimeScaleDefault = hostTimeScale == 1.0;
const float minFrameTime = usercmd_frametime_min->GetFloat(); const float minFrameTime = usercmd_frametime_min.GetFloat();
const float maxFrameTime = usercmd_frametime_max->GetFloat(); const float maxFrameTime = usercmd_frametime_max.GetFloat();
const float netTime = float(*g_pNetTime); const float netTime = float(*g_pNetTime);
if (cl->m_flNextCmdTime <= (maxFrameTime * 0.5f) + netTime) if (cl->m_flNextCmdTime <= (maxFrameTime * 0.5f) + netTime)
sendPacket = chan->CanPacket(); sendPacket = chan->CanPacket();
else if (cl->m_nOutgoingCommandNr - (commandTick+1) < MAX_BACKUP_COMMANDS || isTimeScaleDefault) else if (cl->m_nOutgoingCommandNr - (commandTick+1) < MAX_NEW_COMMANDS || isTimeScaleDefault)
sendPacket = false; sendPacket = false;
const bool isActive = cl->IsActive(); const bool isActive = cl->IsActive();
@ -68,53 +70,48 @@ void H_CL_Move()
float frameTime = 0.0f; float frameTime = 0.0f;
if (cl_move_use_dt->GetBool()) float timeScale;
float deltaTime;
if (isPaused)
{ {
float timeScale; timeScale = 1.0f;
float deltaTime; frameTime = movementCallTime - s_lastMovementCall;
deltaTime = frameTime;
if (isPaused)
{
timeScale = 1.0f;
frameTime = movementCallTime - s_lastMovementCall;
deltaTime = frameTime;
}
else
{
timeScale = hostTimeScale;
frameTime = cl->m_flFrameTime + s_LastFrameTime;
deltaTime = frameTime / timeScale;
}
// Clamp the frame time to the maximum.
if (deltaTime > maxFrameTime)
frameTime = timeScale * maxFrameTime;
// Drop this frame if delta time is below the minimum.
const bool dropFrame = (isTimeScaleDefault && deltaTime < minFrameTime);
// This check originally was 'time < 0.0049999999', but
// that caused problems when the framerate was above 190.
if (dropFrame)
{
s_LastFrameTime = frameTime;
return;
}
s_LastFrameTime = 0.0;
} }
//else if (isPaused) else
// // This hlClient virtual call just returns false. {
timeScale = hostTimeScale;
frameTime = cl->m_flFrameTime + s_LastFrameTime;
deltaTime = frameTime / timeScale;
}
// Clamp the frame time to the maximum.
if (deltaTime > maxFrameTime)
frameTime = timeScale * maxFrameTime;
// Drop this frame if delta time is below the minimum.
const bool dropFrame = (isTimeScaleDefault && deltaTime < minFrameTime);
// This check originally was 'time < 0.0049999999', but
// that caused problems when the framerate was above 190.
if (dropFrame)
{
s_LastFrameTime = frameTime;
return;
}
s_LastFrameTime = 0.0;
// Create and store usercmd structure. // Create and store usercmd structure.
g_pHLClient->CreateMove(nextCommandNr, frameTime, !isPaused); g_pHLClient->CreateMove(nextCommandNr, frameTime, !isPaused);
cl->m_nOutgoingCommandNr = nextCommandNr; cl->m_nOutgoingCommandNr = nextCommandNr;
} }
CL_RunPrediction(); v_CL_RunPrediction();
if (sendPacket) if (sendPacket)
CL_SendMove(); v_CL_SendMove();
else else
chan->SetChoked(); // Choke the packet... chan->SetChoked(); // Choke the packet...
@ -132,19 +129,14 @@ void H_CL_Move()
chan->SendDatagram(nullptr); chan->SendDatagram(nullptr);
// Use full update rate when active. // Use full update rate when active.
float delta = netTime - float(cl->m_flNextCmdTime); const float delta = netTime - float(cl->m_flNextCmdTime);
float maxDelta = fminf(fmaxf(delta, 0.0f), minFrameTime); const float maxDelta = fminf(fmaxf(delta, 0.0f), minFrameTime);
cl->m_flNextCmdTime = double(minFrameTime + netTime - maxDelta); cl->m_flNextCmdTime = double(minFrameTime + netTime - maxDelta);
} }
} }
void VCL_Main::Attach() const void VCL_Main::Detour(const bool bAttach) const
{ {
DetourAttach(&CL_Move, &H_CL_Move); DetourSetup(&v_CL_Move, &CL_MoveEx, bAttach);
}
void VCL_Main::Detach() const
{
DetourDetach(&CL_Move, &H_CL_Move);
} }

View File

@ -1,19 +1,10 @@
#pragma once #pragma once
inline CMemory p_CL_Move; inline void(*v_CL_Move)(void);
inline void(*CL_Move)(void); inline void(*v_CL_SendMove)(void);
inline int(*v_CL_EndMovie)(void);
inline CMemory p_CL_SendMove; inline int(*v_CL_ClearState)(void);
inline void(*CL_SendMove)(void); inline void(*v_CL_RunPrediction)(void);
inline CMemory p_CL_EndMovie;
inline int(*CL_EndMovie)(void);
inline CMemory p_CL_ClearState;
inline int(*CL_ClearState)(void);
inline CMemory p_CL_RunPrediction;
inline void(*CL_RunPrediction)(void);
inline bool g_bClientDLL = false; inline bool g_bClientDLL = false;
@ -28,36 +19,22 @@ class VCL_Main : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CL_Move", p_CL_Move.GetPtr()); LogFunAdr("CL_Move", v_CL_Move);
LogFunAdr("CL_SendMove", p_CL_SendMove.GetPtr()); LogFunAdr("CL_SendMove", v_CL_SendMove);
LogFunAdr("CL_EndMovie", p_CL_EndMovie.GetPtr()); LogFunAdr("CL_EndMovie", v_CL_EndMovie);
LogFunAdr("CL_ClearState", p_CL_ClearState.GetPtr()); LogFunAdr("CL_ClearState", v_CL_ClearState);
LogFunAdr("CL_RunPrediction", p_CL_RunPrediction.GetPtr()); LogFunAdr("CL_RunPrediction", v_CL_RunPrediction);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 83 3D ?? ?? ?? ?? ?? 44 0F 29 5C 24 ??").GetPtr(v_CL_Move);
p_CL_Move = g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 83 3D ?? ?? ?? ?? ?? 0F B6 DA"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 05 ?? ?? ?? ??").GetPtr(v_CL_SendMove);
p_CL_SendMove = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 05 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 74 7B").GetPtr(v_CL_EndMovie);
p_CL_EndMovie = g_GameDll.FindPatternSIMD("48 8B C4 48 83 EC 68 80 3D ?? ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01").GetPtr(v_CL_ClearState);
p_CL_ClearState = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 1D ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 83 EC 48 83 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ??").GetPtr(v_CL_RunPrediction);
p_CL_RunPrediction = g_GameDll.FindPatternSIMD("4C 8B DC 48 83 EC 58 83 3D ?? ?? ?? ?? ??");
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_CL_Move = g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 83 3D ?? ?? ?? ?? ?? 44 0F 29 5C 24 ??");
p_CL_SendMove = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 05 ?? ?? ?? ??");
p_CL_EndMovie = g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 74 7B");
p_CL_ClearState = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01");
p_CL_RunPrediction = g_GameDll.FindPatternSIMD("48 83 EC 48 83 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ??");
#endif
CL_Move = p_CL_Move.RCast<void(*)(void)>();
CL_SendMove = p_CL_SendMove.RCast<void(*)(void)>();
CL_EndMovie = p_CL_EndMovie.RCast<int(*)(void)>();
CL_ClearState = p_CL_ClearState.RCast<int(*)(void)>();
CL_RunPrediction = p_CL_RunPrediction.RCast<void(*)(void)>();
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -16,6 +16,20 @@
#include "common/igameserverdata.h" #include "common/igameserverdata.h"
//-----------------------------------------------------------------------------
// Purpose: console variables
//-----------------------------------------------------------------------------
static ConVar rcon_address("rcon_address", "[loopback]:37015", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access address");
//-----------------------------------------------------------------------------
// Purpose: console commands
//-----------------------------------------------------------------------------
static void RCON_Disconnect_f();
static void RCON_CmdQuery_f(const CCommand& args);
static ConCommand rcon("rcon", RCON_CmdQuery_f, "Forward RCON query to remote server", FCVAR_CLIENTDLL | FCVAR_RELEASE, nullptr, "rcon \"<query>\"");
static ConCommand rcon_disconnect("rcon_disconnect", RCON_Disconnect_f, "Disconnect from RCON server", FCVAR_CLIENTDLL | FCVAR_RELEASE);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: // Purpose:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -29,6 +43,9 @@ CRConClient::CRConClient()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
CRConClient::~CRConClient(void) CRConClient::~CRConClient(void)
{ {
// NOTE: do not call Shutdown() from the destructor as the OS's socket
// system would be shutdown by now, call Shutdown() in application
// shutdown code instead
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -76,7 +93,7 @@ void CRConClient::Disconnect(const char* szReason)
szReason = "unknown reason"; szReason = "unknown reason";
} }
DevMsg(eDLL_T::CLIENT, "Disconnect: (%s)\n", szReason); Msg(eDLL_T::CLIENT, "RCON disconnect: (%s)\n", szReason);
m_Socket.CloseAcceptedSocket(0); m_Socket.CloseAcceptedSocket(0);
} }
} }
@ -112,7 +129,7 @@ bool CRConClient::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
} }
} }
DevMsg(eDLL_T::NETCON, "%s", response.responsemsg().c_str()); Msg(eDLL_T::NETCON, "%s", response.responsemsg().c_str());
break; break;
} }
case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG: case sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG:
@ -187,13 +204,23 @@ SocketHandle_t CRConClient::GetSocket(void)
return SH_GetNetConSocketHandle(this, 0); return SH_GetNetConSocketHandle(this, 0);
} }
//-----------------------------------------------------------------------------
// Purpose: request whether to recv logs from RCON server when cvar changes
//-----------------------------------------------------------------------------
static void RCON_InputOnlyChanged_f(IConVar* pConVar, const char* pOldString)
{
RCONClient()->RequestConsoleLog(RCONClient()->ShouldReceive());
}
static ConVar cl_rcon_inputonly("cl_rcon_inputonly", "0", FCVAR_RELEASE, "Tells the rcon server whether or not we are input only.",
false, 0.f, false, 0.f, RCON_InputOnlyChanged_f);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: returns whether or not we should receive logs from the server // Purpose: returns whether or not we should receive logs from the server
// Output : SOCKET_ERROR (-1) on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool CRConClient::ShouldReceive(void) bool CRConClient::ShouldReceive(void)
{ {
return (!IsRemoteLocal() && !cl_rcon_inputonly->GetBool()); return (!IsRemoteLocal() && !cl_rcon_inputonly.GetBool());
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -221,8 +248,102 @@ bool CRConClient::IsConnected(void)
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
CRConClient* g_RCONClient(new CRConClient()); static CRConClient s_RCONClient;
CRConClient* RCONClient() // Singleton RCON Client. CRConClient* RCONClient() // Singleton RCON Client.
{ {
return g_RCONClient; return &s_RCONClient;
}
/*
=====================
RCON_CmdQuery_f
Issues an RCON command to the
RCON server.
=====================
*/
static void RCON_CmdQuery_f(const CCommand& args)
{
const int64_t argCount = args.ArgC();
if (argCount < 2)
{
const char* pszAddress = rcon_address.GetString();
if (RCONClient()->IsInitialized()
&& !RCONClient()->IsConnected()
&& pszAddress[0])
{
RCONClient()->Connect(pszAddress);
}
}
else
{
if (!RCONClient()->IsInitialized())
{
Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "uninitialized");
return;
}
else if (RCONClient()->IsConnected())
{
vector<char> vecMsg;
bool bSuccess = false;
const SocketHandle_t hSocket = RCONClient()->GetSocket();
if (strcmp(args.Arg(1), "PASS") == 0) // Auth with RCON server using rcon_password ConVar value.
{
if (argCount > 2)
{
bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH);
}
else
{
Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password given");
return;
}
if (bSuccess)
{
RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size()));
}
return;
}
else if (strcmp(args.Arg(1), "disconnect") == 0) // Disconnect from RCON server.
{
RCONClient()->Disconnect("issued by user");
return;
}
bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(1), args.ArgS(), cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
if (bSuccess)
{
RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size()));
}
return;
}
else
{
Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "unconnected");
return;
}
}
}
/*
=====================
RCON_Disconnect_f
Disconnect from RCON server
=====================
*/
static void RCON_Disconnect_f()
{
const bool bIsConnected = RCONClient()->IsConnected();
RCONClient()->Disconnect("issued by user");
if (bIsConnected) // Log if client was indeed connected.
{
Msg(eDLL_T::CLIENT, "User closed RCON connection\n");
}
} }

View File

@ -128,26 +128,18 @@ class VSplitScreen : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogVarAdr("g_SplitScreenMgr", reinterpret_cast<uintptr_t>(g_pSplitScreenMgr)); LogVarAdr("g_SplitScreenMgr", g_pSplitScreenMgr);
} }
virtual void GetFun(void) const { } virtual void GetFun(void) const { }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
const char* pszPattern; const char* const pszPattern = "40 53 48 83 EC 20 48 8D 1D ?? ?? ?? ?? 83 FA FF 75 12 48 8B 05 ?? ?? ?? ?? 48 8B CB FF 50 28 48 63 C8 EB 03 48 63 CA 48 69 C1 ?? ?? ?? ?? 66 C7 84 18 ?? ?? ?? ?? ?? ??";;
const char* pszInstruction; const char* const pszInstruction = "48 8D";
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
pszPattern = "83 FA FF 75 22 48 8D 05 ?? ?? ?? ??";
pszInstruction = "4C 8D";
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
pszPattern = "40 53 48 83 EC 20 48 8D 1D ?? ?? ?? ?? 83 FA FF 75 12 48 8B 05 ?? ?? ?? ?? 48 8B CB FF 50 28 48 63 C8 EB 03 48 63 CA 48 69 C1 ?? ?? ?? ?? 66 C7 84 18 ?? ?? ?? ?? ?? ??";
pszInstruction = "48 8D";
#endif
g_pSplitScreenMgr = g_GameDll.FindPatternSIMD(pszPattern).FindPatternSelf(pszInstruction).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CSplitScreen*>(); g_pSplitScreenMgr = g_GameDll.FindPatternSIMD(pszPattern).FindPatternSelf(pszInstruction).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CSplitScreen*>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { }; virtual void Detour(const bool bAttach) const { };
virtual void Detach(void) const { };
}; };
#endif // CL_SPLITSCREEN_H #endif // CL_SPLITSCREEN_H

View File

@ -13,9 +13,14 @@
#include "tier1/strtools.h" #include "tier1/strtools.h"
#include "engine/server/server.h" #include "engine/server/server.h"
#include "engine/client/client.h" #include "engine/client/client.h"
#ifndef CLIENT_DLL
#include "networksystem/hostmanager.h"
#include "jwt/include/decode.h"
#include "mbedtls/include/mbedtls/sha256.h"
#endif
// 128+1 so that the client still receives the 'console command too long' message. // Absolute max string cmd length, any character past this will be NULLED.
#define STRINGCMD_MAX_LEN 129 #define STRINGCMD_MAX_LEN 512
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Purpose: throw away any residual garbage in the channel // Purpose: throw away any residual garbage in the channel
@ -23,9 +28,9 @@
void CClient::Clear(void) void CClient::Clear(void)
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
g_ServerPlayer[GetUserID()].Reset(); // Reset ServerPlayer slot. GetClientExtended()->Reset(); // Reset extended data.
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
v_CClient_Clear(this); CClient__Clear(this);
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
@ -37,39 +42,224 @@ void CClient::VClear(CClient* pClient)
pClient->Clear(); pClient->Clear();
} }
#ifndef CLIENT_DLL
//---------------------------------------------------------------------------------
// Purpose: gets the extended client data
// Output : CClientExtended* -
//---------------------------------------------------------------------------------
CClientExtended* CClient::GetClientExtended(void) const
{
return m_pServer->GetClientExtended(m_nUserID);
}
#endif // !CLIENT_DLL
static const char JWT_PUBLIC_KEY[] =
"-----BEGIN PUBLIC KEY-----\n"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/335exIZ6LE8pYi6e50\n"
"7tH19tXaeeEJVF5XXpTCXpndXIIWVimvg6xQ381eajySDw93wvG1DzW3U/6LHzyt\n"
"Q++N8w7N+FwnXyoDUD5Y8hheTZv6jjLoYT8ZtsMl20k9UosrbFBTMUhgmIT2dVth\n"
"LH+rT9ohpUNwQXHJvTOs9eY74GyfFw93+32LANBPZ8b+S8S3oZnKFVeCxRkYKsV0\n"
"b34POHVBbXNw6Kt163gR5zaiCfJJtRto9AA7MV2t9pfy8CChs3uJ+Xn7QVHD5cqt\n"
"Msg9MBac2Pvs2j+8wJ/igAVL5L81z3FXVt04id59TfPMUbYhRfY8pk7FB0MCigOH\n"
"dwIDAQAB\n"
"-----END PUBLIC KEY-----\n";
static ConVar sv_onlineAuthEnable("sv_onlineAuthEnable", "1", FCVAR_RELEASE, "Enables the server-side online authentication system");
static ConVar sv_onlineAuthValidateExpiry("sv_onlineAuthValidateExpiry", "1", FCVAR_RELEASE, "Validate the online authentication token 'expiry' claim");
static ConVar sv_onlineAuthValidateIssuedAt("sv_onlineAuthValidateIssuedAt", "1", FCVAR_RELEASE, "Validate the online authentication token 'issued at' claim");
static ConVar sv_onlineAuthExpiryTolerance("sv_onlineAuthExpiryTolerance", "1", FCVAR_DEVELOPMENTONLY, "The online authentication token 'expiry' claim tolerance in seconds", true, 0.f, true, float(UINT8_MAX), "Must range between [0,255]");
static ConVar sv_onlineAuthIssuedAtTolerance("sv_onlineAuthIssuedAtTolerance", "30", FCVAR_DEVELOPMENTONLY, "The online authentication token 'issued at' claim tolerance in seconds", true, 0.f, true, float(UINT8_MAX), "Must range between [0,255]");
static ConVar sv_quota_stringCmdsPerSecond("sv_quota_stringCmdsPerSecond", "16", FCVAR_RELEASE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands", true, 0.f, false, 0.f);
//---------------------------------------------------------------------------------
// Purpose: check whether this client is authorized to join this server
// Input : *playerName -
// *reasonBuf -
// reasonBufLen -
// Output : true if authorized, false otherwise
//---------------------------------------------------------------------------------
bool CClient::Authenticate(const char* const playerName, char* const reasonBuf, const size_t reasonBufLen)
{
#ifndef CLIENT_DLL
// don't bother checking origin auth on bots or local clients
if (IsFakeClient() || GetNetChan()->GetRemoteAddress().IsLoopback())
return true;
l8w8jwt_claim* claims = nullptr;
size_t numClaims = 0;
// formats the error reason, and frees the claims and returns
#define ERROR_AND_RETURN(fmt, ...) \
do {\
V_snprintf(reasonBuf, reasonBufLen, fmt, ##__VA_ARGS__); \
if (claims) {\
l8w8jwt_free_claims(claims, numClaims); \
}\
return false; \
} while(0)\
KeyValues* const cl_onlineAuthTokenKv = this->m_ConVars->FindKey("cl_onlineAuthToken");
KeyValues* const cl_onlineAuthTokenSignature1Kv = this->m_ConVars->FindKey("cl_onlineAuthTokenSignature1");
KeyValues* const cl_onlineAuthTokenSignature2Kv = this->m_ConVars->FindKey("cl_onlineAuthTokenSignature2");
if (!cl_onlineAuthTokenKv || !cl_onlineAuthTokenSignature1Kv)
ERROR_AND_RETURN("Missing token");
const char* const onlineAuthToken = cl_onlineAuthTokenKv->GetString();
const char* const onlineAuthTokenSignature1 = cl_onlineAuthTokenSignature1Kv->GetString();
const char* const onlineAuthTokenSignature2 = cl_onlineAuthTokenSignature2Kv->GetString();
char fullToken[1024]; // enough buffer for 3x255, which is cvar count * userinfo str limit.
const int tokenLen = snprintf(fullToken, sizeof(fullToken), "%s.%s%s",
onlineAuthToken, onlineAuthTokenSignature1, onlineAuthTokenSignature2);
if (tokenLen < 0)
ERROR_AND_RETURN("Token stitching failed");
struct l8w8jwt_decoding_params params;
l8w8jwt_decoding_params_init(&params);
params.alg = L8W8JWT_ALG_RS256;
params.jwt = (char*)fullToken;
params.jwt_length = tokenLen;
params.verification_key = (unsigned char*)JWT_PUBLIC_KEY;
params.verification_key_length = sizeof(JWT_PUBLIC_KEY);
params.validate_exp = sv_onlineAuthValidateExpiry.GetBool();
params.exp_tolerance_seconds = (uint8_t)sv_onlineAuthExpiryTolerance.GetInt();
params.validate_iat = sv_onlineAuthValidateIssuedAt.GetBool();
params.iat_tolerance_seconds = (uint8_t)sv_onlineAuthIssuedAtTolerance.GetInt();
enum l8w8jwt_validation_result validation_result;
const int r = l8w8jwt_decode(&params, &validation_result, &claims, &numClaims);
if (r != L8W8JWT_SUCCESS)
ERROR_AND_RETURN("Code %i", r);
if (validation_result != L8W8JWT_VALID)
{
char reasonBuffer[64];
l8w8jwt_get_validation_result_desc(validation_result, reasonBuffer, sizeof(reasonBuffer));
ERROR_AND_RETURN("%s", reasonBuffer);
}
bool foundSessionId = false;
for (size_t i = 0; i < numClaims; ++i)
{
// session id
if (!strcmp(claims[i].key, "sessionId"))
{
const char* const sessionId = claims[i].value;
char newId[256];
const int idLen = snprintf(newId, sizeof(newId), "%llu-%s-%s",
(NucleusID_t)this->m_DataBlock.userData,
playerName,
g_ServerHostManager.GetHostIP().c_str());
if (idLen < 0)
ERROR_AND_RETURN("Session ID stitching failed");
uint8_t sessionHash[32]; // hash decoded from JWT token
V_hextobinary(sessionId, strlen(sessionId), sessionHash, sizeof(sessionHash));
uint8_t oobHash[32]; // hash of data collected from out of band packet
const int shRet = mbedtls_sha256((const uint8_t*)newId, idLen, oobHash, NULL);
if (shRet != NULL)
ERROR_AND_RETURN("Session ID hashing failed");
if (memcmp(oobHash, sessionHash, sizeof(sessionHash)) != 0)
ERROR_AND_RETURN("Token is not authorized for the connecting client");
foundSessionId = true;
}
}
if (!foundSessionId)
ERROR_AND_RETURN("No session ID");
l8w8jwt_free_claims(claims, numClaims);
#undef ERROR_AND_RETURN
#endif // !CLIENT_DLL
return true;
}
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Purpose: connect new client // Purpose: connect new client
// Input : *szName - // Input : *szName -
// *pNetChannel - // *pNetChan -
// bFakePlayer - // bFakePlayer -
// *a5 - // *conVars -
// *szMessage - // *szMessage -
// nMessageSize - // nMessageSize -
// Output : true if connection was successful, false otherwise // Output : true if connection was successful, false otherwise
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool CClient::Connect(const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize) bool CClient::Connect(const char* szName, CNetChan* pNetChan, bool bFakePlayer,
CUtlVector<NET_SetConVar::cvar_t>* conVars, char* szMessage, int nMessageSize)
{ {
return v_CClient_Connect(this, szName, pNetChannel, bFakePlayer, a5, szMessage, nMessageSize); #ifndef CLIENT_DLL
GetClientExtended()->Reset(); // Reset extended data.
#endif
if (!CClient__Connect(this, szName, pNetChan, bFakePlayer, conVars, szMessage, nMessageSize))
return false;
#ifndef CLIENT_DLL
#define REJECT_CONNECTION(fmt, ...) V_snprintf(szMessage, nMessageSize, fmt, ##__VA_ARGS__);
if (sv_onlineAuthEnable.GetBool())
{
char authFailReason[512];
if (!Authenticate(szName, authFailReason, sizeof(authFailReason)))
{
REJECT_CONNECTION("Failed to verify authentication token [%s]", authFailReason);
const bool bEnableLogging = sv_showconnecting.GetBool();
if (bEnableLogging)
{
const char* const netAdr = pNetChan ? pNetChan->GetAddress() : "<unknown>";
Warning(eDLL_T::SERVER, "Client '%s' ('%llu') failed online authentication! [%s]\n",
netAdr, (NucleusID_t)m_DataBlock.userData, authFailReason);
}
return false;
}
}
#undef REJECT_CONNECTION
#endif // !CLIENT_DLL
return true;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Purpose: connect new client // Purpose: connect new client
// Input : *pClient - // Input : *pClient -
// *szName - // *szName -
// *pNetChannel - // *pNetChan -
// bFakePlayer - // bFakePlayer -
// *a5 - // *a5 -
// *szMessage - // *szMessage -
// nMessageSize - // nMessageSize -
// Output : true if connection was successful, false otherwise // Output : true if connection was successful, false otherwise
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool CClient::VConnect(CClient* pClient, const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize) bool CClient::VConnect(CClient* pClient, const char* szName, CNetChan* pNetChan, bool bFakePlayer,
CUtlVector<NET_SetConVar::cvar_t>* conVars, char* szMessage, int nMessageSize)
{ {
bool bResult = v_CClient_Connect(pClient, szName, pNetChannel, bFakePlayer, a5, szMessage, nMessageSize); return pClient->Connect(szName, pNetChan, bFakePlayer, conVars, szMessage, nMessageSize);;
#ifndef CLIENT_DLL
g_ServerPlayer[pClient->GetUserID()].Reset(); // Reset ServerPlayer slot.
#endif // !CLIENT_DLL
return bResult;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
@ -92,7 +282,7 @@ void CClient::Disconnect(const Reputation_t nRepLvl, const char* szReason, ...)
szBuf[sizeof(szBuf) - 1] = '\0'; szBuf[sizeof(szBuf) - 1] = '\0';
va_end(vArgs); va_end(vArgs);
}///////////////////////////// }/////////////////////////////
v_CClient_Disconnect(this, nRepLvl, szBuf); CClient__Disconnect(this, nRepLvl, szBuf);
} }
} }
@ -104,14 +294,14 @@ void CClient::VActivatePlayer(CClient* pClient)
{ {
// Set the client instance to 'ready' before calling ActivatePlayer. // Set the client instance to 'ready' before calling ActivatePlayer.
pClient->SetPersistenceState(PERSISTENCE::PERSISTENCE_READY); pClient->SetPersistenceState(PERSISTENCE::PERSISTENCE_READY);
v_CClient_ActivatePlayer(pClient); CClient__ActivatePlayer(pClient);
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
const CNetChan* pNetChan = pClient->GetNetChan(); const CNetChan* pNetChan = pClient->GetNetChan();
if (pNetChan && sv_showconnecting->GetBool()) if (pNetChan && sv_showconnecting.GetBool())
{ {
DevMsg(eDLL_T::SERVER, "Activated player #%d; channel %s(%s) ('%llu')\n", Msg(eDLL_T::SERVER, "Activated player #%d; channel %s(%s) ('%llu')\n",
pClient->GetUserID(), pNetChan->GetName(), pNetChan->GetAddress(), pClient->GetNucleusID()); pClient->GetUserID(), pNetChan->GetName(), pNetChan->GetAddress(), pClient->GetNucleusID());
} }
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
@ -125,7 +315,7 @@ void CClient::VActivatePlayer(CClient* pClient)
// bForceReliable - // bForceReliable -
// bVoice - // bVoice -
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool CClient::SendNetMsgEx(CNetMessage* pMsg, char bLocal, bool bForceReliable, bool bVoice) bool CClient::SendNetMsgEx(CNetMessage* pMsg, bool bLocal, bool bForceReliable, bool bVoice)
{ {
if (!ShouldReplayMessage(pMsg)) if (!ShouldReplayMessage(pMsg))
{ {
@ -133,7 +323,7 @@ bool CClient::SendNetMsgEx(CNetMessage* pMsg, char bLocal, bool bForceReliable,
pMsg->m_nGroup = NetMessageGroup::NoReplay; pMsg->m_nGroup = NetMessageGroup::NoReplay;
} }
return v_CClient_SendNetMsgEx(this, pMsg, bLocal, bForceReliable, bVoice); return CClient__SendNetMsgEx(this, pMsg, bLocal, bForceReliable, bVoice);
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
@ -145,7 +335,64 @@ bool CClient::SendNetMsgEx(CNetMessage* pMsg, char bLocal, bool bForceReliable,
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
void* CClient::VSendSnapshot(CClient* pClient, CClientFrame* pFrame, int nTick, int nTickAck) void* CClient::VSendSnapshot(CClient* pClient, CClientFrame* pFrame, int nTick, int nTickAck)
{ {
return v_CClient_SendSnapshot(pClient, pFrame, nTick, nTickAck); return CClient__SendSnapshot(pClient, pFrame, nTick, nTickAck);
}
//---------------------------------------------------------------------------------
// Purpose: internal hook to 'CClient::SendNetMsgEx'
// Input : *pClient -
// *pMsg -
// bLocal -
// bForceReliable -
// bVoice -
//---------------------------------------------------------------------------------
bool CClient::VSendNetMsgEx(CClient* pClient, CNetMessage* pMsg, bool bLocal, bool bForceReliable, bool bVoice)
{
return pClient->SendNetMsgEx(pMsg, bLocal, bForceReliable, bVoice);
}
//---------------------------------------------------------------------------------
// Purpose: write data into data blocks to send to the client
// Input : &buf
//---------------------------------------------------------------------------------
void CClient::WriteDataBlock(CClient* pClient, bf_write& buf)
{
#ifndef CLIENT_DLL
if (net_data_block_enabled->GetBool())
{
buf.WriteUBitLong(net_NOP, NETMSG_TYPE_BITS);
const int remainingBits = buf.GetNumBitsWritten() % 8;
if (remainingBits && (8 - remainingBits) > 0)
{
// fill the last bits in the last byte with NOP
buf.WriteUBitLong(net_NOP, 8 - remainingBits);
}
const bool isMultiplayer = g_ServerGlobalVariables->m_nGameMode < GameMode_t::PVE_MODE;
pClient->m_DataBlock.sender.WriteDataBlock(buf.GetData(), buf.GetNumBytesWritten(), isMultiplayer, buf.GetDebugName());
}
else
{
pClient->m_NetChannel->SendData(buf, true);
}
#endif // !CLIENT_DLL
}
//---------------------------------------------------------------------------------
// Purpose: some versions of the binary have an optimization that shifts the 'this'
// pointer of the CClient structure by 8 bytes to avoid having to cache the vftable
// pointer if it never get used. Here we shift it back so it aligns again.
//---------------------------------------------------------------------------------
CClient* AdjustShiftedThisPointer(CClient* shiftedPointer)
{
/* Original function called method "CClient::ExecuteStringCommand" with an optimization
* that shifted the 'this' pointer with 8 bytes.
* Since this has been inlined with "CClient::ProcessStringCmd" as of S2, the shifting
* happens directly to anything calling this function. */
char* pShifted = reinterpret_cast<char*>(shiftedPointer) - 8;
return reinterpret_cast<CClient*>(pShifted);
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
@ -157,21 +404,16 @@ void* CClient::VSendSnapshot(CClient* pClient, CClientFrame* pFrame, int nTick,
bool CClient::VProcessStringCmd(CClient* pClient, NET_StringCmd* pMsg) bool CClient::VProcessStringCmd(CClient* pClient, NET_StringCmd* pMsg)
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) CClient* const pClient_Adj = AdjustShiftedThisPointer(pClient);
CClient* pClient_Adj = pClient;
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
/* Original function called method "CClient::ExecuteStringCommand" with an optimization
* that shifted the 'this' pointer with 8 bytes.
* Since this has been inlined with "CClient::ProcessStringCmd" as of S2, the shifting
* happens directly to anything calling this function. */
char* pShifted = reinterpret_cast<char*>(pClient) - 8;
CClient* pClient_Adj = reinterpret_cast<CClient*>(pShifted);
#endif // !GAMEDLL_S0 || !GAMEDLL_S1
int nUserID = pClient_Adj->GetUserID();
ServerPlayer_t* pSlot = &g_ServerPlayer[nUserID];
double flStartTime = Plat_FloatTime(); // Jettison the cmd if the client isn't active.
int nCmdQuotaLimit = sv_quota_stringCmdsPerSecond->GetInt(); if (!pClient_Adj->IsActive())
return true;
CClientExtended* const pSlot = pClient_Adj->GetClientExtended();
const double flStartTime = Plat_FloatTime();
const int nCmdQuotaLimit = sv_quota_stringCmdsPerSecond.GetInt();
if (!nCmdQuotaLimit) if (!nCmdQuotaLimit)
return true; return true;
@ -182,16 +424,13 @@ bool CClient::VProcessStringCmd(CClient* pClient, NET_StringCmd* pMsg)
// The internal function discards the command if it's null. // The internal function discards the command if it's null.
if (pCmd) if (pCmd)
{ {
// If the string length exceeds 128, the will engine return a 'command // There is an issue in CUtlBuffer::ParseToken() that causes it to read
// string too long' message back to the client that issued it and // past its buffer; mostly seems to happen on 32bit, but a carefully
// subsequently jettison the string cmd. Before this routine gets hit, // crafted string should work on 64bit too). The fix is to just null
// the entire string gets parsed (up to 512 bytes). There is an issue // everything past the maximum allowed length. The second 'theoretical'
// in CUtlBuffer::ParseToken() that causes it to read past its buffer; // fix would be to properly fix CUtlBuffer::ParseToken() by computing
// mostly seems to happen on 32bit, but a carefully crafted string // the UTF8 character size each iteration and check if it still doesn't
// should work on 64bit too). The fix is to just null everything past // exceed bounds.
// the maximum allowed length. The second 'theoretical' fix would be to
// properly fix CUtlBuffer::ParseToken() by computing the UTF8 character
// size each iteration and check if it still doesn't exceed bounds.
memset(&pMsg->buffer[STRINGCMD_MAX_LEN], memset(&pMsg->buffer[STRINGCMD_MAX_LEN],
'\0', sizeof(pMsg->buffer) - (STRINGCMD_MAX_LEN)); '\0', sizeof(pMsg->buffer) - (STRINGCMD_MAX_LEN));
@ -222,41 +461,80 @@ bool CClient::VProcessStringCmd(CClient* pClient, NET_StringCmd* pMsg)
} }
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
return v_CClient_ProcessStringCmd(pClient, pMsg); return CClient__ProcessStringCmd(pClient, pMsg);
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Purpose: internal hook to 'CClient::SendNetMsgEx' // Purpose: process set convar
// Input : *pClient - // Input : *pClient - (ADJ)
// *pMsg - // *pMsg -
// bLocal - // Output :
// bForceReliable -
// bVoice -
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool CClient::VSendNetMsgEx(CClient* pClient, CNetMessage* pMsg, char bLocal, bool bForceReliable, bool bVoice) bool CClient::VProcessSetConVar(CClient* pClient, NET_SetConVar* pMsg)
{ {
return pClient->SendNetMsgEx(pMsg, bLocal, bForceReliable, bVoice); #ifndef CLIENT_DLL
CClient* const pAdj = AdjustShiftedThisPointer(pClient);
CClientExtended* const pSlot = pAdj->GetClientExtended();
// This loop never exceeds 255 iterations, NET_SetConVar::ReadFromBuffer(...)
// reads and inserts up to 255 entries in the vector (reads a byte for size).
FOR_EACH_VEC(pMsg->m_ConVars, i)
{
const NET_SetConVar::cvar_t& entry = pMsg->m_ConVars[i];
const char* const name = entry.name;
const char* const value = entry.value;
// Discard any ConVar change request if it contains funky characters.
bool bFunky = false;
for (const char* s = name; *s != '\0'; ++s)
{
if (!V_isalnum(*s) && *s != '_')
{
bFunky = true;
break;
}
}
if (bFunky)
{
DevWarning(eDLL_T::SERVER, "Ignoring ConVar change request for variable '%s' from client '%s'; invalid characters in the variable name\n",
name, pAdj->GetClientName());
continue;
}
// The initial set of ConVars must contain all client ConVars that are
// flagged UserInfo. This is a simple fix to exploits that send bogus
// data later, and catches bugs, such as new UserInfo ConVars appearing
// later, which shouldn't happen.
if (pSlot->m_bInitialConVarsSet && !pAdj->m_ConVars->FindKey(name))
{
DevWarning(eDLL_T::SERVER, "UserInfo update from \"%s\" ignored: %s = %s\n",
pAdj->GetClientName(), name, value);
continue;
}
// Add ConVar to list and set string.
pAdj->m_ConVars->SetString(name, value);
DevMsg(eDLL_T::SERVER, "UserInfo update from \"%s\": %s = %s\n", pAdj->GetClientName(), name, value);
}
pSlot->m_bInitialConVarsSet = true;
pAdj->m_bConVarsChanged = true;
#endif // !CLIENT_DLL
return true;
} }
void VClient::Attach(void) const void VClient::Detour(const bool bAttach) const
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
DetourAttach((LPVOID*)&v_CClient_Clear, &CClient::VClear); DetourSetup(&CClient__Clear, &CClient::VClear, bAttach);
DetourAttach((LPVOID*)&v_CClient_Connect, &CClient::VConnect); DetourSetup(&CClient__Connect, &CClient::VConnect, bAttach);
DetourAttach((LPVOID*)&v_CClient_ActivatePlayer, &CClient::VActivatePlayer); DetourSetup(&CClient__ActivatePlayer, &CClient::VActivatePlayer, bAttach);
DetourAttach((LPVOID*)&v_CClient_ProcessStringCmd, &CClient::VProcessStringCmd); DetourSetup(&CClient__SendNetMsgEx, &CClient::VSendNetMsgEx, bAttach);
DetourAttach((LPVOID*)&v_CClient_SendNetMsgEx, &CClient::VSendNetMsgEx); //DetourSetup(&CClient__SendSnapshot, &CClient::VSendSnapshot, bAttach);
//DetourAttach((LPVOID*)&p_CClient_SendSnapshot, &CClient::VSendSnapshot); DetourSetup(&CClient__WriteDataBlock, &CClient::WriteDataBlock, bAttach);
#endif // !CLIENT_DLL
} DetourSetup(&CClient__ProcessStringCmd, &CClient::VProcessStringCmd, bAttach);
void VClient::Detach(void) const DetourSetup(&CClient__ProcessSetConVar, &CClient::VProcessSetConVar, bAttach);
{
#ifndef CLIENT_DLL
DetourDetach((LPVOID*)&v_CClient_Clear, &CClient::VClear);
DetourDetach((LPVOID*)&v_CClient_Connect, &CClient::VConnect);
DetourDetach((LPVOID*)&v_CClient_ActivatePlayer, &CClient::VActivatePlayer);
DetourDetach((LPVOID*)&v_CClient_ProcessStringCmd, &CClient::VProcessStringCmd);
DetourDetach((LPVOID*)&v_CClient_SendNetMsgEx, &CClient::VSendNetMsgEx);
//DetourDetach((LPVOID*)&p_CClient_SendSnapshot, &CClient::VSendSnapshot);
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
} }

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "vpc/keyvalues.h" #include "tier1/keyvalues.h"
#include "common/protocol.h" #include "common/protocol.h"
#include "ebisusdk/EbisuTypes.h"
#include "engine/net.h"
#include "engine/net_chan.h" #include "engine/net_chan.h"
#include "public/edict.h" #include "public/edict.h"
#include "engine/server/datablock_sender.h" #include "engine/server/datablock_sender.h"
@ -20,6 +22,7 @@ enum Reputation_t
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class CServer; class CServer;
class CClient; class CClient;
class CClientExtended;
struct Spike_t struct Spike_t
{ {
@ -65,20 +68,24 @@ public:
inline int64_t GetTeamNum() const { return m_iTeamNum; } inline int64_t GetTeamNum() const { return m_iTeamNum; }
inline edict_t GetHandle(void) const { return m_nHandle; } inline edict_t GetHandle(void) const { return m_nHandle; }
inline int GetUserID(void) const { return m_nUserID; } inline int GetUserID(void) const { return m_nUserID; }
inline uint64_t GetNucleusID(void) const { return m_nNucleusID; } inline NucleusID_t GetNucleusID(void) const { return m_nNucleusID; }
inline SIGNONSTATE GetSignonState(void) const { return m_nSignonState; } inline SIGNONSTATE GetSignonState(void) const { return m_nSignonState; }
inline PERSISTENCE GetPersistenceState(void) const { return m_nPersistenceState; } inline PERSISTENCE GetPersistenceState(void) const { return m_nPersistenceState; }
inline CNetChan* GetNetChan(void) const { return m_NetChannel; } inline CNetChan* GetNetChan(void) const { return m_NetChannel; }
inline CServer* GetServer(void) const { return m_pServer; } inline CServer* GetServer(void) const { return m_pServer; }
#ifndef CLIENT_DLL
CClientExtended* GetClientExtended(void) const;
#endif // !CLIENT_DLL
inline int GetCommandTick(void) const { return m_nCommandTick; } inline int GetCommandTick(void) const { return m_nCommandTick; }
inline const char* GetServerName(void) const { return m_szServerName; } inline const char* GetServerName(void) const { return m_szServerName; }
inline const char* GetClientName(void) const { return m_szClientName; } inline const char* GetClientName(void) const { return m_szClientName; }
inline void SetHandle(edict_t nHandle) { m_nHandle = nHandle; } inline void SetHandle(edict_t nHandle) { m_nHandle = nHandle; }
inline void SetUserID(uint32_t nUserID) { m_nUserID = nUserID; } inline void SetUserID(uint32_t nUserID) { m_nUserID = nUserID; }
inline void SetNucleusID(uint64_t nNucleusID) { m_nNucleusID = nNucleusID; } inline void SetNucleusID(NucleusID_t nNucleusID) { m_nNucleusID = nNucleusID; }
inline void SetSignonState(SIGNONSTATE nSignonState) { m_nSignonState = nSignonState; } inline void SetSignonState(SIGNONSTATE nSignonState) { m_nSignonState = nSignonState; }
inline void SetPersistenceState(PERSISTENCE nPersistenceState) { m_nPersistenceState = nPersistenceState; } inline void SetPersistenceState(PERSISTENCE nPersistenceState) { m_nPersistenceState = nPersistenceState; }
@ -92,18 +99,27 @@ public:
inline bool IsFakeClient(void) const { return m_bFakePlayer; } inline bool IsFakeClient(void) const { return m_bFakePlayer; }
inline bool IsHumanPlayer(void) const { if (!IsConnected() || IsFakeClient()) { return false; } return true; } inline bool IsHumanPlayer(void) const { if (!IsConnected() || IsFakeClient()) { return false; } return true; }
bool SendNetMsgEx(CNetMessage* pMsg, char bLocal, bool bForceReliable, bool bVoice); bool SendNetMsgEx(CNetMessage* pMsg, bool bLocal, bool bForceReliable, bool bVoice);
bool Connect(const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize);
bool Authenticate(const char* const playerName, char* const reasonBuf, const size_t reasonBufLen);
bool Connect(const char* szName, CNetChan* pNetChan, bool bFakePlayer,
CUtlVector<NET_SetConVar::cvar_t>* conVars, char* szMessage, int nMessageSize);
void Disconnect(const Reputation_t nRepLvl, const char* szReason, ...); void Disconnect(const Reputation_t nRepLvl, const char* szReason, ...);
static bool VConnect(CClient* pClient, const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize);
void Clear(void); void Clear(void);
public: // Hook statics: public: // Hook statics:
static void VClear(CClient* pClient); static void VClear(CClient* pClient);
static bool VConnect(CClient* pClient, const char* szName, CNetChan* pNetChan, bool bFakePlayer,
CUtlVector<NET_SetConVar::cvar_t>* conVars, char* szMessage, int nMessageSize);
static void VActivatePlayer(CClient* pClient); static void VActivatePlayer(CClient* pClient);
static bool VProcessStringCmd(CClient* pClient, NET_StringCmd* pMsg);
static void* VSendSnapshot(CClient* pClient, CClientFrame* pFrame, int nTick, int nTickAck); static void* VSendSnapshot(CClient* pClient, CClientFrame* pFrame, int nTick, int nTickAck);
static bool VSendNetMsgEx(CClient* pClient, CNetMessage* pMsg, char bLocal, bool bForceReliable, bool bVoice); static bool VSendNetMsgEx(CClient* pClient, CNetMessage* pMsg, bool bLocal, bool bForceReliable, bool bVoice);
static void WriteDataBlock(CClient* pClient, bf_write& buf);
static bool VProcessStringCmd(CClient* pClient, NET_StringCmd* pMsg);
static bool VProcessSetConVar(CClient* pClient, NET_SetConVar* pMsg);
private: private:
// Stub reimplementation to avoid the 'no overrider' compiler errors in the // Stub reimplementation to avoid the 'no overrider' compiler errors in the
@ -146,24 +162,28 @@ private:
char m_szClientName[256]; char m_szClientName[256];
char m_szMachineName[256]; char m_szMachineName[256];
int m_nCommandTick; int m_nCommandTick;
char m_bUsePersistence_MAYBE; bool m_bUsePersistence_MAYBE;
char pad_0016[59]; char pad_0016[59];
int64_t m_iTeamNum; int64_t m_iTeamNum;
KeyValues* m_ConVars; KeyValues* m_ConVars;
char m_bInitialConVarsSet; bool m_bConVarsChanged;
char m_bSendServerInfo; bool m_bSendServerInfo;
char m_bSendSignonData; bool m_bSendSignonData;
char m_bFullStateAchieved; bool m_bFullStateAchieved;
char pad_0368[4]; char pad_0368[4];
CServer* m_pServer; CServer* m_pServer;
char pad_0378[24]; char pad_0378[20];
int m_nDisconnectTick;
bool m_bKickedByFairFight_MAYBE; bool m_bKickedByFairFight_MAYBE;
char pad_0398[14]; char pad_0398[3];
int m_nSendtableCRC;
int m_nMmDev;
char pad_039C[4];
CNetChan* m_NetChannel; CNetChan* m_NetChannel;
char pad_03A8[8]; char pad_03A8[8];
SIGNONSTATE m_nSignonState; SIGNONSTATE m_nSignonState;
int unk0; int unk0;
uint64_t m_nNucleusID; NucleusID_t m_nNucleusID;
int unk1; int unk1;
int unk2; int unk2;
int m_nDeltaTick; int m_nDeltaTick;
@ -171,10 +191,8 @@ private:
int m_nSignonTick; int m_nSignonTick;
int m_nBaselineUpdateTick_MAYBE; int m_nBaselineUpdateTick_MAYBE;
char pad_03C0[448]; char pad_03C0[448];
#if defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
int unk3; int unk3;
int m_nForceWaitForTick; int m_nForceWaitForTick;
#endif
bool m_bFakePlayer; bool m_bFakePlayer;
bool m_bReceivedPacket; bool m_bReceivedPacket;
bool m_bLowViolence; bool m_bLowViolence;
@ -183,92 +201,108 @@ private:
PERSISTENCE m_nPersistenceState; PERSISTENCE m_nPersistenceState;
char pad_05C0[48]; char pad_05C0[48];
ServerDataBlock m_DataBlock; ServerDataBlock m_DataBlock;
char pad_4A3D8[16]; char pad_4A3D8[60];
int m_LastMovementTick; int m_LastMovementTick;
#if defined (GAMEDLL_S2) || defined (GAMEDLL_S3) char pad_4A418[86];
char pad_4A418[130]; char pad_4A46E[80];
#endif
char pad_4A49A[80];
}; };
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
static_assert(sizeof(CClient) == 0x4A440);
#else
static_assert(sizeof(CClient) == 0x4A4C0); static_assert(sizeof(CClient) == 0x4A4C0);
#endif
//-----------------------------------------------------------------------------
// Extended CClient class
//-----------------------------------------------------------------------------
// NOTE: since we interface directly with the engine, we cannot modify the
// client structure. In order to add new data to each client instance, we
// need to use this new class which we link directly to the corresponding
// client instance through its UserID.
//-----------------------------------------------------------------------------
class CClientExtended
{
friend class CClient;
public:
CClientExtended(void)
{
Reset();
}
inline void Reset(void)
{
m_flNetProcessingTimeMsecs = 0.0;
m_flNetProcessTimeBase = 0.0;
m_flStringCommandQuotaTimeStart = 0.0;
m_nStringCommandQuotaCount = NULL;
m_bInitialConVarsSet = false;
}
public: // Inlines:
inline void SetNetProcessingTimeMsecs(const double flStartTime, const double flCurrentTime)
{ m_flNetProcessingTimeMsecs = (flCurrentTime * 1000) - (flStartTime * 1000); }
inline double GetNetProcessingTimeMsecs(void) const { return m_flNetProcessingTimeMsecs; }
inline void SetNetProcessingTimeBase(const double flTime) { m_flNetProcessTimeBase = flTime; }
inline double GetNetProcessingTimeBase(void) const { return m_flNetProcessTimeBase; }
inline void SetStringCommandQuotaTimeStart(const double flTime) { m_flStringCommandQuotaTimeStart = flTime; }
inline double GetStringCommandQuotaTimeStart(void) const { return m_flStringCommandQuotaTimeStart; }
inline void SetStringCommandQuotaCount(const int iCount) { m_nStringCommandQuotaCount = iCount; }
inline int GetStringCommandQuotaCount(void) const { return m_nStringCommandQuotaCount; }
private:
// Measure how long this client's packets took to process.
double m_flNetProcessingTimeMsecs;
double m_flNetProcessTimeBase;
// The start time of the first stringcmd since reset.
double m_flStringCommandQuotaTimeStart;
int m_nStringCommandQuotaCount;
bool m_bInitialConVarsSet; // Whether or not the initial ConVar KV's are set
};
/* ==== CBASECLIENT ===================================================================================================================================================== */ /* ==== CBASECLIENT ===================================================================================================================================================== */
inline CMemory p_CClient_Connect; inline bool(*CClient__Connect)(CClient* pClient, const char* szName, CNetChan* pNetChan, bool bFakePlayer, CUtlVector<NET_SetConVar::cvar_t>* conVars, char* szMessage, int nMessageSize);
inline bool(*v_CClient_Connect)(CClient* pClient, const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize); inline bool(*CClient__Disconnect)(CClient* pClient, const Reputation_t nRepLvl, const char* szReason, ...);
inline void(*CClient__Clear)(CClient* pClient);
inline CMemory p_CClient_Disconnect; inline void(*CClient__ActivatePlayer)(CClient* pClient);
inline bool(*v_CClient_Disconnect)(CClient* pClient, const Reputation_t nRepLvl, const char* szReason, ...); inline bool(*CClient__SetSignonState)(CClient* pClient, SIGNONSTATE signon);
inline bool(*CClient__SendNetMsgEx)(CClient* pClient, CNetMessage* pMsg, bool bLocal, bool bForceReliable, bool bVoice);
inline CMemory p_CClient_Clear; inline void*(*CClient__SendSnapshot)(CClient* pClient, CClientFrame* pFrame, int nTick, int nTickAck);
inline void(*v_CClient_Clear)(CClient* pClient); inline void(*CClient__WriteDataBlock)(CClient* pClient, bf_write& buf);
inline bool(*CClient__ProcessStringCmd)(CClient* pClient, NET_StringCmd* pMsg);
inline CMemory p_CClient_ActivatePlayer; inline bool(*CClient__ProcessSetConVar)(CClient* pClient, NET_SetConVar* pMsg);
inline void(*v_CClient_ActivatePlayer)(CClient* pClient);
inline CMemory p_CClient_ProcessStringCmd;
inline bool(*v_CClient_ProcessStringCmd)(CClient* pClient, NET_StringCmd* pMsg);
inline CMemory p_CClient_SetSignonState;
inline bool(*v_CClient_SetSignonState)(CClient* pClient, SIGNONSTATE signon);
inline CMemory p_CClient_SendNetMsgEx;
inline bool(*v_CClient_SendNetMsgEx)(CClient* pClient, CNetMessage* pMsg, bool bLocal, bool bForceReliable, bool bVoice);
inline CMemory p_CClient_SendSnapshot;
inline void*(*v_CClient_SendSnapshot)(CClient* pClient, CClientFrame* pFrame, int nTick, int nTickAck);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VClient : public IDetour class VClient : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CClient::Connect", p_CClient_Connect.GetPtr()); LogFunAdr("CClient::Connect", CClient__Connect);
LogFunAdr("CClient::Disconnect", p_CClient_Disconnect.GetPtr()); LogFunAdr("CClient::Disconnect", CClient__Disconnect);
LogFunAdr("CClient::Clear", p_CClient_Clear.GetPtr()); LogFunAdr("CClient::Clear", CClient__Clear);
LogFunAdr("CClient::ActivatePlayer", p_CClient_ActivatePlayer.GetPtr()); LogFunAdr("CClient::ActivatePlayer", CClient__ActivatePlayer);
LogFunAdr("CClient::ProcessStringCmd", p_CClient_ProcessStringCmd.GetPtr()); LogFunAdr("CClient::SetSignonState", CClient__SetSignonState);
LogFunAdr("CClient::SetSignonState", p_CClient_SetSignonState.GetPtr()); LogFunAdr("CClient::SendNetMsgEx", CClient__SendNetMsgEx);
LogFunAdr("CClient::SendNetMsgEx", p_CClient_SendNetMsgEx.GetPtr()); LogFunAdr("CClient::SendSnapshot", CClient__SendSnapshot);
LogFunAdr("CClient::SendSnapshot", p_CClient_SendSnapshot.GetPtr()); LogFunAdr("CClient::WriteDataBlock", CClient__WriteDataBlock);
LogFunAdr("CClient::ProcessStringCmd", CClient__ProcessStringCmd);
LogFunAdr("CClient::ProcessSetConVar", CClient__ProcessSetConVar);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_CClient_Connect = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 20 41 0F B6 E9"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 20 41 0F B6 E9").GetPtr(CClient__Connect);
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2) g_GameDll.FindPatternSIMD("48 8B C4 4C 89 40 18 4C 89 48 20 53 56 57 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ?? 49 8B F8 8B F2").GetPtr(CClient__Disconnect);
p_CClient_Disconnect = g_GameDll.FindPatternSIMD("48 8B C4 4C 89 40 18 4C 89 48 20 53 56 57 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ?? 49 8B F8 0F B6 F2"); g_GameDll.FindPatternSIMD("40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74").GetPtr(CClient__Clear);
#else // !GAMEDLL_S0 || !GAMEDLL_S1 || !GAMEDLL_S2 g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 8B 81 B0 03 ?? ?? 48 8B D9 C6").GetPtr(CClient__ActivatePlayer);
p_CClient_Disconnect = g_GameDll.FindPatternSIMD("48 8B C4 4C 89 40 18 4C 89 48 20 53 56 57 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ?? 49 8B F8 8B F2"); g_GameDll.FindPatternSIMD("40 53 55 56 57 41 56 48 83 EC 40 48 8B 05 ?? ?? ?? ??").GetPtr(CClient__SendNetMsgEx);
#endif g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 56 41 55 41 56 41 57 48 8D 6C 24 ??").GetPtr(CClient__SendSnapshot);
p_CClient_Clear = g_GameDll.FindPatternSIMD("40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74"); g_GameDll.FindPatternSIMD("40 53 57 48 83 EC 38 48 8B 05 ?? ?? ?? ??").GetPtr(CClient__WriteDataBlock);
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 7A 20").GetPtr(CClient__ProcessStringCmd);
p_CClient_ActivatePlayer = g_GameDll.FindPatternSIMD("40 53 57 41 57 48 83 EC 30 8B 81 ?? ?? ?? ??");
p_CClient_ProcessStringCmd = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 81 EC ?? ?? ?? ?? 49 8B D8");
p_CClient_SendNetMsg = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 30 48 8B 05 ?? ?? ?? ?? 45 0F B6 F1");
p_CClient_SendSnapshot = g_GameDll.FindPatternSIMD("44 89 44 24 ?? 48 89 4C 24 ?? 55 53 56 57 41 55");
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_CClient_ActivatePlayer = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 8B 81 B0 03 ?? ?? 48 8B D9 C6");
p_CClient_ProcessStringCmd = g_GameDll.FindPatternSIMD("48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 7A 20");
p_CClient_SendNetMsgEx = g_GameDll.FindPatternSIMD("40 53 55 56 57 41 56 48 83 EC 40 48 8B 05 ?? ?? ?? ??");
p_CClient_SendSnapshot = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 56 41 55 41 56 41 57 48 8D 6C 24 ??");
#endif // !GAMEDLL_S0 || !GAMEDLL_S1
p_CClient_SetSignonState = g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 10 48 89 70 18 57 48 81 EC ?? ?? ?? ?? 0F 29 70 E8 8B F2");
v_CClient_Connect = p_CClient_Connect.RCast<bool (*)(CClient*, const char*, void*, bool, void*, char*, int)>(); g_GameDll.FindPatternSIMD("48 83 EC 28 48 83 C2 20").GetPtr(CClient__ProcessSetConVar);
v_CClient_Disconnect = p_CClient_Disconnect.RCast<bool (*)(CClient*, const Reputation_t, const char*, ...)>(); g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 10 48 89 70 18 57 48 81 EC ?? ?? ?? ?? 0F 29 70 E8 8B F2").GetPtr(CClient__SetSignonState);
v_CClient_Clear = p_CClient_Clear.RCast<void (*)(CClient*)>();
v_CClient_ActivatePlayer = p_CClient_ActivatePlayer.RCast<void (*)(CClient* pClient)>();
v_CClient_ProcessStringCmd = p_CClient_ProcessStringCmd.RCast<bool (*)(CClient*, NET_StringCmd*)>();
v_CClient_SetSignonState = p_CClient_SetSignonState.RCast<bool (*)(CClient*, SIGNONSTATE)>();
v_CClient_SendNetMsgEx = p_CClient_SendNetMsgEx.RCast<bool (*)(CClient*, CNetMessage*, bool, bool, bool)>();
v_CClient_SendSnapshot = p_CClient_SendSnapshot.RCast<void* (*)(CClient*, CClientFrame*, int, int)>();
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -9,13 +9,20 @@
// //
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
#include "core/stdafx.h" #include "core/stdafx.h"
#include "vpc/keyvalues.h"
#include "tier0/frametask.h" #include "tier0/frametask.h"
#include "engine/common.h"
#include "engine/host.h" #include "engine/host.h"
#include "engine/host_cmd.h"
#ifndef CLIENT_DLL
#include "engine/server/server.h"
#endif // !CLIENT_DLL
#include "clientstate.h" #include "clientstate.h"
#include "common/callback.h" #include "common/callback.h"
#include "cdll_engine_int.h" #include "cdll_engine_int.h"
#include "vgui/vgui_baseui_interface.h" #include "vgui/vgui_baseui_interface.h"
#include "rtech/playlists/playlists.h"
#include <ebisusdk/EbisuSDK.h>
#include <engine/cmd.h>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -58,7 +65,7 @@ float CClientState::GetClientTime() const
{ {
if (m_bClockCorrectionEnabled) if (m_bClockCorrectionEnabled)
{ {
return (float)m_ClockDriftMgr.m_nSimulationTick * (*(float*)&interval_per_tick); // VERIFY DEREF return (float)m_ClockDriftMgr.m_nSimulationTick * g_pCommonHostState->interval_per_tick;
} }
else else
{ {
@ -128,12 +135,12 @@ void CClientState::VConnectionClosing(CClientState* thisptr, const char* szReaso
// Delay execution to the next frame; this is required to avoid a rare crash. // Delay execution to the next frame; this is required to avoid a rare crash.
// Cannot reload playlists while still disconnecting. // Cannot reload playlists while still disconnecting.
g_TaskScheduler->Dispatch([]() g_TaskQueue.Dispatch([]()
{ {
// Reload the local playlist to override the cached // Reload the local playlist to override the cached
// one from the server we got disconnected from. // one from the server we got disconnected from.
_DownloadPlaylists_f(); v_Playlists_Download_f();
KeyValues::InitPlaylists(); Playlists_SDKInit();
}, 0); }, 0);
} }
@ -144,35 +151,258 @@ void CClientState::VConnectionClosing(CClientState* thisptr, const char* szReaso
// no longer can process server ticks every frame unlike previous games. // no longer can process server ticks every frame unlike previous games.
// Without this, the server CPU and frame time don't get updated to the client. // Without this, the server CPU and frame time don't get updated to the client.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool CClientState::VProcessServerTick(CClientState* pClientState, SVC_ServerTick* pServerTick) bool CClientState::VProcessServerTick(CClientState* thisptr, SVC_ServerTick* msg)
{ {
if (pServerTick->m_NetTick.m_nCommandTick != -1) if (msg->m_NetTick.m_nCommandTick != -1)
{ {
return CClientState__ProcessServerTick(pClientState, pServerTick); // Updates statistics and updates clockdrift.
return CClientState__ProcessServerTick(thisptr, msg);
} }
else // Statistics only. else // Statistics only.
{ {
char* pShifted = reinterpret_cast<char*>(pClientState) - 0x10; // Shifted due to compiler optimizations. CClientState* const thisptr_ADJ = thisptr->GetShiftedBasePointer();
CClientState* pClient_Adj = reinterpret_cast<CClientState*>(pShifted);
CNetChan* pChan = pClient_Adj->m_NetChannel; if (thisptr_ADJ->IsConnected())
pChan->SetRemoteFramerate(pServerTick->m_NetTick.m_flHostFrameTime, pServerTick->m_NetTick.m_flHostFrameTimeStdDeviation); {
pChan->SetRemoteCPUStatistics(pServerTick->m_NetTick.m_nServerCPU); CNetChan* const pChan = thisptr_ADJ->m_NetChannel;
pChan->SetRemoteFramerate(msg->m_NetTick.m_flHostFrameTime, msg->m_NetTick.m_flHostFrameTimeStdDeviation);
pChan->SetRemoteCPUStatistics(msg->m_NetTick.m_nServerCPU);
}
return true; return true;
} }
} }
void VClientState::Attach() const //------------------------------------------------------------------------------
// Purpose: processes string commands sent from server
// Input : *thisptr -
// *msg -
// Output : true on success, false otherwise
//------------------------------------------------------------------------------
bool CClientState::_ProcessStringCmd(CClientState* thisptr, NET_StringCmd* msg)
{ {
DetourAttach(&CClientState__ConnectionClosing, &CClientState::VConnectionClosing); CClientState* const thisptr_ADJ = thisptr->GetShiftedBasePointer();
DetourAttach(&CClientState__ProcessServerTick, &CClientState::VProcessServerTick);
if (thisptr_ADJ->m_bRestrictServerCommands
#ifndef CLIENT_DLL
&& !g_pServer->IsActive()
#endif // !CLIENT_DLL
)
{
CCommand args;
args.Tokenize(msg->cmd, cmd_source_t::kCommandSrcInvalid);
if (args.ArgC() > 0)
{
if (!Cbuf_AddTextWithMarkers(msg->cmd,
eCmdExecutionMarker_Enable_FCVAR_SERVER_CAN_EXECUTE,
eCmdExecutionMarker_Disable_FCVAR_SERVER_CAN_EXECUTE))
{
DevWarning(eDLL_T::CLIENT, "%s: No room for %i execution markers; command \"%s\" ignored\n",
__FUNCTION__, 2, msg->cmd);
}
return true;
}
}
else
{
Cbuf_AddText(Cbuf_GetCurrentPlayer(), msg->cmd, cmd_source_t::kCommandSrcCode);
}
return true;
} }
void VClientState::Detach() const //------------------------------------------------------------------------------
// Purpose: create's string tables from string table data sent from server
// Input : *thisptr -
// *msg -
// Output : true on success, false otherwise
//------------------------------------------------------------------------------
bool CClientState::_ProcessCreateStringTable(CClientState* thisptr, SVC_CreateStringTable* msg)
{ {
DetourDetach(&CClientState__ConnectionClosing, &CClientState::VConnectionClosing); CClientState* const cl = thisptr->GetShiftedBasePointer();
DetourDetach(&CClientState__ProcessServerTick, &CClientState::VProcessServerTick);
if (!cl->IsConnected())
return false;
CNetworkStringTableContainer* const container = cl->m_StringTableContainer;
// Must have a string table container at this point!
if (!container)
{
Assert(0);
COM_ExplainDisconnection(true, "String table container missing.\n");
v_Host_Disconnect(true);
return false;
}
container->AllowCreation(true);
const ssize_t startbit = msg->m_DataIn.GetNumBitsRead();
CNetworkStringTable* const table = (CNetworkStringTable*)container->CreateStringTable(false, msg->m_szTableName,
msg->m_nMaxEntries, msg->m_nUserDataSize, msg->m_nUserDataSizeBits, msg->m_nDictFlags);
table->SetTick(cl->GetServerTickCount());
CClientState__HookClientStringTable(cl, msg->m_szTableName);
if (msg->m_bDataCompressed)
{
// TODO[ AMOS ]: check sizes before proceeding to decode
// the string tables
unsigned int msgUncompressedSize = msg->m_DataIn.ReadLong();
unsigned int msgCompressedSize = msg->m_DataIn.ReadLong();
size_t uncompressedSize = msgUncompressedSize;
size_t compressedSize = msgCompressedSize;
bool bSuccess = false;
// TODO[ AMOS ]: this could do better. The engine does UINT_MAX-3
// which doesn't look very great. Clamp to more reasonable values
// than UINT_MAX-3 or UINT_MAX/2? The largest string tables sent
// are settings layout string tables which are roughly 256KiB
// compressed with LZSS. perhaps clamp this to something like 16MiB?
if (msg->m_DataIn.TotalBytesAvailable() > 0 &&
msgCompressedSize <= (unsigned int)msg->m_DataIn.TotalBytesAvailable() &&
msgCompressedSize < UINT_MAX / 2 && msgUncompressedSize < UINT_MAX / 2)
{
// allocate buffer for uncompressed data, align to 4 bytes boundary
uint8_t* const uncompressedBuffer = new uint8_t[PAD_NUMBER(msgUncompressedSize, 4)];
uint8_t* const compressedBuffer = new uint8_t[PAD_NUMBER(msgCompressedSize, 4)];
msg->m_DataIn.ReadBytes(compressedBuffer, msgCompressedSize);
// uncompress data
bSuccess = NET_BufferToBufferDecompress(compressedBuffer, compressedSize, uncompressedBuffer, uncompressedSize);
bSuccess &= (uncompressedSize == msgUncompressedSize);
if (bSuccess)
{
bf_read data(uncompressedBuffer, (int)uncompressedSize);
table->ParseUpdate(data, msg->m_nNumEntries);
}
delete[] uncompressedBuffer;
delete[] compressedBuffer;
}
if (!bSuccess)
{
Assert(false);
DevWarning(eDLL_T::CLIENT, "%s: Received malformed string table message!\n", __FUNCTION__);
}
}
else
{
table->ParseUpdate(msg->m_DataIn, msg->m_nNumEntries);
}
container->AllowCreation(false);
const ssize_t endbit = msg->m_DataIn.GetNumBitsRead();
return (endbit - startbit) == msg->m_nLength;
}
static ConVar cl_onlineAuthEnable("cl_onlineAuthEnable", "1", FCVAR_RELEASE, "Enables the client-side online authentication system");
static ConVar cl_onlineAuthToken("cl_onlineAuthToken", "", FCVAR_HIDDEN | FCVAR_USERINFO | FCVAR_DONTRECORD | FCVAR_SERVER_CANNOT_QUERY | FCVAR_PLATFORM_SYSTEM, "The client's online authentication token");
static ConVar cl_onlineAuthTokenSignature1("cl_onlineAuthTokenSignature1", "", FCVAR_HIDDEN | FCVAR_USERINFO | FCVAR_DONTRECORD | FCVAR_SERVER_CANNOT_QUERY | FCVAR_PLATFORM_SYSTEM, "The client's online authentication token signature", false, 0.f, false, 0.f, "Primary");
static ConVar cl_onlineAuthTokenSignature2("cl_onlineAuthTokenSignature2", "", FCVAR_HIDDEN | FCVAR_USERINFO | FCVAR_DONTRECORD | FCVAR_SERVER_CANNOT_QUERY | FCVAR_PLATFORM_SYSTEM, "The client's online authentication token signature", false, 0.f, false, 0.f, "Secondary");
//------------------------------------------------------------------------------
// Purpose: get authentication token for current connection context
// Input : *connectParams -
// *reasonBuf -
// reasonBufLen -
// Output : true on success, false otherwise
//------------------------------------------------------------------------------
bool CClientState::Authenticate(connectparams_t* connectParams, char* const reasonBuf, const size_t reasonBufLen) const
{
#define FORMAT_ERROR_REASON(fmt, ...) V_snprintf(reasonBuf, reasonBufLen, fmt, ##__VA_ARGS__);
string msToken; // token returned by the masterserver authorising the client to play online
string message; // message returned by the masterserver about the result of the auth
// verify that the client is not lying about their account identity
// code is immediately discarded upon verification
const bool ret = g_MasterServer.AuthForConnection(*g_NucleusID, connectParams->netAdr, g_OriginAuthCode, msToken, message);
if (!ret)
{
FORMAT_ERROR_REASON("%s", message.c_str());
return false;
}
// get full token
const char* token = msToken.c_str();
// get a pointer to the delimiter that begins the token's signature
const char* tokenSignatureDelim = strrchr(token, '.');
if (!tokenSignatureDelim)
{
FORMAT_ERROR_REASON("Invalid token returned by MS");
return false;
}
// replace the delimiter with a null char so the first cvar only takes the header and payload data
*(char*)tokenSignatureDelim = '\0';
const size_t sigLength = strlen(tokenSignatureDelim) - 1;
cl_onlineAuthToken.SetValue(token);
if (sigLength > 0)
{
// get a pointer to the first part of the token signature to store in cl_onlineAuthTokenSignature1
const char* tokenSignaturePart1 = tokenSignatureDelim + 1;
cl_onlineAuthTokenSignature1.SetValue(tokenSignaturePart1);
if (sigLength > 255)
{
// get a pointer to the rest of the token signature to store in cl_onlineAuthTokenSignature2
const char* tokenSignaturePart2 = tokenSignaturePart1 + 255;
cl_onlineAuthTokenSignature2.SetValue(tokenSignaturePart2);
}
}
return true;
#undef REJECT_CONNECTION
}
bool IsLocalHost(connectparams_t* connectParams)
{
return (strstr(connectParams->netAdr, "localhost") || strstr(connectParams->netAdr, "127.0.0.1"));
}
void CClientState::VConnect(CClientState* thisptr, connectparams_t* connectParams)
{
if (cl_onlineAuthEnable.GetBool() && !IsLocalHost(connectParams))
{
char authFailReason[512];
if (!thisptr->Authenticate(connectParams, authFailReason, sizeof(authFailReason)))
{
COM_ExplainDisconnection(true, "Failed to authenticate for online play: %s", authFailReason);
return;
}
}
CClientState__Connect(thisptr, connectParams);
}
void VClientState::Detour(const bool bAttach) const
{
DetourSetup(&CClientState__ConnectionClosing, &CClientState::VConnectionClosing, bAttach);
DetourSetup(&CClientState__ProcessStringCmd, &CClientState::_ProcessStringCmd, bAttach);
DetourSetup(&CClientState__ProcessServerTick, &CClientState::VProcessServerTick, bAttach);
DetourSetup(&CClientState__ProcessCreateStringTable, &CClientState::_ProcessCreateStringTable, bAttach);
DetourSetup(&CClientState__Connect, &CClientState::VConnect, bAttach);
} }
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////

View File

@ -5,12 +5,23 @@
#include "public/inetmsghandler.h" #include "public/inetmsghandler.h"
#include "public/isnapshotmgr.h" #include "public/isnapshotmgr.h"
#include "engine/net_chan.h" #include "engine/net_chan.h"
#include "engine/networkstringtable.h"
#include "engine/debugoverlay.h" #include "engine/debugoverlay.h"
#include "engine/clockdriftmgr.h" #include "engine/clockdriftmgr.h"
#include "engine/framesnapshot.h" #include "engine/framesnapshot.h"
#include "engine/packed_entity.h" #include "engine/packed_entity.h"
#include "datablock_receiver.h" #include "datablock_receiver.h"
struct connectparams_t
{
const char* netAdr;
const char* netKey;
int unkReconnect;
int unk;
bool challengeRequest;
bool asSpectator_MAYBE;
};
class CClientSnapshotManager : public IClientSnapshotManager class CClientSnapshotManager : public IClientSnapshotManager
{ {
public: public:
@ -26,7 +37,11 @@ class CClientState : CS_INetChannelHandler, IConnectionlessPacketHandler, IServe
friend class ClientDataBlockReceiver; friend class ClientDataBlockReceiver;
public: // Hook statics. public: // Hook statics.
static void VConnectionClosing(CClientState* thisptr, const char* szReason); static void VConnectionClosing(CClientState* thisptr, const char* szReason);
static bool _ProcessStringCmd(CClientState* thisptr, NET_StringCmd* msg);
static bool VProcessServerTick(CClientState* thisptr, SVC_ServerTick* msg); static bool VProcessServerTick(CClientState* thisptr, SVC_ServerTick* msg);
static bool _ProcessCreateStringTable(CClientState* thisptr, SVC_CreateStringTable* msg);
static void VConnect(CClientState* thisptr, connectparams_t* connectParams);
public: public:
bool IsPaused() const; bool IsPaused() const;
@ -46,6 +61,21 @@ public:
float GetFrameTime(void) const; float GetFrameTime(void) const;
bool Authenticate(connectparams_t* connectParams, char* const reasonBuf, const size_t reasonBufLen) const;
protected:
FORCEINLINE CClientState* GetShiftedBasePointer(void)
{
// NOTE: you must check in the disassembler if the CClientState method
// you detour is shifting the 'this' pointer with 16 bytes forward, if
// so, you need to call this and use this pointer instead! The shifting
// happens as part of a compiler optimization that truncated the vtable
// pointers off so the 'this' pointer points directly to the class data
char* const pShifted = reinterpret_cast<char*>(this) - 0x10;
return reinterpret_cast<CClientState*>(pShifted);
}
public:
int m_Socket; int m_Socket;
int _padding_maybe; int _padding_maybe;
CNetChan* m_NetChannel; CNetChan* m_NetChannel;
@ -84,9 +114,9 @@ public:
int m_nPlayerSlot; int m_nPlayerSlot;
char m_szLevelFileName[64]; char m_szLevelFileName[64];
char m_szLevelBaseName[64]; char m_szLevelBaseName[64];
char field_1F0[64]; char m_szLastLevelBaseName[64];
char field_230[64]; char m_szSkyBoxBaseName[64];
_BYTE m_szServerAddresString[128]; char m_szServerAddresString[128];
int m_bInMpLobbyMenu; int m_bInMpLobbyMenu;
int m_nTeam; int m_nTeam;
_DWORD m_nMaxClients; _DWORD m_nMaxClients;
@ -97,22 +127,19 @@ public:
_BYTE m_bSignonChallengeReceived; _BYTE m_bSignonChallengeReceived;
_DWORD challenge; _DWORD challenge;
netadr_t challengeAddr; netadr_t challengeAddr;
_BYTE byte33C; bool m_bUseLocalSendTableFile;
_QWORD m_pServerClasses; _QWORD m_pServerClasses;
int m_nServerClasses; int m_nServerClasses;
int m_nServerClassBits; int m_nServerClassBits;
__int64 m_StringTableContainer; CNetworkStringTableContainer* m_StringTableContainer;
char m_PersistenceData[98304]; char m_PersistenceData[98304];
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
char pads0[8];
#endif
_BYTE m_bPersistenceBaselineRecvd; _BYTE m_bPersistenceBaselineRecvd;
int m_nPersistenceBaselineEntries; int m_nPersistenceBaselineEntries;
int field_18350; int field_18350;
bool m_bRestrictServerCommands; bool m_bRestrictServerCommands;
bool m_bRestrictClientCommands; bool m_bRestrictClientCommands;
char buffer_0x400[1024]; char buffer_0x400[1024];
ClientDataBlockReceiver blockReceiver; ClientDataBlockReceiver m_DataBlockReceiver;
char client_requested_disconnect; char client_requested_disconnect;
char error_message[512]; char error_message[512];
_BYTE gap18CA1[3]; _BYTE gap18CA1[3];
@ -148,9 +175,7 @@ public:
__int64 qword18D20; __int64 qword18D20;
int dword18D28; int dword18D28;
int dword18D2C; int dword18D2C;
float field_18D30; Vector3D field_18D30;
float m_flUnk1;
float m_flUnk2;
int dword18D3C; int dword18D3C;
int dword18D40; int dword18D40;
char gap18D44[4]; char gap18D44[4];
@ -160,7 +185,6 @@ public:
int dword18D60; int dword18D60;
char gap18D64[4]; char gap18D64[4];
__int64 qword18D68; __int64 qword18D68;
char gap18D70[8];
char buffer_47128[47128]; char buffer_47128[47128];
char entitlements_bitfield[16]; char entitlements_bitfield[16];
__int64 maybe_some_ll_stuff; __int64 maybe_some_ll_stuff;
@ -176,9 +200,7 @@ public:
__int64 qword245F0; __int64 qword245F0;
int dword245F8; int dword245F8;
char gap245FC[1024]; char gap245FC[1024];
int dword249EC;//249EC int dword249EC;
int dword249F0;
char gap24A04[4];
__int64 m_pModelPrecacheTable; __int64 m_pModelPrecacheTable;
__int64 qword24A10; __int64 qword24A10;
__int64 m_pInstanceBaselineTable; __int64 m_pInstanceBaselineTable;
@ -189,11 +211,7 @@ public:
char byte34A38; char byte34A38;
char field_34A39[7]; char field_34A39[7];
}; };
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) static_assert(sizeof(CClientState) == 0x34A20);
static_assert(sizeof(CClientState) == 0x34A38);
#else
static_assert(sizeof(CClientState) == 0x34A30);
#endif
#ifndef DEDICATED #ifndef DEDICATED
extern CClientState* g_pClientState; extern CClientState* g_pClientState;
@ -201,48 +219,42 @@ extern CClientState** g_pClientState_Shifted; // Shifted by 0x10 forward!
#endif // DEDICATED #endif // DEDICATED
/* ==== CCLIENTSTATE ==================================================================================================================================================== */ /* ==== CCLIENTSTATE ==================================================================================================================================================== */
inline CMemory p_CClientState__RunFrame;
inline void(*CClientState__RunFrame)(CClientState* thisptr); inline void(*CClientState__RunFrame)(CClientState* thisptr);
inline void(*CClientState__Connect)(CClientState* thisptr, connectparams_t* connectParams);
inline CMemory p_CClientState__Disconnect;
inline void(*CClientState__Disconnect)(CClientState* thisptr, bool bSendTrackingContext); inline void(*CClientState__Disconnect)(CClientState* thisptr, bool bSendTrackingContext);
inline CMemory p_CClientState__ConnectionClosing;
inline void(*CClientState__ConnectionClosing)(CClientState* thisptr, const char* szReason); inline void(*CClientState__ConnectionClosing)(CClientState* thisptr, const char* szReason);
inline bool(*CClientState__HookClientStringTable)(CClientState* thisptr, const char* tableName);
inline CMemory p_CClientState__ProcessServerTick; inline bool(*CClientState__ProcessStringCmd)(CClientState* thisptr, NET_StringCmd* msg);
inline bool(*CClientState__ProcessServerTick)(CClientState* thisptr, SVC_ServerTick* msg); inline bool(*CClientState__ProcessServerTick)(CClientState* thisptr, SVC_ServerTick* msg);
inline bool(*CClientState__ProcessCreateStringTable)(CClientState* thisptr, SVC_CreateStringTable* msg);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VClientState : public IDetour class VClientState : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CClientState::RunFrame", p_CClientState__RunFrame.GetPtr()); LogFunAdr("CClientState::RunFrame", CClientState__RunFrame);
LogFunAdr("CClientState::Disconnect", p_CClientState__Disconnect.GetPtr()); LogFunAdr("CClientState::Connect", CClientState__Connect);
LogFunAdr("CClientState::ConnectionClosing", p_CClientState__ConnectionClosing.GetPtr()); LogFunAdr("CClientState::Disconnect", CClientState__Disconnect);
LogFunAdr("CClientState::ProcessServerTick", p_CClientState__ProcessServerTick.GetPtr()); LogFunAdr("CClientState::ConnectionClosing", CClientState__ConnectionClosing);
LogVarAdr("g_ClientState", reinterpret_cast<uintptr_t>(g_pClientState)); LogFunAdr("CClientState::HookClientStringTable", CClientState__HookClientStringTable);
LogVarAdr("g_ClientState_Shifted", reinterpret_cast<uintptr_t>(g_pClientState_Shifted)); LogFunAdr("CClientState::ProcessStringCmd", CClientState__ProcessStringCmd);
LogFunAdr("CClientState::ProcessServerTick", CClientState__ProcessServerTick);
LogFunAdr("CClientState::ProcessCreateStringTable", CClientState__ProcessCreateStringTable);
LogVarAdr("g_ClientState", g_pClientState);
LogVarAdr("g_ClientState_Shifted", g_pClientState_Shifted);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ?? 48 8B D9 7D 0B").GetPtr(CClientState__RunFrame);
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 81 EC ?? ?? ?? ?? 48 8B 32").GetPtr(CClientState__Connect);
p_CClientState__RunFrame = g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 57 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("40 56 57 41 54 41 55 41 57 48 83 EC 30 44 0F B6 FA").GetPtr(CClientState__Disconnect);
p_CClientState__Disconnect = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 57 41 56 48 83 EC 30 0F B6 EA"); g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B DA 0F 8E ?? ?? ?? ??").GetPtr(CClientState__ConnectionClosing);
p_CClientState__ConnectionClosing = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B DA 7E 6E"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B D9 48 8B FA 48 8B 89 ?? ?? ?? ?? 48 85 C9 0F 84 ?? ?? ?? ??").GetPtr(CClientState__HookClientStringTable);
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 80 B9 ?? ?? ?? ?? ?? 48 8B DA").GetPtr(CClientState__ProcessStringCmd);
p_CClientState__RunFrame = g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ?? 48 8B D9 7D 0B"); g_GameDll.FindPatternSIMD("40 57 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B F9 7C 66").GetPtr(CClientState__ProcessServerTick);
p_CClientState__Disconnect = g_GameDll.FindPatternSIMD("40 56 57 41 54 41 55 41 57 48 83 EC 30 44 0F B6 FA"); g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 53 56 48 81 EC ?? ?? ?? ?? 83 B9 ?? ?? ?? ?? ??").GetPtr(CClientState__ProcessCreateStringTable);
p_CClientState__ConnectionClosing = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B DA 0F 8E ?? ?? ?? ??");
#endif
p_CClientState__ProcessServerTick = g_GameDll.FindPatternSIMD("40 57 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B F9 7C 66");
CClientState__RunFrame = p_CClientState__RunFrame.RCast<void(*)(CClientState*)>();
CClientState__Disconnect = p_CClientState__Disconnect.RCast<void(*)(CClientState*, bool)>();
CClientState__ConnectionClosing = p_CClientState__ConnectionClosing.RCast<void(*)(CClientState*, const char*)>();
CClientState__ProcessServerTick = p_CClientState__ProcessServerTick.RCast<bool(*)(CClientState*, SVC_ServerTick*)>();
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
@ -250,7 +262,6 @@ class VClientState : public IDetour
g_pClientState_Shifted = reinterpret_cast<CClientState**>(reinterpret_cast<int64_t*>(g_pClientState)+1); // Shift by 8 bytes. g_pClientState_Shifted = reinterpret_cast<CClientState**>(reinterpret_cast<int64_t*>(g_pClientState)+1); // Shift by 8 bytes.
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -1,24 +1,162 @@
//===========================================================================// //===========================================================================//
// //
// Purpose: client side datablock receiver // Purpose: client side data block receiver
// //
//===========================================================================// //===========================================================================//
#include "engine/client/clientstate.h" #include "engine/client/clientstate.h"
#include "datablock_receiver.h" #include "datablock_receiver.h"
#include "common/proto_oob.h"
//----------------------------------------------------------------------------- #include "engine/common.h"
// Purpose: #include "engine/host_cmd.h"
//-----------------------------------------------------------------------------
ClientDataBlockReceiver::~ClientDataBlockReceiver()
{
v_ClientDataBlockReceiver__Destructor(this);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: send an ack back to the server to let them know // Purpose: send an ack back to the server to let them know
// we received the datablock // we received the data block
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ClientDataBlockReceiver::AcknowledgeTransmission() void ClientDataBlockReceiver::AcknowledgeTransmission()
{ {
v_ClientDataBlockReceiver__AcknowledgeTransmission(this); const CClientState* const cl = m_pClientState;
if (!cl)
{
Assert(0, "ClientDataBlockReceiver::AcknowledgeTransmission() called without a valid client handle!");
return;
}
const CNetChan* const chan = cl->m_NetChannel;
if (!chan)
{
Assert(0, "ClientDataBlockReceiver::AcknowledgeTransmission() called without a net channel!");
return;
}
char dataBuf[DATABLOCK_FRAGMENT_PACKET_SIZE];
bf_write buf(&dataBuf, sizeof(dataBuf));
buf.WriteLong(CONNECTIONLESS_HEADER);
buf.WriteByte(C2S_DATABLOCK_ACK);
buf.WriteShort(m_TransferId);
buf.WriteShort(m_nTransferNr);
for (int i = m_nTotalBlocks; (i--) > 0;)
{
if (m_BlockStatus[i])
{
// ack the last blockNr we recv'd and processed
buf.WriteShort(i);
break;
}
}
// send the data block ack packet
v_NET_SendPacket(NULL,
chan->GetSocket(),
chan->GetRemoteAddress(),
buf.GetData(),
buf.GetNumBytesWritten(),
NULL, false, NULL, true);
}
//-----------------------------------------------------------------------------
// Purpose: process the recv'd data block and reconstruct the fragmented data
//-----------------------------------------------------------------------------
bool ClientDataBlockReceiver::ProcessDataBlock(const double startTime, const short transferId, const int transferSize,
const short transferNr, const short currentBlockId, const void* const blockBuffer, const int blockBufferBytes)
{
// should we process a new transfer?
if (transferNr != m_nTransferNr)
ResetBlockReceiver(transferNr);
m_bInitialized = true;
// make sure we always receive fragments in order
if (transferId != m_TransferId || m_bCompletedRecv)
return false;
// initialize the receiver if this is the firs fragment
if (!m_bStartedRecv)
StartBlockReceiver(transferSize, startTime);
// received more blocks than the total # expected?
if (currentBlockId >= m_nTotalBlocks)
return false;
// check if we have already copied the data block
if (!m_BlockStatus[currentBlockId])
{
const int scratchBufferOffset = currentBlockId * MAX_DATABLOCK_FRAGMENT_SIZE;
if (blockBufferBytes + scratchBufferOffset <= m_nTransferSize)
memcpy(m_pScratchBuffer + scratchBufferOffset + (sizeof(ClientDataBlockHeader_s) -1), blockBuffer, blockBufferBytes);
++m_nBlockAckTick;
m_BlockStatus[currentBlockId] = true;
}
// check if we have recv'd enough fragments to decode the data
if (m_nBlockAckTick != m_nTotalBlocks)
return true;
AcknowledgeTransmission();
m_bCompletedRecv = true;
const ClientDataBlockHeader_s* const pHeader = reinterpret_cast<ClientDataBlockHeader_s*>(m_pScratchBuffer);
if (pHeader->isCompressed)
{
// NOTE: the engine's implementation of this function does NOT free
// this buffer when a malformed/corrupt LZ4 packet is sent to the
// receiver; wrapped buffer in unique_ptr to make sure it never leaks!
std::unique_ptr<char> encodedDataBuf(new char[SNAPSHOT_SCRATCH_BUFFER_SIZE]);
char* const pEncodedDataBuf = encodedDataBuf.get();
char* const dataLocation = m_pScratchBuffer + sizeof(ClientDataBlockHeader_s);
// copy the encoded data in the newly allocated buffer so we can decode back
// into the data block buffer we copied the encoded data from
const int compressedSize = m_nTransferSize -1;
memcpy(pEncodedDataBuf, dataLocation, compressedSize);
const int numDecode = LZ4_decompress_safe(pEncodedDataBuf, dataLocation, compressedSize, SNAPSHOT_SCRATCH_BUFFER_SIZE);
if (numDecode < 0)
{
Assert(0);
COM_ExplainDisconnection(true, "LZ4 error decompressing data block from server.\n");
v_Host_Disconnect(true);
return false;
}
m_nTransferSize = numDecode;
}
else
{
// truncate the byte that determines whether the data was compressed
m_nTransferSize--;
}
return true;
}
//-----------------------------------------------------------------------------
// NOTE: detoured for 2 reasons:
// 1: when a corrupt or malformed compress packet is sent, the code never freed
// the temporary copy buffer it made to decode the data into the scratch buf
// 2: exploring other compression algorithms for potential optimizations
//-----------------------------------------------------------------------------
static bool HK_ProcessDataBlock(ClientDataBlockReceiver* receiver, const double startTime,
const short transferId, const int transferSize, const short transferNr,
const short currentBlockId, const void* const blockBuffer, const int blockBufferBytes)
{
return receiver->ProcessDataBlock(startTime, transferId, transferSize, transferNr,
currentBlockId, blockBuffer, blockBufferBytes);
}
void VClientDataBlockReceiver::Detour(const bool bAttach) const
{
DetourAttach(&ClientDataBlockReceiver__ProcessDataBlock, HK_ProcessDataBlock);
} }

View File

@ -1,60 +1,55 @@
//===========================================================================//
//
// Purpose: client side data block receiver
//
//===========================================================================//
#ifndef DATABLOCK_RECEIVER_H #ifndef DATABLOCK_RECEIVER_H
#define DATABLOCK_RECEIVER_H #define DATABLOCK_RECEIVER_H
#include "idatablock.h" #include "engine/shared/datablock.h"
class CClientState; class CClientState;
class ClientDataBlockReceiver : public NetDataBlockReceiver class ClientDataBlockReceiver : public NetDataBlockReceiver
{ {
friend class CClientState;
public: public:
virtual ~ClientDataBlockReceiver();
virtual void AcknowledgeTransmission() override; virtual void AcknowledgeTransmission() override;
protected: bool ProcessDataBlock(const double startTime, const short transferId, const int transferSize,
CClientState* m_pClientState; const short counter, const short currentBlockId, const void* const blockBuffer, const int blockBufferBytes);
bool m_bStartedRecv;
bool m_bCompletedRecv;
bool byte12;
short m_TransferId;
short m_Counter;
bool m_bInitialized;
int m_nTransferSize;
int m_nTotalBlocks;
int m_nBlockAckTick;
double m_flStartTime;
bool m_BlockStatus[DATABLOCK_STATUS_SIZE];
void* m_pBigBuffer;
}; };
inline CMemory p_ClientDataBlockReceiver__Destructor; struct ClientDataBlockHeader_s
inline void*(*v_ClientDataBlockReceiver__Destructor)(ClientDataBlockReceiver* thisptr); {
char reserved[3]; // unused in retail
bool isCompressed;
};
inline CMemory p_ClientDataBlockReceiver__AcknowledgeTransmission; // virtual methods
inline void*(*v_ClientDataBlockReceiver__AcknowledgeTransmission)(ClientDataBlockReceiver* thisptr); inline void*(*ClientDataBlockReceiver__AcknowledgeTransmission)(ClientDataBlockReceiver* thisptr);
// non-virtual methods
inline bool (*ClientDataBlockReceiver__ProcessDataBlock)(ClientDataBlockReceiver* thisptr, const double time,
const short transferId, const int transferSize, const short counter, const short currentBlockId,
const void* const blockBuffer, const int blockBufferBytes);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VClientDataBlockReceiver : public IDetour class VClientDataBlockReceiver : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("ClientDataBlockReceiver::~ClientDataBlockReceiver", p_ClientDataBlockReceiver__Destructor.GetPtr()); LogFunAdr("ClientDataBlockReceiver::AcknowledgeTransmission", ClientDataBlockReceiver__AcknowledgeTransmission);
LogFunAdr("ClientDataBlockReceiver::AcknowledgeTransmission", p_ClientDataBlockReceiver__AcknowledgeTransmission.GetPtr()); LogFunAdr("ClientDataBlockReceiver::ProcessDataBlock", ClientDataBlockReceiver__ProcessDataBlock);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_ClientDataBlockReceiver__Destructor = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 8B DA 48 8B F9 E8 ?? ?? ?? ?? F6 C3 01 74" g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 4C 8B 51 08").GetPtr(ClientDataBlockReceiver__AcknowledgeTransmission);
" 0D BA ?? ?? ?? ?? 48 8B CF E8 ?? ?? ?? ?? 48 8B C7 48 8B 5C 24 ?? 48 83 C4 20 5F C3 CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24"
" ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8D 05 ?? ?? ?? ?? C6 41 12 00");
v_ClientDataBlockReceiver__Destructor = p_ClientDataBlockReceiver__Destructor.RCast<void* (*)(ClientDataBlockReceiver*)>();
p_ClientDataBlockReceiver__AcknowledgeTransmission = g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 4C 8B 51 08"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 30 0F B7 44 24 ??")
v_ClientDataBlockReceiver__AcknowledgeTransmission = p_ClientDataBlockReceiver__AcknowledgeTransmission.RCast<void* (*)(ClientDataBlockReceiver*)>(); .GetPtr(ClientDataBlockReceiver__ProcessDataBlock);
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -5,6 +5,7 @@
//=============================================================================// //=============================================================================//
#include "core/stdafx.h" #include "core/stdafx.h"
#include "engine/cmd.h"
#include "clientstate.h" #include "clientstate.h"
#include "vengineclient_impl.h" #include "vengineclient_impl.h"
@ -55,10 +56,43 @@ bool CEngineClient::GetRestrictClientCommands() const
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
int CEngineClient::GetLocalPlayer() int CEngineClient::GetLocalPlayer()
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
const static int index = 35;
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
const static int index = 36; const static int index = 36;
#endif
return CallVFunc<int>(index, this); return CallVFunc<int>(index, this);
} }
//---------------------------------------------------------------------------------
// Purpose: execute client command
// Input : *thisptr -
// *szCmdString -
// Output :
//---------------------------------------------------------------------------------
void CEngineClient::_ClientCmd(CEngineClient* thisptr, const char* const szCmdString)
{
const bool restrictClientCommands = g_pClientState->m_bRestrictClientCommands;
const int numMarkers = 2;
if (restrictClientCommands && !Cbuf_HasRoomForExecutionMarkers(numMarkers))
{
DevWarning(eDLL_T::CLIENT, "%s: No room for %i execution markers; command \"%s\" ignored\n",
__FUNCTION__, numMarkers, szCmdString);
return;
}
if (restrictClientCommands)
{
Cbuf_AddExecutionMarker(Cbuf_GetCurrentPlayer(), eCmdExecutionMarker_Enable_FCVAR_CLIENTCMD_CAN_EXECUTE);
}
Cbuf_AddText(Cbuf_GetCurrentPlayer(), szCmdString, cmd_source_t::kCommandSrcCode);
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "\n", cmd_source_t::kCommandSrcCode);
if (restrictClientCommands)
{
Cbuf_AddExecutionMarker(Cbuf_GetCurrentPlayer(), eCmdExecutionMarker_Disable_FCVAR_CLIENTCMD_CAN_EXECUTE);
}
}
void HVEngineClient::Detour(const bool bAttach) const
{
DetourSetup(&CEngineClient__ClientCmd, &CEngineClient::_ClientCmd, bAttach);
}

View File

@ -8,10 +8,15 @@ public:
void SetRestrictClientCommands(bool bRestrict); void SetRestrictClientCommands(bool bRestrict);
bool GetRestrictClientCommands() const; bool GetRestrictClientCommands() const;
int GetLocalPlayer(); // Local player index. int GetLocalPlayer(); // Local player index.
// Hook statics:
static void _ClientCmd(CEngineClient* thisptr, const char* const szCmdString);
}; };
/* ==== CVENGINECLIENT ================================================================================================================================================== */ /* ==== CVENGINECLIENT ================================================================================================================================================== */
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
inline void(*CEngineClient__ClientCmd)(CEngineClient* thisptr, const char* const szCmdString);
inline CMemory g_pEngineClientVFTable = nullptr; inline CMemory g_pEngineClientVFTable = nullptr;
inline CEngineClient* g_pEngineClient = nullptr; inline CEngineClient* g_pEngineClient = nullptr;
@ -20,16 +25,19 @@ class HVEngineClient : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogConAdr("CEngineClient::`vftable'", g_pEngineClientVFTable.GetPtr()); LogConAdr("CEngineClient::`vftable'", (void*)g_pEngineClientVFTable.GetPtr());
LogFunAdr("CEngineClient::ClientCmd", CEngineClient__ClientCmd);
}
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 80 3D ?? ?? ?? ?? ?? 48 8B DA 74 0C").GetPtr(CEngineClient__ClientCmd);
} }
virtual void GetFun(void) const { }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const virtual void GetCon(void) const
{ {
g_pEngineClientVFTable = g_GameDll.GetVirtualMethodTable(".?AVCEngineClient@@"); g_pEngineClientVFTable = g_GameDll.GetVirtualMethodTable(".?AVCEngineClient@@");
g_pEngineClient = g_pEngineClientVFTable.RCast<CEngineClient*>(); g_pEngineClient = g_pEngineClientVFTable.RCast<CEngineClient*>();
} }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -1,13 +1,69 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "tier1/cmd.h" #include "tier1/cmd.h"
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "tier1/commandbuffer.h"
#include "engine/cmd.h" #include "engine/cmd.h"
CCommandBuffer** s_pCommandBuffer = nullptr; // array size = ECommandTarget_t::CBUF_COUNT.
LPCRITICAL_SECTION s_pCommandBufferMutex = nullptr;
//=============================================================================
// List of execution markers
//=============================================================================
CUtlVector<int>* g_pExecutionMarkers = nullptr;
//-----------------------------------------------------------------------------
// Purpose: checks if there's room left for execution markers
// Input : cExecutionMarkers -
// Output : true if there's room for execution markers, false otherwise
//-----------------------------------------------------------------------------
bool Cbuf_HasRoomForExecutionMarkers(const int cExecutionMarkers)
{
return (g_pExecutionMarkers->Count() + cExecutionMarkers) < MAX_EXECUTION_MARKERS;
}
//-----------------------------------------------------------------------------
// Purpose: adds command text at the end of the command buffer with execution markers
// Input : *pText -
// markerLeft -
// markerRight -
// Output : true if there's room for execution markers, false otherwise
//-----------------------------------------------------------------------------
bool Cbuf_AddTextWithMarkers(const char* const pText, const ECmdExecutionMarker markerLeft, const ECmdExecutionMarker markerRight)
{
if (Cbuf_HasRoomForExecutionMarkers(2))
{
Cbuf_AddExecutionMarker(Cbuf_GetCurrentPlayer(), markerLeft);
Cbuf_AddText(Cbuf_GetCurrentPlayer(), pText, cmd_source_t::kCommandSrcCode);
Cbuf_AddExecutionMarker(Cbuf_GetCurrentPlayer(), markerRight);
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: adds command text at the end of the buffer
//-----------------------------------------------------------------------------
//void Cbuf_AddText(ECommandTarget_t eTarget, const char* pText, int nTickDelay)
//{
// LOCK_COMMAND_BUFFER();
// if (!s_pCommandBuffer[(int)eTarget]->AddText(pText, nTickDelay, cmd_source_t::kCommandSrcInvalid))
// {
// Error(eDLL_T::ENGINE, NO_ERROR, "%s: buffer overflow\n", __FUNCTION__);
// }
//}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Sends the entire command line over to the server // Purpose: Sends the entire command line over to the server
// Input : *args - // Input : *args -
// Output : true on success, false otherwise // Output : true on success, false otherwise
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef DEDICATED
ConVar cl_quota_stringCmdsPerSecond("cl_quota_stringCmdsPerSecond", "16", FCVAR_RELEASE, "How many string commands per second user is allowed to submit, 0 to allow all submissions.", true, 0.f, false, 0.f);
#endif // DEDICATED
bool Cmd_ForwardToServer(const CCommand* args) bool Cmd_ForwardToServer(const CCommand* args)
{ {
#ifndef DEDICATED #ifndef DEDICATED
@ -19,8 +75,8 @@ bool Cmd_ForwardToServer(const CCommand* args)
if (args->ArgC() == 0) if (args->ArgC() == 0)
return false; return false;
double flStartTime = Plat_FloatTime(); const double flStartTime = Plat_FloatTime();
int nCmdQuotaLimit = cl_quota_stringCmdsPerSecond->GetInt(); const int nCmdQuotaLimit = cl_quota_stringCmdsPerSecond.GetInt();
const char* pszCmdString = nullptr; const char* pszCmdString = nullptr;
// Special case: "cmd whatever args..." is forwarded as "whatever args..."; // Special case: "cmd whatever args..." is forwarded as "whatever args...";
@ -49,16 +105,13 @@ bool Cmd_ForwardToServer(const CCommand* args)
} }
return v_Cmd_ForwardToServer(args); return v_Cmd_ForwardToServer(args);
#else // !DEDICATED #else // !DEDICATED
Assert(0);
return false; // Client only. return false; // Client only.
#endif // DEDICATED #endif // DEDICATED
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VCmd::Attach() const void VCmd::Detour(const bool bAttach) const
{ {
DetourAttach((LPVOID*)&v_Cmd_ForwardToServer, &Cmd_ForwardToServer); DetourSetup(&v_Cmd_ForwardToServer, &Cmd_ForwardToServer, bAttach);
}
void VCmd::Detach() const
{
DetourDetach((LPVOID*)&v_Cmd_ForwardToServer, &Cmd_ForwardToServer);
} }

View File

@ -1,5 +1,17 @@
#ifndef CMD_H #ifndef CMD_H
#define CMD_H #define CMD_H
#include "tier1/commandbuffer.h"
#define MAX_EXECUTION_MARKERS 2048
typedef enum
{
eCmdExecutionMarker_Enable_FCVAR_SERVER_CAN_EXECUTE = 'a',
eCmdExecutionMarker_Disable_FCVAR_SERVER_CAN_EXECUTE = 'b',
eCmdExecutionMarker_Enable_FCVAR_CLIENTCMD_CAN_EXECUTE = 'c',
eCmdExecutionMarker_Disable_FCVAR_CLIENTCMD_CAN_EXECUTE = 'd'
} ECmdExecutionMarker;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Returns current player calling this function // Purpose: Returns current player calling this function
@ -11,46 +23,53 @@ FORCEINLINE ECommandTarget_t Cbuf_GetCurrentPlayer(void)
return ECommandTarget_t::CBUF_FIRST_PLAYER; return ECommandTarget_t::CBUF_FIRST_PLAYER;
} }
extern bool Cbuf_HasRoomForExecutionMarkers(const int cExecutionMarkers);
extern bool Cbuf_AddTextWithMarkers(const char* text, const ECmdExecutionMarker markerLeft, const ECmdExecutionMarker markerRight);
/* ==== COMMAND_BUFFER ================================================================================================================================================== */ /* ==== COMMAND_BUFFER ================================================================================================================================================== */
inline CMemory p_Cbuf_AddText;
inline void(*Cbuf_AddText)(ECommandTarget_t eTarget, const char* pText, cmd_source_t cmdSource); inline void(*Cbuf_AddText)(ECommandTarget_t eTarget, const char* pText, cmd_source_t cmdSource);
inline void(*Cbuf_AddExecutionMarker)(ECommandTarget_t target, ECmdExecutionMarker marker);
inline CMemory p_Cbuf_Execute;
inline void(*Cbuf_Execute)(void); inline void(*Cbuf_Execute)(void);
inline CMemory p_Cmd_Dispatch;
inline void(*v_Cmd_Dispatch)(ECommandTarget_t eTarget, const ConCommandBase* pCmdBase, const CCommand* pCommand, bool bCallBackupCallback); inline void(*v_Cmd_Dispatch)(ECommandTarget_t eTarget, const ConCommandBase* pCmdBase, const CCommand* pCommand, bool bCallBackupCallback);
inline CMemory p_Cmd_ForwardToServer;
inline bool(*v_Cmd_ForwardToServer)(const CCommand* pCommand); inline bool(*v_Cmd_ForwardToServer)(const CCommand* pCommand);
extern CCommandBuffer** s_pCommandBuffer;
extern LPCRITICAL_SECTION s_pCommandBufferMutex;
extern CUtlVector<int>* g_pExecutionMarkers;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VCmd : public IDetour class VCmd : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("Cbuf_AddText", p_Cbuf_AddText.GetPtr()); LogFunAdr("Cbuf_AddText", Cbuf_AddText);
LogFunAdr("Cbuf_Execute", p_Cbuf_Execute.GetPtr()); LogFunAdr("Cbuf_AddExecutionMarker", Cbuf_AddExecutionMarker);
LogFunAdr("Cmd_Dispatch", p_Cmd_Dispatch.GetPtr()); LogFunAdr("Cbuf_Execute", Cbuf_Execute);
LogFunAdr("Cmd_ForwardToServer", p_Cmd_ForwardToServer.GetPtr()); LogFunAdr("Cmd_Dispatch", v_Cmd_Dispatch);
LogFunAdr("Cmd_ForwardToServer", v_Cmd_ForwardToServer);
LogVarAdr("s_CommandBuffer", s_pCommandBuffer);
LogVarAdr("s_CommandBufferMutex", s_pCommandBufferMutex);
LogVarAdr("g_ExecutionMarkers", g_pExecutionMarkers);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_Cbuf_AddText = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 63 D9 41 8B F8 48 8D 0D ?? ?? ?? ?? 48 8B F2 FF 15 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 41 B9 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 63 D9 41 8B F8 48 8D 0D ?? ?? ?? ?? 48 8B F2 FF 15 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 41 B9 ?? ?? ?? ??").GetPtr(Cbuf_AddText);
p_Cbuf_Execute = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 FF 15 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 44 8B 05 ?? ?? ?? ??").GetPtr(Cbuf_AddExecutionMarker);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 FF 15 ?? ?? ?? ??").GetPtr(Cbuf_Execute);
p_Cmd_Dispatch = g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 8B ?? 0C 49 FF C7").FollowNearCallSelf(); g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 8B ?? 0C 49 FF C7").FollowNearCallSelf().GetPtr(v_Cmd_Dispatch);
p_Cmd_ForwardToServer = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 44 8B 59 04"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 44 8B 59 04").GetPtr(v_Cmd_ForwardToServer);
}
Cbuf_AddText = p_Cbuf_AddText.RCast<void (*)(ECommandTarget_t, const char*, cmd_source_t)>(); /*48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 63 D9 41 8B F8 48 8D 0D ?? ?? ?? ?? 48 8B F2 FF 15 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 41 B9 ?? ?? ?? ??*/ virtual void GetVar(void) const
Cbuf_Execute = p_Cbuf_Execute.RCast<void (*)(void)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 FF 15 ?? ?? ?? ??*/ {
v_Cmd_Dispatch = p_Cmd_Dispatch.RCast<void (*)(ECommandTarget_t, const ConCommandBase*, const CCommand*, bool)>(); s_pCommandBuffer = CMemory(Cbuf_AddText).FindPattern("48 8D 05").ResolveRelativeAddressSelf(3, 7).RCast<CCommandBuffer**>();
v_Cmd_ForwardToServer = p_Cmd_ForwardToServer.RCast<bool (*)(const CCommand*)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 44 8B 59 04*/ s_pCommandBufferMutex = CMemory(Cbuf_AddText).FindPattern("48 8D 0D").ResolveRelativeAddressSelf(3, 7).RCast<LPCRITICAL_SECTION>();
g_pExecutionMarkers = CMemory(Cbuf_AddExecutionMarker).FindPattern("48 8B 0D").ResolveRelativeAddressSelf(3, 7).RCast<CUtlVector<int>*>();
} }
virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
#endif // CMD_H #endif // CMD_H

View File

@ -8,37 +8,110 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "tier0/memstd.h" #include "tier0/memstd.h"
#include "tier0/jobthread.h" #include "tier0/jobthread.h"
#include "tier1/fmtstr.h"
#include "tier2/fileutils.h" #include "tier2/fileutils.h"
#include "engine/sys_dll2.h" #include "engine/sys_dll2.h"
#include "engine/host_cmd.h" #include "engine/host_cmd.h"
#include "engine/cmodel_bsp.h" #include "engine/cmodel_bsp.h"
#include "rtech/rtech_utils.h"
#include "rtech/rtech_game.h" #include "rtech/pak/pakstate.h"
#include "vpc/keyvalues.h" #include "rtech/pak/pakparse.h"
#include "rtech/pak/paktools.h"
#include "rtech/pak/pakstream.h"
#include "tier1/keyvalues.h"
#include "datacache/mdlcache.h" #include "datacache/mdlcache.h"
#include "filesystem/filesystem.h" #include "filesystem/filesystem.h"
#ifndef DEDICATED #ifndef DEDICATED
#include "client/clientstate.h" #include "client/clientstate.h"
#endif // !DEDICATED #endif // !DEDICATED
vector<string> g_InstalledMaps; CUtlVector<CUtlString> g_InstalledMaps;
string s_LevelName; CFmtStrN<MAX_MAP_NAME> s_CurrentLevelName;
std::regex s_ArchiveRegex{ R"([^_]*_(.*)(.bsp.pak000_dir).*)" }; static std::regex s_ArchiveRegex{ R"([^_]*_(.*)(.bsp.pak000_dir).*)" };
bool s_bLevelResourceInitialized = false; static CustomPakData_t s_customPakData;
bool s_bBasePaksInitialized = false; static KeyValues* s_pLevelSetKV = nullptr;
KeyValues* s_pLevelSetKV = nullptr;
//-----------------------------------------------------------------------------
// Purpose: load a custom pak and add it to the list
//-----------------------------------------------------------------------------
PakHandle_t CustomPakData_t::LoadAndAddPak(const char* const pakFile)
{
if (numHandles >= MAX_CUSTOM_PAKS)
{
Error(eDLL_T::ENGINE, NO_ERROR, "Tried to load pak '%s', but already reached the SDK's limit of %d!\n", pakFile, MAX_CUSTOM_PAKS);
return INVALID_PAK_HANDLE;
}
const PakHandle_t pakId = g_pakLoadApi->LoadAsync(pakFile, AlignedMemAlloc(), 4, 0);
// failure, don't add and return the invalid handle.
if (pakId == INVALID_PAK_HANDLE)
return pakId;
handles[numHandles++] = pakId;
return pakId;
}
//-----------------------------------------------------------------------------
// Purpose: unloads all active custom pak handles
//-----------------------------------------------------------------------------
void CustomPakData_t::UnloadAndRemoveAll()
{
for (; numHandles-1 >= CustomPakData_t::PAK_TYPE_COUNT; numHandles--)
{
const PakHandle_t pakId = handles[numHandles-1];
if (pakId == INVALID_PAK_HANDLE)
{
assert(0); // invalid handles should not be inserted
return;
}
g_pakLoadApi->UnloadAsync(pakId);
handles[numHandles-1] = INVALID_PAK_HANDLE;
}
}
//-----------------------------------------------------------------------------
// Purpose: loads the base SDK pak file by type
//-----------------------------------------------------------------------------
PakHandle_t CustomPakData_t::LoadBasePak(const char* const pakFile, const EPakType type)
{
const PakHandle_t pakId = g_pakLoadApi->LoadAsync(pakFile, AlignedMemAlloc(), 4, 0);
// the file is most likely missing
assert(pakId != INVALID_PAK_HANDLE);
handles[type] = pakId;
return pakId;
}
//-----------------------------------------------------------------------------
// Purpose: unload the SDK base pak file by type
//-----------------------------------------------------------------------------
void CustomPakData_t::UnloadBasePak(const EPakType type)
{
const PakHandle_t pakId = handles[type];
// only unload if it was actually successfully loaded
if (pakId != INVALID_PAK_HANDLE)
{
g_pakLoadApi->UnloadAsync(pakId);
handles[type] = INVALID_PAK_HANDLE;
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: checks if level has changed // Purpose: checks if level has changed
// Input : *pszLevelName - // Input : *pszLevelName -
// Output : true if level name deviates from previous level // Output : true if level name deviates from previous level
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool Mod_LevelHasChanged(const char* pszLevelName) bool Mod_LevelHasChanged(const char* const pszLevelName)
{ {
return (s_LevelName.compare(pszLevelName) != 0); return (V_strcmp(pszLevelName, s_CurrentLevelName.String()) != NULL);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -52,7 +125,7 @@ void Mod_GetAllInstalledMaps()
std::cmatch regexMatches; std::cmatch regexMatches;
std::lock_guard<std::mutex> l(g_InstalledMapsMutex); std::lock_guard<std::mutex> l(g_InstalledMapsMutex);
g_InstalledMaps.clear(); // Clear current list. g_InstalledMaps.Purge(); // Clear current list.
FOR_EACH_VEC(fileList, i) FOR_EACH_VEC(fileList, i)
{ {
@ -67,326 +140,299 @@ void Mod_GetAllInstalledMaps()
if (!regexMatches.empty()) if (!regexMatches.empty())
{ {
if (regexMatches[1].str().compare("frontend") == 0) const std::sub_match<const char*>& match = regexMatches[1];
if (match.compare("frontend") == 0)
continue; // Frontend contains no BSP's. continue; // Frontend contains no BSP's.
else if (regexMatches[1].str().compare("mp_common") == 0) else if (match.compare("mp_common") == 0)
{ {
if (std::find(g_InstalledMaps.begin(), g_InstalledMaps.end(), "mp_lobby") == g_InstalledMaps.end()) if (!g_InstalledMaps.HasElement("mp_lobby"))
g_InstalledMaps.push_back("mp_lobby"); g_InstalledMaps.AddToTail("mp_lobby");
continue; // Common contains mp_lobby. continue; // Common contains mp_lobby.
} }
else
if (std::find(g_InstalledMaps.begin(), g_InstalledMaps.end(), regexMatches[1].str()) == g_InstalledMaps.end())
g_InstalledMaps.push_back(regexMatches[1].str());
}
}
}
//-----------------------------------------------------------------------------
// Purpose: gets the queued pak handles
// Input : *a1 -
// *a2 -
// a3 -
// Output : __int64
//-----------------------------------------------------------------------------
__int64 __fastcall Mod_GetQueuedPakHandle(char* a1, char* a2, __int64 a3)
{
char v3; // al
signed int v4; // er11
__int64 v5; // r10
char* v6; // r9
signed __int64 v7; // rdx
char v8; // al
char* v10; // r8
char* v11; // r8
v3 = *a2;
v4 = 0;
*a1 = *a2;
v5 = 0i64;
if (v3)
{
v6 = a1;
v7 = a2 - a1;
while (1)
{
++v5;
++v6;
if (v5 == a3)
break;
v8 = v6[v7];
*v6 = v8;
if (!v8)
return v5;
}
*(v6 - 1) = 0;
if (--v5)
{
v10 = &a1[v5 - 1];
if ((*v10 & 0xC0) == 0x80)
{ {
do const string mapName = match.str();
++v4; if (!g_InstalledMaps.HasElement(mapName.c_str()))
while ((v10[-v4] & 0xC0) == 0x80); g_InstalledMaps.AddToTail(mapName.c_str());
}
v11 = &v10[-v4];
if (v4 != (signed int)((0xE5000000 >> (((unsigned __int8)*v11 >> 3) & 0x1E)) & 3))
{
*v11 = 0;
v5 -= v4;
} }
} }
} }
return v5;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: processes queued pak files // Purpose: processes queued pak files
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Mod_ProcessPakQueue() void Mod_QueuedPakCacheFrame()
{ {
char v0; // bl
char** v1; // r10
__int64 i; // er9
char* v3; // rcx
signed __int64 v4; // r8
int v5; // eax
int v6; // edx
__int64 v7; // eax
__int64 v8; // rbp
__int64 v9; // rsi
char* v10; // rbx
unsigned int v11; // ecx
__int64 v12; // rax
int v13; // edi
char v14; // al
char* v15; // rbx
__int64 v16; // edi
char* v17; // rsi
char* v18; // rax
int v19; // ecx
int v20; // er8
int v21; // ecx
__int64 v22; // rdx
__int64 v24{}; // rdx
__int64 v25{}; // rcx
v0 = 0;
#ifndef DEDICATED #ifndef DEDICATED
bool bUnconnected = !(*g_pClientState_Shifted)->IsConnected(); bool bUnconnected = !(*g_pClientState_Shifted)->IsConnected();
#else // !DEDICATED #else // !DEDICATED
bool bUnconnected = true; // Always true for dedicated. bool bUnconnected = true; // Always true for dedicated.
#endif #endif
if (*(float*)&*dword_14B383420 == 1.0 && *qword_167ED7BB8 && bUnconnected) bool startFromFirst = false;
if (Pak_StreamingDownloadFinished() && Pak_GetNumStreamableAssets() && bUnconnected)
{ {
*byte_16709DDDF = 0; *g_pPakPrecacheJobFinished = false;
v0 = 1; startFromFirst = true;
} }
else if (*byte_16709DDDF) else if (*g_pPakPrecacheJobFinished)
{ {
return; return;
} }
if (FileSystem()->ResetItemCache() && !*dword_1634F445C)
if (!FileSystem()->ResetItemCache() || *g_pNumPrecacheItemsMTVTF)
{ {
v1 = &*off_141874660; return;
for (i = 0; i < 5; ++i) }
const char** pPakName = &g_commonPakData[0].basePakName;
int i;
for (i = 0; i < 5; ++i)
{
if (*((_BYTE*)pPakName - 268))
break;
const char* pakName = g_commonPakData[i].pakName;
const int64_t v4 = *pPakName - pakName;
int v5;
int v6;
do
{ {
if (*((_BYTE*)v1 - 268)) v5 = (unsigned __int8)pakName[v4];
break; v6 = (unsigned __int8)*pakName - v5;
v3 = (char*)&*unk_141874555 + 280 * i;
v4 = *v1 - v3;
do
{
v5 = (unsigned __int8)v3[v4];
v6 = (unsigned __int8)*v3 - v5;
if (v6)
break;
++v3;
} while (v5);
if (v6) if (v6)
break; break;
v1 += 35;
}
v7 = 0;
if (!v0)
v7 = i;
v8 = v7;
if (v7 <= 4i64)
{
v9 = 4i64;
v10 = (char*)&*unk_1418749B0;
do
{
if (v10[5])
{
v11 = *(_DWORD*)v10;
v12 = *(_DWORD*)v10 & 0x1FF;
v10[4] = 1;
if (*((_DWORD*)&*g_pLoadedPakInfo + 46 * v12) == v11)
{
v13 = *((_DWORD*)&*g_pLoadedPakInfo + 46 * v12 + 1);
v14 = v10[4];
}
else
{
v13 = 14;
v14 = 1;
}
if (!v14 || v13 == 9)
{
// SDK pak files must be unloaded before the engine pak files,
// as we reference assets within engine pak files.
const RPakLoadedInfo_t* pLoadedPakInfo = g_pRTech->GetPakLoadedInfo(*(RPakHandle_t*)v10);
if (pLoadedPakInfo)
{
const char* pszLoadedPakName = pLoadedPakInfo->m_pszFileName;
if (strcmp(pszLoadedPakName, "common_mp.rpak") == 0 || ++pakName;
strcmp(pszLoadedPakName, "common_sp.rpak") == 0 || } while (v5);
strcmp(pszLoadedPakName, "common_pve.rpak") == 0)
{
const RPakLoadedInfo_t* pLoadedSdkPak = g_pRTech->GetPakLoadedInfo("common_sdk.rpak");
if (pLoadedSdkPak) // Only unload if sdk pak file is loaded. if (v6)
g_pakLoadApi->UnloadPak(pLoadedSdkPak->m_nHandle); break;
} pPakName += 35;
#ifndef DEDICATED
else if (strcmp(pszLoadedPakName, "ui_mp.rpak") == 0)
{
const RPakLoadedInfo_t* pLoadedSdkPak = g_pRTech->GetPakLoadedInfo("ui_sdk.rpak");
if (pLoadedSdkPak) // Only unload if sdk pak file is loaded.
g_pakLoadApi->UnloadPak(pLoadedSdkPak->m_nHandle);
}
#endif // !DEDICATED
}
// The old gather props is set if a model couldn't be
// loaded properly. If we unload level assets, we just
// enable the new implementation again and re-evaluate
// on the next level load. If we load a missing/bad
// model again, we toggle the old implementation as
// the helper functions for this implementation have
// been restored in the SDK, and modified to support
// stubbing missing model assets. See the function
// 'CMDLCache::GetErrorModel' for more information.
if (old_gather_props->GetBool())
old_gather_props->SetValue(false);
g_pakLoadApi->UnloadPak(*(RPakHandle_t*)v10);
Mod_UnloadPakFile(); // Unload mod pak files.
if (s_pLevelSetKV)
{
// Delete current level settings if we drop all paks..
s_pLevelSetKV->DeleteThis();
s_pLevelSetKV = nullptr;
}
}
if (v13 && (unsigned int)(v13 - 13) > 1)
return;
*((_WORD*)v10 + 2) = 0;
*(_DWORD*)v10 = 0xFFFFFFFF;
}
--v9;
v10 -= 280;
} while (v9 >= v8);
}
*byte_16709DDDF = 1;
v15 = (char*)&*unk_141874550;
v16 = 0;
while (1)
{
v17 = (char*)&*unk_141874550 + 280 * v16 + 5;
v18 = v17;
do
{
v19 = (unsigned __int8)v18[*((_QWORD*)v15 + 34) - (_QWORD)v17];
v20 = (unsigned __int8)*v18 - v19;
if (v20)
break;
++v18;
} while (v19);
if (!v20)
goto LABEL_37;
Mod_GetQueuedPakHandle(v17, *((char**)v15 + 34), 260i64);
if (v15[5])
break;
*(_DWORD*)v15 = 0xFFFFFFFF;
LABEL_40:
++v16;
v15 += 280;
if (v16 >= 5)
{
if (*byte_16709DDDF)
{
if (*g_pMTVFTaskItem)
{
if (!*(_BYTE*)(*g_pMTVFTaskItem + 4))
{
if (*qword_167ED7BC0 || WORD2(*g_pPakLoadJobID) != HIWORD(*g_pPakLoadJobID))
{
if (!JT_AcquireFifoLock(g_pPakFifoLock)
&& !(unsigned __int8)sub_14045BAC0((__int64(__fastcall*)(__int64, _DWORD*, __int64, _QWORD*))g_pPakFifoLockWrapper, g_pPakFifoLock, -1i64, 0i64))
{
sub_14045A1D0((unsigned __int8(__fastcall*)(_QWORD))g_pPakFifoLockWrapper, g_pPakFifoLock, -1i64, 0i64, 0i64, 1);
}
sub_140441220(v25, v24);
if (ThreadInMainThread())
{
if (*g_bPakFifoLockAcquired)
{
*g_bPakFifoLockAcquired = 0;
JT_ReleaseFifoLock(g_pPakFifoLock);
}
}
JT_ReleaseFifoLock(g_pPakFifoLock);
}
FileSystem()->ResetItemCacheSize(256);
FileSystem()->PrecacheTaskItem(*g_pMTVFTaskItem);
}
}
}
return;
}
}
if (strcmp(v17, "mp_lobby.rpak") == 0)
s_bBasePaksInitialized = true;
if (s_bBasePaksInitialized && !s_bLevelResourceInitialized)
{
Mod_PreloadLevelPaks(s_LevelName.c_str());
s_bLevelResourceInitialized = true;
}
*(_DWORD*)v15 = g_pakLoadApi->LoadAsync(v17, AlignedMemAlloc(), 4, 0);
if (strcmp(v17, "common_mp.rpak") == 0 || strcmp(v17, "common_sp.rpak") == 0 || strcmp(v17, "common_pve.rpak") == 0)
g_pakLoadApi->LoadAsync("common_sdk.rpak", AlignedMemAlloc(), 4, 0);
#ifndef DEDICATED
if (strcmp(v17, "ui_mp.rpak") == 0)
g_pakLoadApi->LoadAsync("ui_sdk.rpak", AlignedMemAlloc(), 4, 0);
#endif // !DEDICATED
LABEL_37:
v21 = *(_DWORD*)v15;
if (*(_DWORD*)v15 != INVALID_PAK_HANDLE)
{
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2)
v22 = 232i64 * (v21 & 0x1FF);
#else
v22 = 184i64 * (v21 & 0x1FF);
#endif
if (*(_DWORD*)((char*)&*g_pLoadedPakInfo + v22) != _DWORD(v21) || ((*(_DWORD*)((char*)&*g_pLoadedPakInfo + v22 + 4) - 9) & 0xFFFFFFFB) != 0)
{
*byte_16709DDDF = 0; return;
}
}
goto LABEL_40;
} }
int startIndex = 0;
if (!startFromFirst)
startIndex = i; // start from last pre-cached
const int numToProcess = startIndex;
if (startIndex <= 4)
{
int numLeftToProcess = 4;
CommonPakData_t* data = &g_commonPakData[4];
do
{
if (*data->pakName)
{
PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(data->pakId);
EPakStatus status;
// TODO: revisit this, this appears incorrect but also the way
// respawn does this. it this always supposed to be true on
// retail builds?
bool keepLoaded = true;
data->keepLoaded = true;
if (pakInfo->handle == data->pakId)
{
status = pakInfo->status;
keepLoaded = data->keepLoaded;
}
else
{
status = PAK_STATUS_INVALID_PAKHANDLE;
keepLoaded = true;
}
if (!keepLoaded || status == PAK_STATUS_LOADED)
{
// SDK pak files must be unloaded before the engine pak files,
// as we use assets within engine pak files.
switch (numLeftToProcess)
{
#ifndef DEDICATED
case CommonPakData_t::PAK_TYPE_UI_GM:
s_customPakData.UnloadBasePak(CustomPakData_t::PAK_TYPE_UI_SDK);
break;
#endif // !DEDICATED
case CommonPakData_t::PAK_TYPE_COMMON:
g_StudioMdlFallbackHandler.Clear();
break;
case CommonPakData_t::PAK_TYPE_COMMON_GM:
s_customPakData.UnloadBasePak(CustomPakData_t::PAK_TYPE_COMMON_SDK);
break;
case CommonPakData_t::PAK_TYPE_LOBBY:
s_customPakData.basePaksLoaded = false;
break;
default:
break;
}
// The old gather props is set if a model couldn't be
// loaded properly. If we unload level assets, we just
// enable the new implementation again and re-evaluate
// on the next level load. If we load a missing/bad
// model again, we toggle the old implementation as
// otherwise the fallback models won't render; the new
// gather props solution does not attempt to obtain
// studio hardware data on bad mdl handles. See
// 'GatherStaticPropsSecondPass_PreInit()' for details.
g_StudioMdlFallbackHandler.DisableLegacyGatherProps();
g_pakLoadApi->UnloadAsync(data->pakId);
Mod_UnloadPakFile(); // Unload mod pak files.
if (s_pLevelSetKV)
{
// Delete current level settings if we drop all paks..
s_pLevelSetKV->DeleteThis();
s_pLevelSetKV = nullptr;
}
}
if (status && (unsigned int)(status - 13) > 1)
return;
data->keepLoaded = false;
data->pakName[0] = '\0';
data->pakId = INVALID_PAK_HANDLE;
}
--numLeftToProcess;
--data;
} while (numLeftToProcess >= numToProcess);
}
*g_pPakPrecacheJobFinished = true;
CommonPakData_t* commonData = g_commonPakData;
int it = 0;
char* name;
char* nameIt;
while (true)
{
name = g_commonPakData[it].pakName;
nameIt = name;
char c;
int v20;
do
{
c = (unsigned __int8)nameIt[(unsigned __int64)(commonData->basePakName - (const char*)name)];
v20 = (unsigned __int8)*nameIt - c;
if (v20)
break;
++nameIt;
} while (c);
if (!v20)
goto CHECK_FOR_FAILURE;
V_strncpy(name, commonData->basePakName, MAX_PATH);
if (*commonData->pakName)
break;
commonData->pakId = INVALID_PAK_HANDLE;
LOOP_AGAIN_OR_FINISH:
++it;
++commonData;
if (it >= 5)
{
if (*g_pPakPrecacheJobFinished)
{
__int64 pMTVFTaskItem = *g_pMTVFTaskItem;
if (pMTVFTaskItem)
{
if (!*(_BYTE*)(pMTVFTaskItem + 4))
{
JobFifoLock_s* const pakFifoLock = &g_pakGlobals->fifoLock;
if (g_pakGlobals->hasPendingUnloadJobs || g_pakGlobals->loadedPakCount != g_pakGlobals->requestedPakCount)
{
if (!JT_AcquireFifoLockOrHelp(pakFifoLock)
&& !JT_HelpWithJobTypes(g_pPakFifoLockWrapper, pakFifoLock, -1i64, 0i64))
{
JT_HelpWithJobTypesOrSleep(g_pPakFifoLockWrapper, pakFifoLock, -1i64, 0i64, 0i64, 1);
}
Mod_UnloadPendingAndPrecacheRequestedPaks();
if (ThreadInMainThread())
{
if (*g_bPakFifoLockAcquired)
{
*g_bPakFifoLockAcquired = 0;
JT_ReleaseFifoLock(pakFifoLock);
}
}
JT_ReleaseFifoLock(pakFifoLock);
pMTVFTaskItem = *g_pMTVFTaskItem;
}
FileSystem()->ResetItemCacheSize(256);
FileSystem()->PrecacheTaskItem(pMTVFTaskItem);
}
}
}
return;
}
}
if (it == CommonPakData_t::PAK_TYPE_LOBBY)
s_customPakData.basePaksLoaded = true;
if (s_customPakData.basePaksLoaded && !s_customPakData.levelResourcesLoaded)
{
Mod_PreloadLevelPaks(s_CurrentLevelName.String());
s_customPakData.levelResourcesLoaded = true;
}
commonData->pakId = g_pakLoadApi->LoadAsync(name, AlignedMemAlloc(), 4, 0);
#ifndef DEDICATED
if (it == CommonPakData_t::PAK_TYPE_UI_GM)
s_customPakData.LoadBasePak("ui_sdk.rpak", CustomPakData_t::PAK_TYPE_UI_SDK);
#endif // !DEDICATED
if (it == CommonPakData_t::PAK_TYPE_COMMON_GM)
s_customPakData.LoadBasePak("common_sdk.rpak", CustomPakData_t::PAK_TYPE_COMMON_SDK);
CHECK_FOR_FAILURE:
if (commonData->pakId != INVALID_PAK_HANDLE)
{
const PakLoadedInfo_t* const pli = Pak_GetPakInfo(commonData->pakId);
if (pli->handle != commonData->pakId || ((pli->status - 9) & 0xFFFFFFFB) != 0)
{
*g_pPakPrecacheJobFinished = false;
return;
}
}
goto LOOP_AGAIN_OR_FINISH;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -394,12 +440,12 @@ void Mod_ProcessPakQueue()
// Input : *szLevelName - // Input : *szLevelName -
// Output : true on success, false on failure // Output : true on success, false on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Mod_LoadPakForMap(const char* pszLevelName) void Mod_LoadPakForMap(const char* const pszLevelName)
{ {
if (Mod_LevelHasChanged(pszLevelName)) if (Mod_LevelHasChanged(pszLevelName))
s_bLevelResourceInitialized = false; s_customPakData.levelResourcesLoaded = false;
s_LevelName = pszLevelName; s_CurrentLevelName = pszLevelName;
// Dedicated should not load loadscreens. // Dedicated should not load loadscreens.
#ifndef DEDICATED #ifndef DEDICATED
@ -412,11 +458,12 @@ void Mod_LoadPakForMap(const char* pszLevelName)
// Input : *pszLevelName - // Input : *pszLevelName -
// Output : KeyValues* // Output : KeyValues*
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
KeyValues* Mod_GetLevelSettings(const char* pszLevelName) KeyValues* Mod_GetLevelSettings(const char* const pszLevelName)
{ {
if (s_pLevelSetKV) if (s_pLevelSetKV)
{ {
if (s_bLevelResourceInitialized) // If we didn't change the level, return the current one
if (s_customPakData.levelResourcesLoaded)
return s_pLevelSetKV; return s_pLevelSetKV;
s_pLevelSetKV->DeleteThis(); s_pLevelSetKV->DeleteThis();
@ -433,14 +480,14 @@ KeyValues* Mod_GetLevelSettings(const char* pszLevelName)
// Purpose: loads required pakfile assets for specified BSP level // Purpose: loads required pakfile assets for specified BSP level
// Input : &svSetFile - // Input : &svSetFile -
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Mod_PreloadLevelPaks(const char* pszLevelName) void Mod_PreloadLevelPaks(const char* const pszLevelName)
{ {
KeyValues* pSettingsKV = Mod_GetLevelSettings(pszLevelName); KeyValues* const pSettingsKV = Mod_GetLevelSettings(pszLevelName);
if (!pSettingsKV) if (!pSettingsKV)
return; return;
KeyValues* pPakListKV = pSettingsKV->FindKey("PakList"); KeyValues* const pPakListKV = pSettingsKV->FindKey("PakList");
if (!pPakListKV) if (!pPakListKV)
return; return;
@ -453,12 +500,10 @@ void Mod_PreloadLevelPaks(const char* pszLevelName)
continue; continue;
snprintf(szPathBuffer, sizeof(szPathBuffer), "%s.rpak", pSubKey->GetName()); snprintf(szPathBuffer, sizeof(szPathBuffer), "%s.rpak", pSubKey->GetName());
RPakHandle_t nPakId = g_pakLoadApi->LoadAsync(szPathBuffer, AlignedMemAlloc(), 4, 0); const PakHandle_t nPakId = s_customPakData.LoadAndAddPak(szPathBuffer);
if (nPakId == INVALID_PAK_HANDLE) if (nPakId == INVALID_PAK_HANDLE)
Error(eDLL_T::ENGINE, NO_ERROR, "%s: unable to load pak '%s' results '%d'\n", __FUNCTION__, szPathBuffer, nPakId); Error(eDLL_T::ENGINE, NO_ERROR, "%s: unable to load pak '%s' results '%d'\n", __FUNCTION__, szPathBuffer, nPakId);
else
g_vLoadedPakHandle.AddToTail(nPakId);
} }
} }
@ -467,25 +512,14 @@ void Mod_PreloadLevelPaks(const char* pszLevelName)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Mod_UnloadPakFile(void) void Mod_UnloadPakFile(void)
{ {
for (const RPakHandle_t& it : g_vLoadedPakHandle) s_customPakData.UnloadAndRemoveAll();
{
if (it >= 0) g_StudioMdlFallbackHandler.ClearBadModelHandleCache();
{ g_StudioMdlFallbackHandler.ClearSuppresionList();
g_pakLoadApi->UnloadPak(it);
}
}
g_vLoadedPakHandle.Purge();
g_vBadMDLHandles.clear();
} }
void VModel_BSP::Attach() const void VModel_BSP::Detour(const bool bAttach) const
{ {
DetourAttach((LPVOID*)&v_Mod_LoadPakForMap, &Mod_LoadPakForMap); DetourSetup(&v_Mod_LoadPakForMap, &Mod_LoadPakForMap, bAttach);
DetourAttach((LPVOID*)&v_Mod_ProcessPakQueue, &Mod_ProcessPakQueue); DetourSetup(&v_Mod_QueuedPakCacheFrame, &Mod_QueuedPakCacheFrame, bAttach);
} }
void VModel_BSP::Detach() const
{
DetourDetach((LPVOID*)&v_Mod_LoadPakForMap, &Mod_LoadPakForMap);
DetourDetach((LPVOID*)&v_Mod_ProcessPakQueue, &Mod_ProcessPakQueue);
}

View File

@ -1,33 +1,135 @@
#pragma once #pragma once
#include "tier0/jobthread.h" #include "tier0/jobthread.h"
#include "rtech/ipakfile.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Forward declarations // Forward declarations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class KeyValues; class KeyValues;
inline CMemory p_Mod_LoadPakForMap; //-----------------------------------------------------------------------------
// this structure contains handles and names to the base pak files the engine
// loads for a level, this is used for load/unload management during level
// changes or engine shutdown
//-----------------------------------------------------------------------------
struct CommonPakData_t
{
enum EPakType
{
// the UI pak assigned to the current gamemode (range in GameMode_t)
PAK_TYPE_UI_GM = 0,
PAK_TYPE_COMMON,
// the base pak assigned to the current gamemode (range in GameMode_t)
PAK_TYPE_COMMON_GM,
PAK_TYPE_LOBBY,
// NOTE: this one is assigned to the name of the level, the prior ones are
// all static!
PAK_TYPE_LEVEL,
// the total number of pak files to watch and manage
PAK_TYPE_COUNT
};
CommonPakData_t()
{
Reset();
}
void Reset()
{
pakId = INVALID_PAK_HANDLE;
keepLoaded = false;
basePakName = nullptr;
memset(pakName, '\0', sizeof(pakName));
}
PakHandle_t pakId;
bool keepLoaded;
// the pak name that's being requested to be loaded for this particular slot
char pakName[MAX_PATH];
// the actual base pak name, like "common_pve.rpak" as set when this array is
// being initialized
const char* basePakName;
};
//-----------------------------------------------------------------------------
// this structure contains handles and names to the custom pak files that are
// loaded with the settings KV for that level, these paks are loaded after the
// common paks are loaded, but unloaded before the common paks are unloaded
//-----------------------------------------------------------------------------
struct CustomPakData_t
{
enum EPakType
{
// the pak that loads after CommonPakData_t::PAK_TYPE_UI_GM has loaded, and
// unloads before CommonPakData_t::PAK_TYPE_UI_GM gets unloaded
PAK_TYPE_UI_SDK = 0,
// the pak that loads after CommonPakData_t::PAK_TYPE_COMMON_GM has loaded,
// and unloads before CommonPakData_t::PAK_TYPE_COMMON_GM gets unloaded
PAK_TYPE_COMMON_SDK,
// the total number of base SDK pak files
PAK_TYPE_COUNT
};
enum
{
// the absolute max number of custom paks, note that the engine's limit
// could still be reached before this number as game scripts and other
// code still loads paks such as gladiator cards or load screens
MAX_CUSTOM_PAKS = (PAK_MAX_HANDLES - CommonPakData_t::PAK_TYPE_COUNT)
};
CustomPakData_t()
{
for (size_t i = 0; i < V_ARRAYSIZE(handles); i++)
{
handles[i] = INVALID_PAK_HANDLE;
}
// the first # handles are reserved for base SDK paks
numHandles = PAK_TYPE_COUNT;
levelResourcesLoaded = false;
basePaksLoaded = false;
}
PakHandle_t LoadAndAddPak(const char* const pakFile);
void UnloadAndRemoveAll();
PakHandle_t LoadBasePak(const char* const pakFile, const EPakType type);
void UnloadBasePak(const EPakType type);
// Pak handles that have been loaded with the level
// from within the level settings KV (located in
// scripts/levels/settings/*.kv). On level unload,
// each pak listed in this vector gets unloaded.
PakHandle_t handles[MAX_CUSTOM_PAKS];
size_t numHandles;
bool levelResourcesLoaded;
bool basePaksLoaded;
};
// array size = CommonPakData_t::PAK_TYPE_COUNT
inline CommonPakData_t* g_commonPakData;
inline void(*v_Mod_LoadPakForMap)(const char* szLevelName); inline void(*v_Mod_LoadPakForMap)(const char* szLevelName);
inline void(*v_Mod_QueuedPakCacheFrame)(void);
inline CMemory p_Mod_ProcessPakQueue; inline int32_t * g_pNumPrecacheItemsMTVTF;
inline void(*v_Mod_ProcessPakQueue)(void); inline bool* g_pPakPrecacheJobFinished;
inline float* dword_14B383420; inline void(*Mod_UnloadPendingAndPrecacheRequestedPaks)(void);
inline int32_t * dword_1634F445C;
inline void** qword_167ED7BB8;
inline bool* byte_16709DDDF;
inline char** off_141874660;
inline void** unk_141874555;
inline void** unk_1418749B0;
inline void** unk_141874550;
inline int64_t* qword_167ED7BC0;
inline __int64(*sub_14045BAC0)(__int64(__fastcall* a1)(__int64, _DWORD*, __int64, _QWORD*), JobFifoLock_s* pFifoLock, __int64 a3, __int64 a4); extern CUtlVector<CUtlString> g_InstalledMaps;
inline __int64(*sub_14045A1D0)(unsigned __int8(__fastcall* a1)(_QWORD), JobFifoLock_s* pFifoLock, __int64 a3, __int64 a4, volatile signed __int64* a5, char a6); extern std::mutex g_InstalledMapsMutex;
inline void(*sub_140441220)(__int64 a1, __int64 a2);
extern bool s_bBasePaksInitialized;
extern vector<string> g_InstalledMaps;
bool Mod_LevelHasChanged(const char* pszLevelName); bool Mod_LevelHasChanged(const char* pszLevelName);
void Mod_GetAllInstalledMaps(); void Mod_GetAllInstalledMaps();
@ -41,55 +143,30 @@ class VModel_BSP : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("Mod_LoadPakForMap", p_Mod_LoadPakForMap.GetPtr()); LogFunAdr("Mod_LoadPakForMap", v_Mod_LoadPakForMap);
LogFunAdr("Mod_ProcessPakQueue", p_Mod_ProcessPakQueue.GetPtr()); LogFunAdr("Mod_QueuedPakCacheFrame", v_Mod_QueuedPakCacheFrame);
LogFunAdr("sub_14045BAC0", reinterpret_cast<uintptr_t>(sub_14045BAC0));
LogFunAdr("sub_14045A1D0", reinterpret_cast<uintptr_t>(sub_14045A1D0)); LogFunAdr("Mod_UnloadPendingAndPrecacheRequestedPaks", Mod_UnloadPendingAndPrecacheRequestedPaks);
LogFunAdr("sub_140441220", reinterpret_cast<uintptr_t>(sub_140441220));
LogVarAdr("dword_14B383420", reinterpret_cast<uintptr_t>(dword_14B383420)); LogVarAdr("g_numPrecacheItemsMTVTF", g_pNumPrecacheItemsMTVTF);
LogVarAdr("dword_1634F445C", reinterpret_cast<uintptr_t>(dword_1634F445C)); LogVarAdr("g_pakPrecacheJobFinished", g_pPakPrecacheJobFinished);
LogVarAdr("qword_167ED7BB8", reinterpret_cast<uintptr_t>(qword_167ED7BB8));
LogVarAdr("byte_16709DDDF", reinterpret_cast<uintptr_t>(byte_16709DDDF)); LogVarAdr("g_commonPakData", g_commonPakData);
LogVarAdr("off_141874660", reinterpret_cast<uintptr_t>(off_141874660));
LogVarAdr("unk_141874555", reinterpret_cast<uintptr_t>(unk_141874555));
LogVarAdr("unk_1418749B0", reinterpret_cast<uintptr_t>(unk_1418749B0));
LogVarAdr("unk_141874550", reinterpret_cast<uintptr_t>(unk_141874550));
LogVarAdr("qword_167ED7BC0", reinterpret_cast<uintptr_t>(qword_167ED7BC0));
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ?? 4C 8D 05 ?? ?? ?? ?? 84 C0").GetPtr(v_Mod_LoadPakForMap);
p_Mod_LoadPakForMap = g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 4C 8B C1 48 8D 15 ?? ?? ?? ?? 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 4C 8D 0D ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("40 53 48 83 EC ?? F3 0F 10 05 ?? ?? ?? ?? 32 DB").GetPtr(v_Mod_QueuedPakCacheFrame);
v_Mod_LoadPakForMap = p_Mod_LoadPakForMap.RCast<void(*)(const char*)>(); /*48 81 EC ? ? ? ? 4C 8B C1 48 8D 15 ? ? ? ? 48 8D 4C 24 ? E8 ? ? ? ? 4C 8D 0D ? ? ? ?*/ g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 33 ED 48 8D 35 ?? ?? ?? ?? 48 39 2D ?? ?? ?? ??").GetPtr(Mod_UnloadPendingAndPrecacheRequestedPaks);
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_Mod_LoadPakForMap = g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ?? 4C 8D 05 ?? ?? ?? ?? 84 C0");
v_Mod_LoadPakForMap = p_Mod_LoadPakForMap.RCast<void(*)(const char*)>(); /*48 81 EC ? ? ? ? 0F B6 05 ? ? ? ? 4C 8D 05 ? ? ? ? 84 C0*/
#endif
p_Mod_ProcessPakQueue = g_GameDll.FindPatternSIMD("40 53 48 83 EC ?? F3 0F 10 05 ?? ?? ?? ?? 32 DB");
v_Mod_ProcessPakQueue = p_Mod_ProcessPakQueue.RCast<void(*)(void)>(); /*40 53 48 83 EC ?? F3 0F 10 05 ? ? ? ? 32 DB*/
sub_14045BAC0 = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 4C 89 4C 24 ?? 4C 89 44 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 60").RCast<__int64(*)(__int64(__fastcall* a1)(__int64, _DWORD*, __int64, _QWORD*), JobFifoLock_s* pFifoLock, __int64 a3, __int64 a4)>();
sub_14045A1D0 = g_GameDll.FindPatternSIMD("4C 89 4C 24 ?? 4C 89 44 24 ?? 48 89 54 24 ?? 48 89 4C 24 ?? 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ??").RCast<__int64(*)(unsigned __int8(__fastcall* a1)(_QWORD), JobFifoLock_s* pFifoLock, __int64 a3, __int64 a4, volatile signed __int64* a5, char a6)>();
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
sub_140441220 = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 83 EC 20 33 ED 48 39 2D ?? ?? ?? ??").RCast<void(*)(__int64 a1, __int64 a2)>();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
sub_140441220 = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 33 ED 48 8D 35 ?? ?? ?? ?? 48 39 2D ?? ?? ?? ??").RCast<void(*)(__int64 a1, __int64 a2)>();
#endif
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
dword_14B383420 = p_Mod_ProcessPakQueue.FindPattern("F3 0F 10").ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>(); g_pNumPrecacheItemsMTVTF = CMemory(v_Mod_QueuedPakCacheFrame).FindPattern("8B 05").ResolveRelativeAddressSelf(0x2, 0x6).RCast<int32_t*>();
dword_1634F445C = p_Mod_ProcessPakQueue.FindPattern("8B 05").ResolveRelativeAddressSelf(0x2, 0x6).RCast<int32_t*>(); g_pPakPrecacheJobFinished = CMemory(v_Mod_QueuedPakCacheFrame).Offset(0x20).FindPatternSelf("88 1D").ResolveRelativeAddressSelf(0x2, 0x6).RCast<bool*>();
qword_167ED7BB8 = p_Mod_ProcessPakQueue.Offset(0x10).FindPatternSelf("48 83").ResolveRelativeAddressSelf(0x3, 0x8).RCast<void**>();
byte_16709DDDF = p_Mod_ProcessPakQueue.Offset(0x20).FindPatternSelf("88 1D").ResolveRelativeAddressSelf(0x2, 0x6).RCast<bool*>(); CMemory(v_Mod_QueuedPakCacheFrame).Offset(0xA0).FindPatternSelf("48 8D 2D").ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(g_commonPakData);
off_141874660 = p_Mod_ProcessPakQueue.Offset(0x40).FindPatternSelf("4C 8D 15").ResolveRelativeAddressSelf(0x3, 0x7).RCast<char**>();
unk_141874555 = p_Mod_ProcessPakQueue.Offset(0x40).FindPatternSelf("4C 8D 1D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<void**>();
unk_1418749B0 = p_Mod_ProcessPakQueue.Offset(0xA0).FindPatternSelf("48 8D 1D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<void**>();
unk_141874550 = p_Mod_ProcessPakQueue.Offset(0x150).FindPatternSelf("48 8D 2D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<void**>();
qword_167ED7BC0 = p_Mod_ProcessPakQueue.Offset(0x200).FindPatternSelf("48 83 3D").ResolveRelativeAddressSelf(0x3, 0x8).RCast<int64_t*>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -6,6 +6,7 @@
#include <core/stdafx.h> #include <core/stdafx.h>
#include <tier1/strtools.h> #include <tier1/strtools.h>
#include <localize/localize.h>
#include <engine/common.h> #include <engine/common.h>
/* /*
@ -42,4 +43,54 @@ const char* COM_FormatSeconds(int seconds)
} }
return string; return string;
} }
/*
==============================
COM_ExplainDisconnection
==============================
*/
void COM_ExplainDisconnection(bool bPrint, const char* fmt, ...)
{
char szBuf[1024];
{/////////////////////////////
va_list vArgs;
va_start(vArgs, fmt);
vsnprintf(szBuf, sizeof(szBuf), fmt, vArgs);
szBuf[sizeof(szBuf) - 1] = '\0';
va_end(vArgs);
}/////////////////////////////
if (bPrint)
{
if (szBuf[0] == '#')
{
wchar_t formatStr[1024];
const wchar_t* wpchReason = (*g_ppVGuiLocalize) ? (*g_ppVGuiLocalize)->Find(szBuf) : nullptr;
if (wpchReason)
{
wcsncpy(formatStr, wpchReason, sizeof(formatStr) / sizeof(wchar_t));
char conStr[256];
(*g_ppVGuiLocalize)->ConvertUnicodeToANSI(formatStr, conStr, sizeof(conStr));
Error(eDLL_T::CLIENT, NO_ERROR, "%s\n", conStr);
}
else
Error(eDLL_T::CLIENT, NO_ERROR, "%s\n", szBuf);
}
else
{
Error(eDLL_T::CLIENT, NO_ERROR, "%s\n", szBuf);
}
}
v_COM_ExplainDisconnection(bPrint, szBuf);
}
void VCommon::Detour(const bool bAttach) const
{
DetourSetup(&v_COM_ExplainDisconnection, COM_ExplainDisconnection, bAttach);
}

View File

@ -1,32 +1,29 @@
#pragma once #pragma once
/* ==== COMMON ========================================================================================================================================================== */ /* ==== COMMON ========================================================================================================================================================== */
inline CMemory p_COM_InitFilesystem; inline void*(*v_COM_InitFilesystem)(const char* pFullModPath);
inline void*(*COM_InitFilesystem)(const char* pFullModPath); inline char* const(*v_COM_GetPrintMessageBuffer)(void);
inline void(*v_COM_ExplainDisconnection)(bool bPrint, const char* fmt, ...);
inline CMemory p_COM_ExplainDisconnection;
inline void*(*COM_ExplainDisconnection)(uint64_t level, const char* fmt, ...);
const char* COM_FormatSeconds(int seconds); const char* COM_FormatSeconds(int seconds);
void COM_ExplainDisconnection(bool bPrint, const char* fmt, ...);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VCommon : public IDetour class VCommon : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("COM_InitFilesystem", p_COM_InitFilesystem.GetPtr()); LogFunAdr("COM_InitFilesystem", v_COM_InitFilesystem);
LogFunAdr("COM_ExplainDisconnection", p_COM_ExplainDisconnection.GetPtr()); LogFunAdr("COM_GetPrintMessageBuffer", v_COM_GetPrintMessageBuffer);
LogFunAdr("COM_ExplainDisconnection", v_COM_ExplainDisconnection);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_COM_InitFilesystem = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 48 C7 44 24 ?? ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 48 C7 44 24 ?? ?? ?? ?? ??").GetPtr(v_COM_InitFilesystem);
p_COM_ExplainDisconnection = g_GameDll.FindPatternSIMD("48 8B C4 48 89 50 10 4C 89 40 18 4C 89 48 20 48 81 EC ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 8D 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 4C 89 44 24 ??").GetPtr(v_COM_GetPrintMessageBuffer);
g_GameDll.FindPatternSIMD("48 8B C4 48 89 50 10 4C 89 40 18 4C 89 48 20 48 81 EC ?? ?? ?? ??").GetPtr(v_COM_ExplainDisconnection);
COM_InitFilesystem = p_COM_InitFilesystem.RCast<void* (*)(const char*)>(); /*48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 48 C7 44 24 ?? ?? ?? ?? ??*/
COM_ExplainDisconnection = p_COM_ExplainDisconnection.RCast<void* (*)(uint64_t, const char*, ...)>(); /*48 8B C4 48 89 50 10 4C 89 40 18 4C 89 48 20 48 81 EC ?? ?? ?? ??*/
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -20,6 +20,11 @@
#include "game/server/ai_network.h" #include "game/server/ai_network.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
ConVar r_debug_draw_depth_test("r_debug_draw_depth_test", "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Toggle depth test for other debug draw functionality");
static ConVar r_debug_overlay_nodecay("r_debug_overlay_nodecay", "0", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Keeps all debug overlays alive regardless of their lifetime. Use command 'clear_debug_overlays' to clear everything");
static ConVar r_debug_overlay_invisible("r_debug_overlay_invisible", "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Show invisible debug overlays (alpha < 1 = 255)");
static ConVar r_debug_overlay_wireframe("r_debug_overlay_wireframe", "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Use wireframe in debug overlay");
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Purpose: checks if overlay should be decayed // Purpose: checks if overlay should be decayed
@ -27,7 +32,7 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool OverlayBase_t::IsDead() const bool OverlayBase_t::IsDead() const
{ {
if (r_debug_overlay_nodecay->GetBool()) if (r_debug_overlay_nodecay.GetBool())
{ {
// Keep rendering the overlay if no-decay is set. // Keep rendering the overlay if no-decay is set.
return false; return false;
@ -107,7 +112,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
OverlayBox_t* pBox = static_cast<OverlayBox_t*>(pOverlay); OverlayBox_t* pBox = static_cast<OverlayBox_t*>(pOverlay);
if (pBox->a < 1) if (pBox->a < 1)
{ {
if (r_debug_overlay_invisible->GetBool()) if (r_debug_overlay_invisible.GetBool())
{ {
pBox->a = 255; pBox->a = 255;
} }
@ -126,7 +131,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
OverlaySphere_t* pSphere = static_cast<OverlaySphere_t*>(pOverlay); OverlaySphere_t* pSphere = static_cast<OverlaySphere_t*>(pOverlay);
if (pSphere->a < 1) if (pSphere->a < 1)
{ {
if (r_debug_overlay_invisible->GetBool()) if (r_debug_overlay_invisible.GetBool())
{ {
pSphere->a = 255; pSphere->a = 255;
} }
@ -137,14 +142,14 @@ void DrawOverlay(OverlayBase_t* pOverlay)
} }
} }
if (r_debug_overlay_wireframe->GetBool()) if (r_debug_overlay_wireframe.GetBool())
{ {
v_RenderWireframeSphere(pSphere->vOrigin, pSphere->flRadius, pSphere->nTheta, pSphere->nPhi, v_RenderWireframeSphere(pSphere->vOrigin, pSphere->flRadius, pSphere->nTheta, pSphere->nPhi,
Color(pSphere->r, pSphere->g, pSphere->b, pSphere->a), r_debug_draw_depth_test->GetBool()); Color(pSphere->r, pSphere->g, pSphere->b, pSphere->a), r_debug_draw_depth_test.GetBool());
} }
else else
{ {
DebugDrawSphere(pSphere->vOrigin, pSphere->flRadius, Color(pSphere->r, pSphere->g, pSphere->b, pSphere->a), 16, r_debug_draw_depth_test->GetBool()); DebugDrawSphere(pSphere->vOrigin, pSphere->flRadius, Color(pSphere->r, pSphere->g, pSphere->b, pSphere->a), 16, r_debug_draw_depth_test.GetBool());
} }
break; break;
} }
@ -153,7 +158,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
OverlayLine_t* pLine = static_cast<OverlayLine_t*>(pOverlay); OverlayLine_t* pLine = static_cast<OverlayLine_t*>(pOverlay);
if (pLine->a < 1) if (pLine->a < 1)
{ {
if (r_debug_overlay_invisible->GetBool()) if (r_debug_overlay_invisible.GetBool())
{ {
pLine->a = 255; pLine->a = 255;
} }
@ -188,7 +193,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
OverlayCapsule_t* pCapsule = static_cast<OverlayCapsule_t*>(pOverlay); OverlayCapsule_t* pCapsule = static_cast<OverlayCapsule_t*>(pOverlay);
if (pCapsule->a < 1) if (pCapsule->a < 1)
{ {
if (r_debug_overlay_invisible->GetBool()) if (r_debug_overlay_invisible.GetBool())
{ {
pCapsule->a = 255; pCapsule->a = 255;
} }
@ -205,7 +210,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
AngleInverse(angles, angles); AngleInverse(angles, angles);
DebugDrawCapsule(pCapsule->start, angles, pCapsule->radius, pCapsule->start.DistTo(pCapsule->end), DebugDrawCapsule(pCapsule->start, angles, pCapsule->radius, pCapsule->start.DistTo(pCapsule->end),
Color(pCapsule->r, pCapsule->g, pCapsule->b, pCapsule->a), r_debug_draw_depth_test->GetBool()); Color(pCapsule->r, pCapsule->g, pCapsule->b, pCapsule->a), r_debug_draw_depth_test.GetBool());
break; break;
} }
case OverlayType_t::OVERLAY_UNK0: case OverlayType_t::OVERLAY_UNK0:
@ -292,16 +297,7 @@ void DrawAllOverlays(bool bRender)
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
if (bOverlayEnabled) if (bOverlayEnabled)
{ {
if (ai_script_nodes_draw->GetInt() > -1) g_pAIUtility->RunRenderFrame();
g_pAIUtility->DrawAIScriptNetwork(*g_pAINetwork);
if (navmesh_draw_bvtree->GetInt() > -1)
g_pAIUtility->DrawNavMeshBVTree();
if (navmesh_draw_portal->GetInt() > -1)
g_pAIUtility->DrawNavMeshPortals();
if (navmesh_draw_polys->GetInt() > -1)
g_pAIUtility->DrawNavMeshPolys();
if (navmesh_draw_poly_bounds->GetInt() > -1)
g_pAIUtility->DrawNavMeshPolyBoundaries();
} }
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
@ -309,12 +305,7 @@ void DrawAllOverlays(bool bRender)
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VDebugOverlay::Attach() const void VDebugOverlay::Detour(const bool bAttach) const
{ {
DetourAttach(&v_DrawAllOverlays, &DrawAllOverlays); DetourSetup(&v_DrawAllOverlays, &DrawAllOverlays, bAttach);
}
void VDebugOverlay::Detach() const
{
DetourDetach(&v_DrawAllOverlays, &DrawAllOverlays);
} }

View File

@ -4,22 +4,8 @@
#include "mathlib/color.h" #include "mathlib/color.h"
#include "mathlib/ssemath.h" #include "mathlib/ssemath.h"
// Something has to be hardcoded..
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2)
constexpr auto MATERIALSYSTEM_VCALL_OFF_0 = 0x3F8;
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_0 = 0x278;
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_1 = 0x280;
#elif defined (GAMEDLL_S3)
constexpr auto MATERIALSYSTEM_VCALL_OFF_0 = 0x3F0;
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_0 = 0x288;
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_1 = 0x290;
#endif
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_2 = 0x8;
constexpr auto NDEBUG_PERSIST_TILL_NEXT_SERVER = (0.01023f); constexpr auto NDEBUG_PERSIST_TILL_NEXT_SERVER = (0.01023f);
extern ConVar r_debug_draw_depth_test;
enum class OverlayType_t enum class OverlayType_t
{ {
@ -159,19 +145,10 @@ struct OverlayCapsule_t : public OverlayBase_t
void DestroyOverlay(OverlayBase_t* pOverlay); void DestroyOverlay(OverlayBase_t* pOverlay);
void DrawOverlay(OverlayBase_t* pOverlay); void DrawOverlay(OverlayBase_t* pOverlay);
inline CMemory p_DrawAllOverlays;
inline void(*v_DrawAllOverlays)(bool bDraw); inline void(*v_DrawAllOverlays)(bool bDraw);
inline CMemory p_DestroyOverlay;
inline void(*v_DestroyOverlay)(OverlayBase_t* pOverlay); inline void(*v_DestroyOverlay)(OverlayBase_t* pOverlay);
inline CMemory p_RenderLine;
inline void*(*v_RenderLine)(const Vector3D& vOrigin, const Vector3D& vDest, Color color, bool bZBuffer); inline void*(*v_RenderLine)(const Vector3D& vOrigin, const Vector3D& vDest, Color color, bool bZBuffer);
inline CMemory p_RenderBox;
inline void*(*v_RenderBox)(const matrix3x4_t& vTransforms, const Vector3D& vMins, const Vector3D& vMaxs, Color color, bool bZBuffer); inline void*(*v_RenderBox)(const matrix3x4_t& vTransforms, const Vector3D& vMins, const Vector3D& vMaxs, Color color, bool bZBuffer);
inline CMemory p_RenderWireframeSphere;
inline void*(*v_RenderWireframeSphere)(const Vector3D& vCenter, float flRadius, int nTheta, int nPhi, Color color, bool bZBuffer); inline void*(*v_RenderWireframeSphere)(const Vector3D& vCenter, float flRadius, int nTheta, int nPhi, Color color, bool bZBuffer);
inline OverlayBase_t** s_pOverlays = nullptr; inline OverlayBase_t** s_pOverlays = nullptr;
@ -185,50 +162,33 @@ class VDebugOverlay : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("DrawAllOverlays", p_DrawAllOverlays.GetPtr()); LogFunAdr("DrawAllOverlays", v_DrawAllOverlays);
LogFunAdr("DestroyOverlay", p_DestroyOverlay.GetPtr()); LogFunAdr("DestroyOverlay", v_DestroyOverlay);
LogFunAdr("RenderLine", p_RenderLine.GetPtr()); LogFunAdr("RenderLine", v_RenderLine);
LogFunAdr("RenderBox", p_RenderBox.GetPtr()); LogFunAdr("RenderBox", v_RenderBox);
LogFunAdr("RenderWireframeSphere", p_RenderWireframeSphere.GetPtr()); LogFunAdr("RenderWireframeSphere", v_RenderWireframeSphere);
LogVarAdr("s_Overlays", reinterpret_cast<uintptr_t>(s_pOverlays)); LogVarAdr("s_Overlays", s_pOverlays);
LogVarAdr("s_OverlayMutex", reinterpret_cast<uintptr_t>(s_OverlayMutex)); LogVarAdr("s_OverlayMutex", s_OverlayMutex);
LogVarAdr("g_nOverlayTickCount", reinterpret_cast<uintptr_t>(g_nOverlayTickCount)); LogVarAdr("g_nOverlayTickCount", g_nOverlayTickCount);
LogVarAdr("g_nRenderTickCount", reinterpret_cast<uintptr_t>(g_nRenderTickCount)); LogVarAdr("g_nRenderTickCount", g_nRenderTickCount);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("40 55 48 83 EC 30 48 8B 05 ?? ?? ?? ?? 0F B6 E9").GetPtr(v_DrawAllOverlays);
p_DrawAllOverlays = g_GameDll.FindPatternSIMD("40 55 48 83 EC 50 48 8B 05 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 44 89 4C 24 ??").GetPtr(v_RenderBox);
p_RenderBox = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 44 89 4C 24 ?? 55 41 56"); g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B D9 48 8D 0D ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 48 63 03").GetPtr(v_DestroyOverlay);
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) g_GameDll.FindPatternSIMD("40 56 41 54 41 55 48 81 EC ?? ?? ?? ??").GetPtr(v_RenderWireframeSphere);
p_DrawAllOverlays = g_GameDll.FindPatternSIMD("40 55 48 83 EC 30 48 8B 05 ?? ?? ?? ?? 0F B6 E9"); g_GameDll.FindPatternSIMD("48 89 74 24 ?? 44 89 44 24 ?? 57 41 56").GetPtr(v_RenderLine);
p_RenderBox = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 44 89 4C 24 ??");
#endif
p_DestroyOverlay = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B D9 48 8D 0D ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 48 63 03");
p_RenderWireframeSphere = g_GameDll.FindPatternSIMD("40 56 41 54 41 55 48 81 EC ?? ?? ?? ??");
p_RenderLine = g_GameDll.FindPatternSIMD("48 89 74 24 ?? 44 89 44 24 ?? 57 41 56");
v_DrawAllOverlays = p_DrawAllOverlays.RCast<void (*)(bool)>(); /*40 55 48 83 EC 30 48 8B 05 ?? ?? ?? ?? 0F B6 E9*/
v_DestroyOverlay = p_DestroyOverlay.RCast<void (*)(OverlayBase_t*)>(); /*40 53 48 83 EC 20 48 8B D9 48 8D 0D ?? ?? ?? ?? FF 15 ?? ?? ?? ?? 48 63 03 */
v_RenderBox = p_RenderBox.RCast<void* (*)(const matrix3x4_t&, const Vector3D&, const Vector3D&, Color, bool)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 44 89 4C 24 ??*/
v_RenderWireframeSphere = p_RenderWireframeSphere.RCast<void* (*)(const Vector3D&, float, int, int, Color, bool)>(); /*40 56 41 54 41 55 48 81 EC ?? ?? ?? ??*/
v_RenderLine = p_RenderLine.RCast<void* (*)(const Vector3D&, const Vector3D&, Color, bool)>(); /*48 89 74 24 ?? 44 89 44 24 ?? 57 41 56*/
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
s_pOverlays = p_DrawAllOverlays.Offset(0x10).FindPatternSelf("48 8B 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<OverlayBase_t**>(); s_pOverlays = CMemory(v_DrawAllOverlays).Offset(0x10).FindPatternSelf("48 8B 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<OverlayBase_t**>();
s_OverlayMutex = p_DrawAllOverlays.Offset(0x10).FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<LPCRITICAL_SECTION>(); s_OverlayMutex = CMemory(v_DrawAllOverlays).Offset(0x10).FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<LPCRITICAL_SECTION>();
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_nRenderTickCount = CMemory(v_DrawAllOverlays).Offset(0x50).FindPatternSelf("3B 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
g_nRenderTickCount = p_DrawAllOverlays.Offset(0x80).FindPatternSelf("3B 0D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>(); g_nOverlayTickCount = CMemory(v_DrawAllOverlays).Offset(0x70).FindPatternSelf("3B 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
g_nOverlayTickCount = p_DrawAllOverlays.Offset(0x70).FindPatternSelf("3B 0D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
g_nRenderTickCount = p_DrawAllOverlays.Offset(0x50).FindPatternSelf("3B 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
g_nOverlayTickCount = p_DrawAllOverlays.Offset(0x70).FindPatternSelf("3B 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
#endif
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -6,13 +6,3 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "engine/enginetrace.h" #include "engine/enginetrace.h"
void CEngineTrace_Attach()
{
}
void CEngineTrace_Detach()
{
}

View File

@ -22,20 +22,16 @@ class CEngineTraceClient : public CEngineTrace
inline CEngineTraceClient* g_pEngineTraceClient = nullptr; inline CEngineTraceClient* g_pEngineTraceClient = nullptr;
#endif // DEDICATED #endif // DEDICATED
///////////////////////////////////////////////////////////////////////////////
void CEngineTrace_Attach();
void CEngineTrace_Detach();
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VEngineTrace : public IDetour class VEngineTrace : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
LogVarAdr("g_pEngineTraceServer", reinterpret_cast<uintptr_t>(g_pEngineTraceServer)); LogVarAdr("g_pEngineTraceServer", g_pEngineTraceServer);
#endif // CLIENT_DLL #endif // CLIENT_DLL
#ifndef DEDICATED #ifndef DEDICATED
LogVarAdr("g_pEngineTraceClient", reinterpret_cast<uintptr_t>(g_pEngineTraceClient)); LogVarAdr("g_pEngineTraceClient", g_pEngineTraceClient);
#endif // DEDICATED #endif // DEDICATED
} }
virtual void GetFun(void) const { } virtual void GetFun(void) const { }
@ -47,7 +43,6 @@ class VEngineTrace : public IDetour
g_pEngineTraceServer = reinterpret_cast<CEngineTraceServer*>(&g_pEngineTraceServerVFTable); // Must be done for virtual calls. g_pEngineTraceServer = reinterpret_cast<CEngineTraceServer*>(&g_pEngineTraceServerVFTable); // Must be done for virtual calls.
#endif // CLIENT_DLL #endif // CLIENT_DLL
} }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,93 @@
//===========================================================================//
//
// Purpose: High-precision frame rate limiter
//
//===========================================================================//
#include <dwmapi.h>
#include "tier0/platform_internal.h"
#include "windows/id3dx.h"
#include "sys_mainwind.h"
#include "framelimit.h"
//-----------------------------------------------------------------------------
// Purpose: constructor
//-----------------------------------------------------------------------------
CFrameLimit::CFrameLimit(void)
{
m_MilliSeconds = 0.0;
m_FramesPerSecond = 0.0;
m_Start.QuadPart = 0;
m_Next.QuadPart = 0;
m_Time.QuadPart = 0;
m_Frames = 0;
m_bRestart = false;
}
//-----------------------------------------------------------------------------
// Purpose: initializer
// Input : targetFps -
//-----------------------------------------------------------------------------
void CFrameLimit::Reset(double targetFps)
{
m_MilliSeconds = 1000.0 / targetFps;
m_FramesPerSecond = targetFps;
QueryPerformanceCounter(&m_Start);
m_Next.QuadPart = 0ULL;
m_Time.QuadPart = 0ULL;
//m_Last.QuadPart = m_Start.QuadPart - (LONGLONG)((m_MilliSeconds / 1000.0) * g_pPerformanceFrequency->QuadPart);
m_Next.QuadPart = m_Start.QuadPart + (LONGLONG)((m_MilliSeconds / 1000.0) * g_pPerformanceFrequency->QuadPart);
m_Frames = 0;
}
//-----------------------------------------------------------------------------
// Purpose: runs the frame limiter logic
//-----------------------------------------------------------------------------
void CFrameLimit::Run(const double targetFps, const double sleepThreshold, const double maxTolerance)
{
if (m_FramesPerSecond != targetFps)
Reset(targetFps);
m_Frames++;
QueryPerformanceCounter(&m_Time);
// Actual frametime before we forced a delay
//m_EffectiveMilliSeconds = 1000.0 * ((double)(m_Time.QuadPart - m_Last.QuadPart) / (double)g_pPerformanceFrequency->QuadPart);
if ((double)(m_Time.QuadPart - m_Next.QuadPart) / (double)g_pPerformanceFrequency->QuadPart / (m_MilliSeconds / 1000.0) > (maxTolerance * m_FramesPerSecond))
{
DevMsg(eDLL_T::ENGINE, "%s: Frame time too long (expected: %3.01fx); restarting...\n",
__FUNCTION__, (double)(m_Time.QuadPart - m_Next.QuadPart) / (double)g_pPerformanceFrequency->QuadPart / (m_MilliSeconds / 1000.0) / m_FramesPerSecond );
m_bRestart = true;
}
if (m_bRestart)
{
m_Frames = 0;
m_Start.QuadPart = m_Time.QuadPart + (LONGLONG)((m_MilliSeconds / 1000.0) * (double)g_pPerformanceFrequency->QuadPart);
m_bRestart = false;
//Reset (targetFps);
//return;
}
m_Next.QuadPart = (LONGLONG)((m_Start.QuadPart + (double)m_Frames * (m_MilliSeconds / 1000.0) * (double)g_pPerformanceFrequency->QuadPart));
if (m_Next.QuadPart > 0ULL)
{
while (m_Time.QuadPart < m_Next.QuadPart)
{
if ((double)(m_Next.QuadPart - m_Time.QuadPart) > (sleepThreshold * (double)g_pPerformanceFrequency->QuadPart))
{
Sleep(10);
}
QueryPerformanceCounter(&m_Time);
}
}
//m_Last.QuadPart = m_Time.QuadPart;
}

26
r5dev/engine/framelimit.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef FRAMELIMIT_H
#define FRAMELIMIT_H
//-----------------------------------------------------------------------------
// RenderThread frame limiter
//-----------------------------------------------------------------------------
class CFrameLimit
{
public:
CFrameLimit(void);
void Reset(const double target);
void Run(const double targetFps, const double sleepThreshold, const double maxTolerance);
private:
double m_MilliSeconds;
double m_FramesPerSecond;
LARGE_INTEGER m_Start;
LARGE_INTEGER m_Next;
LARGE_INTEGER m_Time;
uint32_t m_Frames;
bool m_bRestart;
};
#endif // FRAMELIMIT_H

View File

@ -0,0 +1,13 @@
#include "gl_drawlights.h"
void DrawLightSprites(void* unkType)
{
v_DrawLightSprites(unkType);
}
void VGL_DrawLights::Detour(const bool bAttach) const
{
// Enable if needed.
//DetourSetup(&v_DrawLightSprites, &DrawLightSprites, bAttach);
}

View File

@ -0,0 +1,20 @@
#pragma once
inline void(*v_DrawLightSprites)(void*);
///////////////////////////////////////////////////////////////////////////////
class VGL_DrawLights : public IDetour
{
virtual void GetAdr(void) const
{
LogFunAdr("DrawLightSprites", v_DrawLightSprites);
}
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("48 8B C4 55 57 48 8D 68 A1 48 81 EC ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ??").GetPtr(v_DrawLightSprites);
}
virtual void GetVar(void) const { }
virtual void GetCon(void) const { }
virtual void Detour(const bool bAttach) const;
};
///////////////////////////////////////////////////////////////////////////////

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
/* ==== MATSYSIFACE ===================================================================================================================================================== */ /* ==== MATSYSIFACE ===================================================================================================================================================== */
inline CMemory p_InitMaterialSystem;
inline void*(*v_InitMaterialSystem)(void); inline void*(*v_InitMaterialSystem)(void);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -9,20 +8,14 @@ class VGL_MatSysIFace : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("InitMaterialSystem", p_InitMaterialSystem.GetPtr()); LogFunAdr("InitMaterialSystem", v_InitMaterialSystem);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ??").GetPtr(v_InitMaterialSystem);
p_InitMaterialSystem = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 48 8D 1D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ??");
#else
p_InitMaterialSystem = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ??");
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1)
v_InitMaterialSystem = p_InitMaterialSystem.RCast<void* (*)(void)>();
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -9,20 +9,57 @@
#ifndef GL_MODEL_PRIVATE_H #ifndef GL_MODEL_PRIVATE_H
#define GL_MODEL_PRIVATE_H #define GL_MODEL_PRIVATE_H
#include "vpc/keyvalues.h" #include "tier1/keyvalues.h"
#include "mathlib/vector.h" #include "mathlib/vector.h"
#include "common/qlimits.h" #include "common/qlimits.h"
#include "datacache/imdlcache.h" #include "datacache/imdlcache.h"
#include "public/model_types.h" #include "public/model_types.h"
#include "public/bspfile.h"
#ifndef DEDICATED #ifndef DEDICATED
#include "game/client/enginesprite.h" #include "game/client/enginesprite.h"
#endif // !DEDICATED #endif // !DEDICATED
typedef int ModelFileNameHandle_t; // 4 bytes in r5, void* originally. typedef int ModelFileNameHandle_t; // 4 bytes in r5, void* originally.
struct worldbrushdata_t
{
char unk[64];
Vector3D* vertpositions;
int numvertices;
char unk_4C[4];
Vector3D* vertnormals;
int numvertnormals;
int numtexdata;
dtexdata_t* texdata;
char* surfacenames;
char unk_60[4];
int nummeshes;
char unk_78[72];
int nummaterialsorts;
char unk_C4[4];
char* lmapTypes;
int* lmapSizes;
dlightmapheader_t* lmapHeaders;
char* rtlData;
char* rtlPageData;
int numRtlPages;
int numLightmapHeaders;
bool externalLightmaps;
int numlightprobeindices;
int* lightprobeindices;
int numlightprobes;
dlightprobe_t* lightprobes;
char* lightproberefs;
char* lightprobetrees;
char* lightprobeparentinfos;
char unk_130[16];
char* worldlights;
int numworldlights;
};
struct brushdata_t // !! UNCONFIRMED !! struct brushdata_t // !! UNCONFIRMED !!
{ {
void* pShared; // worldbrushdata_t worldbrushdata_t* pShared; // worldbrushdata_t
int firstmodelsurface; int firstmodelsurface;
int nummodelsurfaces; int nummodelsurfaces;

View File

@ -24,8 +24,7 @@ class VGL_RMain : public IDetour
virtual void GetFun(void) const { } virtual void GetFun(void) const { }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -6,11 +6,24 @@
//===========================================================================// //===========================================================================//
#include "core/stdafx.h" #include "core/stdafx.h"
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "windows/id3dx.h"
#include "geforce/reflex.h"
#include "engine/gl_rsurf.h" #include "engine/gl_rsurf.h"
#include <materialsystem/cmaterialsystem.h>
static ConVar r_drawWorldMeshes("r_drawWorldMeshes", "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Render world meshes.");
static ConVar r_drawWorldMeshesDepthOnly("r_drawWorldMeshesDepthOnly", "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Render world meshes (depth only).");
static ConVar r_drawWorldMeshesDepthAtTheEnd("r_drawWorldMeshesDepthAtTheEnd", "1", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, "Render world meshes (depth at the end).");
void* R_DrawDepthOfField(const float scalar)
{
GFX_SetLatencyMarker(D3D11Device(), RENDERSUBMIT_START, MaterialSystem()->GetCurrentFrameCount());
return V_DrawDepthOfField(scalar);
}
void* R_DrawWorldMeshes(void* baseEntity, void* renderContext, DrawWorldLists_t worldLists) void* R_DrawWorldMeshes(void* baseEntity, void* renderContext, DrawWorldLists_t worldLists)
{ {
if (r_drawWorldMeshes->GetBool()) if (r_drawWorldMeshes.GetBool())
return V_DrawWorldMeshes(baseEntity, renderContext, worldLists); return V_DrawWorldMeshes(baseEntity, renderContext, worldLists);
else else
return nullptr; return nullptr;
@ -18,7 +31,7 @@ void* R_DrawWorldMeshes(void* baseEntity, void* renderContext, DrawWorldLists_t
void* R_DrawWorldMeshesDepthOnly(void* renderContext, DrawWorldLists_t worldLists) void* R_DrawWorldMeshesDepthOnly(void* renderContext, DrawWorldLists_t worldLists)
{ {
if (r_drawWorldMeshesDepthOnly->GetBool()) if (r_drawWorldMeshesDepthOnly.GetBool())
return V_DrawWorldMeshesDepthOnly(renderContext, worldLists); return V_DrawWorldMeshesDepthOnly(renderContext, worldLists);
else else
return nullptr; return nullptr;
@ -26,22 +39,16 @@ void* R_DrawWorldMeshesDepthOnly(void* renderContext, DrawWorldLists_t worldList
void* R_DrawWorldMeshesDepthAtTheEnd(void* ptr1, void* ptr2, void* ptr3, DrawWorldLists_t worldLists) void* R_DrawWorldMeshesDepthAtTheEnd(void* ptr1, void* ptr2, void* ptr3, DrawWorldLists_t worldLists)
{ {
if (r_drawWorldMeshesDepthAtTheEnd->GetBool()) if (r_drawWorldMeshesDepthAtTheEnd.GetBool())
return V_DrawWorldMeshesDepthAtTheEnd(ptr1, ptr2, ptr3, worldLists); return V_DrawWorldMeshesDepthAtTheEnd(ptr1, ptr2, ptr3, worldLists);
else else
return nullptr; return nullptr;
} }
void VGL_RSurf::Attach() const void VGL_RSurf::Detour(const bool bAttach) const
{ {
DetourAttach(&V_DrawWorldMeshes, &R_DrawWorldMeshes); DetourSetup(&V_DrawDepthOfField, &R_DrawDepthOfField, bAttach);
DetourAttach(&V_DrawWorldMeshesDepthOnly, &R_DrawWorldMeshesDepthOnly); DetourSetup(&V_DrawWorldMeshes, &R_DrawWorldMeshes, bAttach);
DetourAttach(&V_DrawWorldMeshesDepthAtTheEnd, &R_DrawWorldMeshesDepthAtTheEnd); DetourSetup(&V_DrawWorldMeshesDepthOnly, &R_DrawWorldMeshesDepthOnly, bAttach);
DetourSetup(&V_DrawWorldMeshesDepthAtTheEnd, &R_DrawWorldMeshesDepthAtTheEnd, bAttach);
} }
void VGL_RSurf::Detach() const
{
DetourDetach(&V_DrawWorldMeshes, &R_DrawWorldMeshes);
DetourDetach(&V_DrawWorldMeshesDepthOnly, &R_DrawWorldMeshesDepthOnly);
DetourDetach(&V_DrawWorldMeshesDepthAtTheEnd, &R_DrawWorldMeshesDepthAtTheEnd);
}

View File

@ -1,13 +1,9 @@
#pragma once #pragma once
#include "public/ivrenderview.h" #include "public/ivrenderview.h"
inline CMemory P_DrawWorldMeshes; inline void*(*V_DrawDepthOfField)(const float scalar);
inline void*(*V_DrawWorldMeshes)(void* baseEntity, void* renderContext, DrawWorldLists_t worldLists); inline void*(*V_DrawWorldMeshes)(void* baseEntity, void* renderContext, DrawWorldLists_t worldLists);
inline CMemory P_DrawWorldMeshesDepthOnly;
inline void*(*V_DrawWorldMeshesDepthOnly)(void* renderContext, DrawWorldLists_t worldLists); inline void*(*V_DrawWorldMeshesDepthOnly)(void* renderContext, DrawWorldLists_t worldLists);
inline CMemory P_DrawWorldMeshesDepthAtTheEnd;
inline void*(*V_DrawWorldMeshesDepthAtTheEnd)(void* ptr1, void* ptr2, void* ptr3, DrawWorldLists_t worldLists); inline void*(*V_DrawWorldMeshesDepthAtTheEnd)(void* ptr1, void* ptr2, void* ptr3, DrawWorldLists_t worldLists);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -15,27 +11,20 @@ class VGL_RSurf : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("R_DrawWorldMeshes", P_DrawWorldMeshes.GetPtr()); LogFunAdr("R_DrawDepthOfField", V_DrawDepthOfField);
LogFunAdr("R_DrawWorldMeshesDepthOnly", P_DrawWorldMeshesDepthOnly.GetPtr()); LogFunAdr("R_DrawWorldMeshes", V_DrawWorldMeshes);
LogFunAdr("R_DrawWorldMeshesDepthAtTheEnd", P_DrawWorldMeshesDepthAtTheEnd.GetPtr()); LogFunAdr("R_DrawWorldMeshesDepthOnly", V_DrawWorldMeshesDepthOnly);
LogFunAdr("R_DrawWorldMeshesDepthAtTheEnd", V_DrawWorldMeshesDepthAtTheEnd);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 83 EC 48 0F 28 E8").GetPtr(V_DrawDepthOfField);
P_DrawWorldMeshes = g_GameDll.FindPatternSIMD("48 8B C4 48 89 48 08 53 48 83 EC 70"); g_GameDll.FindPatternSIMD("48 8B C4 48 89 48 08 53 57 41 55").GetPtr(V_DrawWorldMeshes);
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) g_GameDll.FindPatternSIMD("40 56 57 B8 ?? ?? ?? ??").GetPtr(V_DrawWorldMeshesDepthOnly);
P_DrawWorldMeshes = g_GameDll.FindPatternSIMD("48 8B C4 48 89 48 08 53 57 41 55"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 41 8B F9").GetPtr(V_DrawWorldMeshesDepthAtTheEnd);
#endif
P_DrawWorldMeshesDepthOnly = g_GameDll.FindPatternSIMD("40 56 57 B8 ?? ?? ?? ??");
P_DrawWorldMeshesDepthAtTheEnd = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 41 8B F9");
V_DrawWorldMeshes = P_DrawWorldMeshes.RCast<void* (*)(void*, void*, DrawWorldLists_t)>(); /*48 8B C4 48 89 48 08 53 57 41 55*/
V_DrawWorldMeshesDepthOnly = P_DrawWorldMeshesDepthOnly.RCast<void* (*)(void*, DrawWorldLists_t)>(); /*40 56 57 B8 ?? ?? ?? ??*/
V_DrawWorldMeshesDepthAtTheEnd = P_DrawWorldMeshesDepthAtTheEnd.RCast<void* (*)(void*, void*, void*, DrawWorldLists_t)>(); /*48 89 5C 24 ?? 48 89 74 24 ? 57 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 41 8B F9*/
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
inline CMemory SCR_BeginLoadingPlaque; inline __int64(*v_SCR_BeginLoadingPlaque)(void* a1);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
inline bool* scr_drawloading = nullptr; inline bool* scr_drawloading = nullptr;
@ -14,32 +14,20 @@ class VGL_Screen : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("SCR_BeginLoadingPlaque", SCR_BeginLoadingPlaque.GetPtr()); LogFunAdr("SCR_BeginLoadingPlaque", v_SCR_BeginLoadingPlaque);
LogVarAdr("scr_drawloading", reinterpret_cast<uintptr_t>(scr_drawloading)); LogVarAdr("scr_drawloading", scr_drawloading);
LogVarAdr("scr_engineevent_loadingstarted", reinterpret_cast<uintptr_t>(scr_engineevent_loadingstarted)); LogVarAdr("scr_engineevent_loadingstarted", scr_engineevent_loadingstarted);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 83 EC 38 0F 29 74 24 ?? 48 89 5C 24 ??").GetPtr(v_SCR_BeginLoadingPlaque);
SCR_BeginLoadingPlaque = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 30 0F 29 74 24 ?? 48 8B F9");
// 0x14022A4A0 // 48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 30 0F 29 74 24 ? 48 8B F9 //
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
SCR_BeginLoadingPlaque = g_GameDll.FindPatternSIMD("48 83 EC 38 0F 29 74 24 ?? 48 89 5C 24 ??");
// 0x14022A4A0 // 48 83 EC 38 0F 29 74 24 ? 48 89 5C 24 ? //
#endif
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
scr_drawloading = g_GameDll.FindPatternSIMD("0F B6 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 83 EC 28").ResolveRelativeAddressSelf(0x3, 0x7).RCast<bool*>(); scr_drawloading = g_GameDll.FindPatternSIMD("0F B6 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 83 EC 28").ResolveRelativeAddressSelf(0x3, 0x7).RCast<bool*>();
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) scr_engineevent_loadingstarted = CMemory(v_SCR_BeginLoadingPlaque).Offset(0x60).FindPatternSelf("C6 05 ?? ?? ?? ?? 01", CMemory::Direction::DOWN).ResolveRelativeAddress(0x2, 0x7).RCast<bool*>();
scr_engineevent_loadingstarted = SCR_BeginLoadingPlaque.Offset(0x130).FindPatternSelf("C6 05 ?? ?? ?? ?? 01", CMemory::Direction::DOWN).ResolveRelativeAddress(0x2, 0x7).RCast<bool*>();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
scr_engineevent_loadingstarted = SCR_BeginLoadingPlaque.Offset(0x60).FindPatternSelf("C6 05 ?? ?? ?? ?? 01", CMemory::Direction::DOWN).ResolveRelativeAddress(0x2, 0x7).RCast<bool*>();
#endif
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -9,9 +9,49 @@
#include "tier0/frametask.h" #include "tier0/frametask.h"
#include "engine/host.h" #include "engine/host.h"
#ifndef DEDICATED #ifndef DEDICATED
#include "windows/id3dx.h"
#include "geforce/reflex.h"
#include "vgui/vgui_debugpanel.h" #include "vgui/vgui_debugpanel.h"
#include <materialsystem/cmaterialsystem.h>
#endif // !DEDICATED #endif // !DEDICATED
CCommonHostState* g_pCommonHostState = nullptr;
void CCommonHostState::SetWorldModel(model_t* pModel)
{
if (worldmodel == pModel)
return;
worldmodel = pModel;
if (pModel)
{
worldbrush = pModel->brush.pShared;
}
else
{
worldbrush = NULL;
}
}
/*
==================
Host_CountRealTimePackets
Counts the number of
packets in non-prescaled
clock frames (does not
count for bots or Terminal
Services environments)
==================
*/
void Host_CountRealTimePackets()
{
v_Host_CountRealTimePackets();
#ifndef DEDICATED
GFX_SetLatencyMarker(D3D11Device(), SIMULATION_START, MaterialSystem()->GetCurrentFrameCount());
#endif // !DEDICATED
}
/* /*
================== ==================
_Host_RunFrame _Host_RunFrame
@ -21,24 +61,24 @@ Runs all active servers
*/ */
void _Host_RunFrame(void* unused, float time) void _Host_RunFrame(void* unused, float time)
{ {
for (IFrameTask* const& task : g_FrameTasks) for (IFrameTask* const& task : g_TaskQueueList)
{ {
task->RunFrame(); task->RunFrame();
} }
g_FrameTasks.erase(std::remove_if(g_FrameTasks.begin(), g_FrameTasks.end(), [](const IFrameTask* task) g_TaskQueueList.erase(std::remove_if(g_TaskQueueList.begin(), g_TaskQueueList.end(), [](const IFrameTask* task)
{ {
return task->IsFinished(); return task->IsFinished();
}), g_FrameTasks.end()); }), g_TaskQueueList.end());
#ifndef DEDICATED #ifndef DEDICATED
g_pOverlay->ShouldDraw(time); g_TextOverlay.ShouldDraw(time);
#endif // !DEDICATED #endif // !DEDICATED
return v_Host_RunFrame(unused, time); return v_Host_RunFrame(unused, time);
} }
void _Host_Error(char* error, ...) void _Host_Error(const char* error, ...)
{ {
char buf[1024]; char buf[1024];
{///////////////////////////// {/////////////////////////////
@ -56,20 +96,12 @@ void _Host_Error(char* error, ...)
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VHost::Attach() const void VHost::Detour(const bool bAttach) const
{ {
DetourAttach((LPVOID*)&v_Host_RunFrame, &_Host_RunFrame); DetourSetup(&v_Host_RunFrame, &_Host_RunFrame, bAttach);
DetourSetup(&v_Host_CountRealTimePackets, &Host_CountRealTimePackets, bAttach);
#ifndef DEDICATED // Dedicated already logs this! #ifndef DEDICATED // Dedicated already logs this!
DetourAttach((LPVOID*)&v_Host_Error, &_Host_Error); DetourSetup(&v_Host_Error, &_Host_Error, bAttach);
#endif // !DEDICATED #endif // !DEDICATED
} }
void VHost::Detach() const
{
DetourDetach((LPVOID*)&v_Host_RunFrame, &_Host_RunFrame);
#ifndef DEDICATED // Dedicated already logs this!
DetourDetach((LPVOID*)&v_Host_Error, &_Host_Error);
#endif // !DEDICATED
}

View File

@ -1,86 +1,93 @@
#pragma once #pragma once
#include "engine/gl_model_private.h"
inline CMemory p_Host_RunFrame;
inline void(*v_Host_RunFrame)(void* unused, float time); inline void(*v_Host_RunFrame)(void* unused, float time);
inline void(*v_Host_RunFrame_Render)(void);
//inline CMemory p_Host_RunFrame_Render; // DEDICATED PATCH! inline void(*v_Host_CountRealTimePackets)(void);
//inline void(*v_Host_RunFrame_Render)(void);
inline CMemory p_Host_ShouldRun;
inline bool(*v_Host_ShouldRun)(); inline bool(*v_Host_ShouldRun)();
inline CMemory p_Host_Error;
inline void(*v_Host_Error)(const char* error, ...); inline void(*v_Host_Error)(const char* error, ...);
//inline CMemory p_VCR_EnterPausedState; // DEDICATED PATCH!
//inline void(*v_VCR_EnterPausedState)(void); //inline void(*v_VCR_EnterPausedState)(void);
inline bool* g_bAbortServerSet = nullptr; inline bool* g_bAbortServerSet = nullptr;
inline float* interval_per_tick = nullptr;
inline jmp_buf* host_abortserver = nullptr; inline jmp_buf* host_abortserver = nullptr;
inline bool* host_initialized = nullptr; inline bool* host_initialized = nullptr;
inline float* host_frametime_unbounded = nullptr; inline float* host_frametime_unbounded = nullptr;
inline float* host_frametime_stddeviation = nullptr; inline float* host_frametime_stddeviation = nullptr;
class CCommonHostState
{
public:
CCommonHostState()
: worldmodel(NULL)
, worldbrush(NULL)
, interval_per_tick(0.0f)
, max_splitscreen_players(1)
, max_splitscreen_players_clientdll(1)
{}
// cl_entitites[0].model
model_t* worldmodel;
struct worldbrushdata_t* worldbrush;
// Tick interval for game
float interval_per_tick;
// 1, unless a game supports split screen, then probably 2 or 4 (4 is the max allowable)
int max_splitscreen_players;
// This is the # the client .dll thinks is the max, it might be > max_splitscreen_players in -tools mode, etc.
int max_splitscreen_players_clientdll;
void SetWorldModel(model_t* pModel);
};
extern CCommonHostState* g_pCommonHostState;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VHost : public IDetour class VHost : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("_Host_RunFrame", p_Host_RunFrame.GetPtr()); LogFunAdr("_Host_RunFrame", v_Host_RunFrame);
//LogFunAdr("_Host_RunFrame_Render", p_Host_RunFrame_Render.GetPtr()); LogFunAdr("_Host_RunFrame_Render", v_Host_RunFrame_Render);
LogFunAdr("Host_ShouldRun", p_Host_ShouldRun.GetPtr()); LogFunAdr("Host_CountRealTimePackets", v_Host_CountRealTimePackets);
LogFunAdr("Host_Error", p_Host_Error.GetPtr()); LogFunAdr("Host_ShouldRun", v_Host_ShouldRun);
//LogFunAdr("VCR_EnterPausedState", p_VCR_EnterPausedState.GetPtr()); LogFunAdr("Host_Error", v_Host_Error);
LogVarAdr("g_bAbortServerSet", reinterpret_cast<uintptr_t>(g_bAbortServerSet)); //LogFunAdr("VCR_EnterPausedState", v_VCR_EnterPausedState);
LogVarAdr("interval_per_tick", reinterpret_cast<uintptr_t>(interval_per_tick)); LogVarAdr("g_CommonHostState", g_pCommonHostState);
LogVarAdr("host_abortserver", reinterpret_cast<uintptr_t>(host_abortserver)); LogVarAdr("g_bAbortServerSet", g_bAbortServerSet);
LogVarAdr("host_initialized", reinterpret_cast<uintptr_t>(host_initialized)); LogVarAdr("host_abortserver", host_abortserver);
LogVarAdr("host_frametime_unbounded", reinterpret_cast<uintptr_t>(host_frametime_unbounded)); LogVarAdr("host_initialized", host_initialized);
LogVarAdr("host_frametime_stddeviation", reinterpret_cast<uintptr_t>(host_frametime_stddeviation)); LogVarAdr("host_frametime_unbounded", host_frametime_unbounded);
LogVarAdr("host_frametime_stddeviation", host_frametime_stddeviation);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_Host_RunFrame = g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 18 48 89 70 20 F3 0F 11 48 ??"); g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 18 48 89 70 20 F3 0F 11 48 ??").GetPtr(v_Host_RunFrame);
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 34").GetPtr(v_Host_RunFrame_Render);
//p_Host_RunFrame_Render = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B 1D ?? ?? ?? ?? 33 FF"); g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 65 48 8B 04 25 ?? ?? ?? ?? 33 DB").GetPtr(v_Host_CountRealTimePackets);
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 83 78 6C 00 75 07 B0 01").GetPtr(v_Host_ShouldRun);
//p_Host_RunFrame_Render = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 34"); g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 48 89 54 24 ?? 4C 89 44 24 ?? 4C 89 4C 24 ?? 53 57 48 81 EC ?? ?? ?? ??").GetPtr(v_Host_Error);
#endif //g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 65 48 8B 04 25 ?? ?? ?? ?? BB ?? ?? ?? ?? C6 05 ?? ?? ?? ?? ??").GetPtr(v_VCR_EnterPausedState);
p_Host_ShouldRun = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 83 78 6C 00 75 07 B0 01");
p_Host_Error = g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 48 89 54 24 ?? 4C 89 44 24 ?? 4C 89 4C 24 ?? 53 57 48 81 EC ?? ?? ?? ??");
//p_VCR_EnterPausedState = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 65 48 8B 04 25 ?? ?? ?? ?? BB ?? ?? ?? ?? C6 05 ?? ?? ?? ?? ??");
v_Host_RunFrame = p_Host_RunFrame.RCast<void(*)(void*, float)>();
//v_Host_RunFrame_Render = p_Host_Error.RCast<void(*)(void)>();
v_Host_ShouldRun = p_Host_ShouldRun.RCast<bool(*)()>();
v_Host_Error = p_Host_Error.RCast<void(*)(const char*, ...)>();
//v_VCR_EnterPausedState = p_VCR_EnterPausedState.RCast<void(*)(void)>();
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
interval_per_tick = g_GameDll.FindPatternSIMD("4C 8B DC 4D 89 4B 20 55 56 41 54").FindPatternSelf("F3 0F 5E", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>(); g_pCommonHostState = g_GameDll.FindPatternSIMD("48 83 EC 28 84 C9 75 0B")
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) .FindPatternSelf("48 8B 15").ResolveRelativeAddressSelf(0x3, 0x7).RCast<CCommonHostState*>();
g_bAbortServerSet = p_Host_Error.FindPattern("40 38 3D", CMemory::Direction::DOWN, 512, 2).ResolveRelativeAddress(3, 7).RCast<bool*>();
host_abortserver = p_Host_Error.FindPattern("48 8D 0D", CMemory::Direction::DOWN, 512, 3).ResolveRelativeAddress(3, 7).RCast<jmp_buf*>();
static const int n_host_frametime_unbounded_search_offset = 0x380; const CMemory hostErrorBase(v_Host_Error);
static const int n_host_frametime_stddeviation_search_offset = 0x1200;
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
g_bAbortServerSet = p_Host_Error.FindPattern("40 38 3D", CMemory::Direction::DOWN, 512, 4).ResolveRelativeAddress(3, 7).RCast<bool*>();
host_abortserver = p_Host_Error.FindPattern("48 8D 0D", CMemory::Direction::DOWN, 512, 5).ResolveRelativeAddress(3, 7).RCast<jmp_buf*>();
static const int n_host_initialized_search_offset = 0x500; // TODO: S1!!! g_bAbortServerSet = hostErrorBase.FindPattern("40 38 3D", CMemory::Direction::DOWN, 512, 4).ResolveRelativeAddress(3, 7).RCast<bool*>();
host_abortserver = hostErrorBase.FindPattern("48 8D 0D", CMemory::Direction::DOWN, 512, 5).ResolveRelativeAddress(3, 7).RCast<jmp_buf*>();
static const int n_host_initialized_search_offset = 0x500;
static const int n_host_frametime_unbounded_search_offset = 0x330; static const int n_host_frametime_unbounded_search_offset = 0x330;
static const int n_host_frametime_stddeviation_search_offset = 0xFAA; static const int n_host_frametime_stddeviation_search_offset = 0xFAA;
#endif
host_initialized = p_Host_RunFrame.Offset(n_host_initialized_search_offset).FindPatternSelf("44 38").ResolveRelativeAddressSelf(0x3, 0x7).RCast<bool*>(); const CMemory hostRunFrameBase(v_Host_RunFrame);
host_frametime_unbounded = p_Host_RunFrame.Offset(n_host_frametime_unbounded_search_offset).FindPatternSelf("F3 0F 11").ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>();
host_frametime_stddeviation = p_Host_RunFrame.Offset(n_host_frametime_stddeviation_search_offset).FindPatternSelf("F3 0F 11").ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>(); host_initialized = hostRunFrameBase.Offset(n_host_initialized_search_offset).FindPatternSelf("44 38").ResolveRelativeAddressSelf(0x3, 0x7).RCast<bool*>();
host_frametime_unbounded = hostRunFrameBase.Offset(n_host_frametime_unbounded_search_offset).FindPatternSelf("F3 0F 11").ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>();
host_frametime_stddeviation = hostRunFrameBase.Offset(n_host_frametime_stddeviation_search_offset).FindPatternSelf("F3 0F 11").ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -62,7 +62,6 @@ void Host_Status_PrintClient(CClient* client, bool bShowAddress, void (*print) (
//print("\n"); //print("\n");
} }
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
/* /*
================== ==================
DFS_InitializeFeatureFlagDefinitions DFS_InitializeFeatureFlagDefinitions
@ -78,25 +77,13 @@ bool DFS_InitializeFeatureFlagDefinitions(const char* pszFeatureFlags)
return v_DFS_InitializeFeatureFlagDefinitions(pszFeatureFlags); return v_DFS_InitializeFeatureFlagDefinitions(pszFeatureFlags);
} }
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VHostCmd::Attach() const void VHostCmd::Detour(const bool bAttach) const
{ {
DetourAttach(&v_Host_Shutdown, &Host_Shutdown); DetourSetup(&v_Host_Shutdown, &Host_Shutdown, bAttach);
DetourAttach(&v_Host_Status_PrintClient, &Host_Status_PrintClient); DetourSetup(&v_Host_Status_PrintClient, &Host_Status_PrintClient, bAttach);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2) DetourSetup(&v_DFS_InitializeFeatureFlagDefinitions, &DFS_InitializeFeatureFlagDefinitions, bAttach);
DetourAttach(&v_DFS_InitializeFeatureFlagDefinitions, &DFS_InitializeFeatureFlagDefinitions);
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2)
}
void VHostCmd::Detach() const
{
DetourDetach(&v_Host_Shutdown, &Host_Shutdown);
DetourDetach(&v_Host_Status_PrintClient, &Host_Status_PrintClient);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
DetourDetach(&v_DFS_InitializeFeatureFlagDefinitions, &DFS_InitializeFeatureFlagDefinitions);
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2)
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -18,31 +18,17 @@ struct EngineParms_t
extern EngineParms_t* g_pEngineParms; extern EngineParms_t* g_pEngineParms;
/* ==== HOST ============================================================================================================================================================ */ /* ==== HOST ============================================================================================================================================================ */
inline CMemory p_Host_Init; inline void(*v_Host_Init)();
inline void*(*v_Host_Init)(bool* bDedicated); inline void(*v_Host_Init_DuringVideo)(bool* bDedicated);
inline void(*v_Host_Init_PostVideo)(bool* bDedicated);
inline CMemory p_Host_Shutdown;
inline void(*v_Host_Shutdown)(); inline void(*v_Host_Shutdown)();
inline CMemory p_Host_NewGame;
inline bool(*v_Host_NewGame)(char* pszMapName, char* pszMapGroup, bool bLoadGame, char bBackground, LARGE_INTEGER PerformanceCount); inline bool(*v_Host_NewGame)(char* pszMapName, char* pszMapGroup, bool bLoadGame, char bBackground, LARGE_INTEGER PerformanceCount);
inline CMemory p_Host_Disconnect;
inline void(*v_Host_Disconnect)(bool bShowMainMenu); inline void(*v_Host_Disconnect)(bool bShowMainMenu);
inline CMemory p_Host_ChangeLevel;
inline bool(*v_Host_ChangeLevel)(bool bLoadFromSavedGame, const char* pszMapName, const char* pszMapGroup); inline bool(*v_Host_ChangeLevel)(bool bLoadFromSavedGame, const char* pszMapName, const char* pszMapGroup);
inline CMemory p_Host_Status_PrintClient;
inline void (*v_Host_Status_PrintClient)(CClient* client, bool bShowAddress, void (*print) (const char* fmt, ...)); inline void (*v_Host_Status_PrintClient)(CClient* client, bool bShowAddress, void (*print) (const char* fmt, ...));
inline CMemory p_SetLaunchOptions;
inline int(*v_SetLaunchOptions)(const CCommand& args); inline int(*v_SetLaunchOptions)(const CCommand& args);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
inline CMemory p_DFS_InitializeFeatureFlagDefinitions;
inline bool(*v_DFS_InitializeFeatureFlagDefinitions)(const char* pszFeatureFlags); inline bool(*v_DFS_InitializeFeatureFlagDefinitions)(const char* pszFeatureFlags);
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2)
extern EngineParms_t* g_pEngineParms; extern EngineParms_t* g_pEngineParms;
@ -51,57 +37,39 @@ class VHostCmd : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("Host_Init", p_Host_Init.GetPtr()); LogFunAdr("Host_Init", v_Host_Init);
LogFunAdr("Host_Shutdown", p_Host_Shutdown.GetPtr()); LogFunAdr("Host_Init_DuringVideo", v_Host_Init_DuringVideo);
LogFunAdr("Host_Disconnect", p_Host_Disconnect.GetPtr()); LogFunAdr("Host_Init_PostVideo", v_Host_Init_PostVideo);
LogFunAdr("Host_NewGame", p_Host_NewGame.GetPtr()); LogFunAdr("Host_Shutdown", v_Host_Shutdown);
LogFunAdr("Host_ChangeLevel", p_Host_ChangeLevel.GetPtr()); LogFunAdr("Host_Disconnect", v_Host_Disconnect);
LogFunAdr("Host_Status_PrintClient", p_Host_Status_PrintClient.GetPtr()); LogFunAdr("Host_NewGame", v_Host_NewGame);
LogFunAdr("SetLaunchOptions", p_SetLaunchOptions.GetPtr()); LogFunAdr("Host_ChangeLevel", v_Host_ChangeLevel);
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2) LogFunAdr("Host_Status_PrintClient", v_Host_Status_PrintClient);
LogFunAdr("DFS_InitializeFeatureFlagDefinitions", p_DFS_InitializeFeatureFlagDefinitions.GetPtr()); LogFunAdr("SetLaunchOptions", v_SetLaunchOptions);
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2)
LogVarAdr("g_pEngineParms", reinterpret_cast<uintptr_t>(g_pEngineParms)); LogFunAdr("DFS_InitializeFeatureFlagDefinitions", v_DFS_InitializeFeatureFlagDefinitions);
LogVarAdr("g_pEngineParms", g_pEngineParms);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("88 4C 24 08 53 55 56 57 48 83 EC 68").GetPtr(v_Host_Init);
p_Host_Init = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8B D9 FF 15 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9").GetPtr(v_Host_Init_DuringVideo);
p_Host_NewGame = g_GameDll.FindPatternSIMD("48 8B C4 56 41 54 41 57 48 81 EC ?? ?? ?? ?? F2 0F 10 05 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 8B C4 ?? 41 54 41 55 48 81 EC 70 04 ?? ?? F2 0F 10 05 ?? ?? ?? 0B").GetPtr(v_Host_NewGame);
p_Host_Disconnect = g_GameDll.FindPatternSIMD("48 83 EC 38 48 89 7C 24 ?? 0F B6 F9"); g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 0F B6 D9").GetPtr(v_Host_Disconnect);
p_Host_ChangeLevel = g_GameDll.FindPatternSIMD("40 53 56 41 56 48 81 EC ?? ?? ?? ?? 49 8B D8"); g_GameDll.FindPatternSIMD("40 56 57 41 56 48 81 EC ?? ?? ?? ??").GetPtr(v_Host_ChangeLevel);
p_SetLaunchOptions = g_GameDll.FindPatternSIMD("48 89 6C 24 ?? 57 48 83 EC 20 48 8B E9 48 8B 0D ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 8B C4 41 56 48 81 EC ?? ?? ?? ?? 45 33 F6").GetPtr(v_Host_Init_PostVideo);
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) g_GameDll.FindPatternSIMD("48 8B C4 48 83 EC ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? 8B 15 ?? ?? ?? ??").GetPtr(v_Host_Shutdown);
p_Host_Init = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 60 48 8B A9 ?? ?? ?? ??").GetPtr(v_Host_Status_PrintClient);
p_Host_NewGame = g_GameDll.FindPatternSIMD("48 8B C4 ?? 41 54 41 55 48 81 EC 70 04 ?? ?? F2 0F 10 05 ?? ?? ?? 0B");
p_Host_Disconnect = g_GameDll.FindPatternSIMD("40 53 48 83 EC 30 0F B6 D9"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 83 EC 20 48 8B 1D ?? ?? ?? ?? 48 8B E9 48 85 DB").GetPtr(v_SetLaunchOptions);
p_Host_ChangeLevel = g_GameDll.FindPatternSIMD("40 56 57 41 56 48 81 EC ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 40 38 3D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B CE").FollowNearCallSelf().GetPtr(v_DFS_InitializeFeatureFlagDefinitions);
p_SetLaunchOptions = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 83 EC 20 48 8B 1D ?? ?? ?? ?? 48 8B E9 48 85 DB");
#endif
p_Host_Shutdown = g_GameDll.FindPatternSIMD("48 8B C4 48 83 EC ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ?? 8B 15 ?? ?? ?? ??");
p_Host_Status_PrintClient = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 60 48 8B A9 ?? ?? ?? ??");
#if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) && !defined (GAMEDLL_S2)
p_DFS_InitializeFeatureFlagDefinitions = g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 40 38 3D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B CE").FollowNearCallSelf();
v_DFS_InitializeFeatureFlagDefinitions = p_DFS_InitializeFeatureFlagDefinitions.RCast<bool (*)(const char*)>(); /*48 8B C4 55 53 48 8D 68 E8*/
#endif // !(GAMEDLL_S0) || !(GAMEDLL_S1) || !(GAMEDLL_S2)
v_Host_Init = p_Host_Init.RCast<void* (*)(bool*)>(); /*48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9*/
v_Host_Shutdown = p_Host_Shutdown.RCast<void (*)()>();
v_Host_NewGame = p_Host_NewGame.RCast<bool (*)(char*, char*, bool, char, LARGE_INTEGER)>(); /*48 8B C4 ?? 41 54 41 55 48 81 EC 70 04 00 00 F2 0F 10 05 ?? ?? ?? 0B*/
v_Host_Disconnect = p_Host_Disconnect.RCast<void (*)(bool)>();
v_Host_ChangeLevel = p_Host_ChangeLevel.RCast<bool (*)(bool, const char*, const char*)>(); /*40 56 57 41 56 48 81 EC ?? ?? ?? ??*/
v_Host_Status_PrintClient = p_Host_Status_PrintClient.RCast<void (*)(CClient*, bool, void (*) (const char*, ...))>();
v_SetLaunchOptions = p_SetLaunchOptions.RCast<int (*)(const CCommand&)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 83 EC 20 48 8B 1D ?? ?? ?? ?? 48 8B E9 48 85 DB*/
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_pEngineParms = CMemory(CModAppSystemGroup__Main).FindPattern("48 8B", CMemory::Direction::DOWN, 100).ResolveRelativeAddress(0x3, 0x7).RCast<EngineParms_t*>();
g_pEngineParms = p_CModAppSystemGroup_Main.FindPattern("48 8B", CMemory::Direction::DOWN, 100).ResolveRelativeAddress(0x3, 0x7).RCast<EngineParms_t*>(); g_pEngineParms = CMemory(CModAppSystemGroup__Main).FindPattern("4C 8B", CMemory::Direction::DOWN, 100).ResolveRelativeAddress(0x3, 0x7).RCast<EngineParms_t*>();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
g_pEngineParms = p_CModAppSystemGroup_Main.FindPattern("4C 8B", CMemory::Direction::DOWN, 100).ResolveRelativeAddress(0x3, 0x7).RCast<EngineParms_t*>();
#endif
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -10,10 +10,10 @@
#include "tier0/jobthread.h" #include "tier0/jobthread.h"
#include "tier0/commandline.h" #include "tier0/commandline.h"
#include "tier0/fasttimer.h" #include "tier0/fasttimer.h"
#include "tier0/frametask.h"
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "tier1/NetAdr.h" #include "tier1/NetAdr.h"
#include "tier2/socketcreator.h" #include "tier2/socketcreator.h"
#include "vpc/keyvalues.h"
#include "datacache/mdlcache.h" #include "datacache/mdlcache.h"
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
#include "engine/server/sv_rcon.h" #include "engine/server/sv_rcon.h"
@ -35,17 +35,19 @@
#include "engine/cmodel_bsp.h" #include "engine/cmodel_bsp.h"
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
#include "engine/server/server.h" #include "engine/server/server.h"
#include "rtech/liveapi/liveapi.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
#include "rtech/rtech_game.h"
#include "rtech/rtech_utils.h"
#include "rtech/stryder/stryder.h" #include "rtech/stryder/stryder.h"
#include "rtech/playlists/playlists.h"
#ifndef DEDICATED #ifndef DEDICATED
#include "vgui/vgui_baseui_interface.h" #include "vgui/vgui_baseui_interface.h"
#include "client/vengineclient_impl.h" #include "client/vengineclient_impl.h"
#include "gameui/imgui_system.h"
#endif // DEDICATED #endif // DEDICATED
#include "networksystem/pylon.h" #include "networksystem/pylon.h"
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
#include "networksystem/bansystem.h" #include "networksystem/bansystem.h"
#include "networksystem/hostmanager.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
#include "networksystem/listmanager.h" #include "networksystem/listmanager.h"
#include "public/edict.h" #include "public/edict.h"
@ -55,44 +57,84 @@
#include "game/shared/vscript_shared.h" #include "game/shared/vscript_shared.h"
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
static ConVar sv_pylonVisibility("sv_pylonVisibility", "0", FCVAR_RELEASE, "Determines the visibility to the Pylon master server.", "0 = Offline, 1 = Hidden, 2 = Public.");
static ConVar sv_pylonRefreshRate("sv_pylonRefreshRate", "5.0", FCVAR_DEVELOPMENTONLY, "Pylon host refresh rate (seconds).");
static ConVar sv_autoReloadRate("sv_autoReloadRate", "0", FCVAR_RELEASE, "Time in seconds between each server auto-reload (disabled if null).");
#endif // !CLIENT_DLL
#ifdef DEDICATED
static ConVar hostdesc("hostdesc", "", FCVAR_RELEASE, "Host game server description.");
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Send keep alive request to Pylon Master Server. // Purpose: Send keep alive request to Pylon Master Server.
// Input : &netGameServer -
// Output : Returns true on success, false otherwise. // Output : Returns true on success, false otherwise.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool HostState_KeepAlive(const NetGameServer_t& netGameServer) static void HostState_KeepAlive()
{ {
if (!g_pServer->IsActive() || !sv_pylonVisibility->GetBool()) // Check for active game. if (!g_pServer->IsActive() || !sv_pylonVisibility.GetBool()) // Check for active game.
{ {
return false; return;
} }
string errorMsg; const NetGameServer_t gameServer
string hostToken;
const bool result = g_pMasterServer->PostServerHost(errorMsg, hostToken, netGameServer);
if (!result)
{ {
if (!errorMsg.empty() && g_pMasterServer->GetCurrentError().compare(errorMsg) != NULL) hostname->GetString(),
hostdesc.GetString(),
sv_pylonVisibility.GetInt() == ServerVisibility_e::HIDDEN,
g_pHostState->m_levelName,
v_Playlists_GetCurrent(),
hostip->GetString(),
hostport->GetInt(),
g_pNetKey->GetBase64NetKey(),
*g_nServerRemoteChecksum,
SDK_VERSION,
g_pServer->GetNumClients(),
g_ServerGlobalVariables->m_nMaxClients,
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count()
};
std::thread request([&, gameServer]
{ {
g_pMasterServer->SetCurrentError(errorMsg); string errorMsg;
Error(eDLL_T::SERVER, NO_ERROR, "%s\n", errorMsg.c_str()); string hostToken;
} string hostIp;
}
else // Attempt to log the token, if there is one.
{
if (!hostToken.empty() && g_pMasterServer->GetCurrentToken().compare(hostToken) != NULL)
{
g_pMasterServer->SetCurrentToken(hostToken);
DevMsg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n",
g_svReset, g_svGreyB,
hostToken.c_str(), g_svReset);
}
}
return result; const bool result = g_MasterServer.PostServerHost(errorMsg, hostToken, hostIp, gameServer);
// Apply the data the next frame
g_TaskQueue.Dispatch([result, errorMsg, hostToken, hostIp]
{
if (!result)
{
if (!errorMsg.empty() && g_ServerHostManager.GetCurrentError().compare(errorMsg) != NULL)
{
g_ServerHostManager.SetCurrentError(errorMsg);
Error(eDLL_T::SERVER, NO_ERROR, "%s\n", errorMsg.c_str());
}
}
else // Attempt to log the token, if there is one.
{
if (!hostToken.empty() && g_ServerHostManager.GetCurrentToken().compare(hostToken) != NULL)
{
g_ServerHostManager.SetCurrentToken(hostToken);
Msg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n",
g_svReset, g_svGreyB,
hostToken.c_str(), g_svReset);
}
}
if (hostIp.length() != 0)
g_ServerHostManager.SetHostIP(hostIp);
}, 0);
}
);
request.detach();
} }
#endif // !CLIENT_DLL #endif // DEDICATED
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: state machine's main processing loop // Purpose: state machine's main processing loop
@ -115,8 +157,6 @@ void CHostState::FrameUpdate(CHostState* pHostState, double flCurrentTime, float
RCONClient()->RunFrame(); RCONClient()->RunFrame();
#endif // !DEDICATED #endif // !DEDICATED
HostStates_t oldState{};
// Disable "warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable" // Disable "warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable"
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4611) #pragma warning(disable : 4611)
@ -131,11 +171,11 @@ void CHostState::FrameUpdate(CHostState* pHostState, double flCurrentTime, float
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
*g_bAbortServerSet = true; *g_bAbortServerSet = true;
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
do while (true)
{ {
Cbuf_Execute(); Cbuf_Execute();
oldState = g_pHostState->m_iCurrentState;
const HostStates_t oldState = g_pHostState->m_iCurrentState;
switch (g_pHostState->m_iCurrentState) switch (g_pHostState->m_iCurrentState)
{ {
case HostStates_t::HS_NEW_GAME: case HostStates_t::HS_NEW_GAME:
@ -168,32 +208,32 @@ void CHostState::FrameUpdate(CHostState* pHostState, double flCurrentTime, float
bResetIdleName = true; bResetIdleName = true;
} }
CHostState_State_Run(&g_pHostState->m_iCurrentState, flCurrentTime, flFrameTime); CHostState__State_Run(&g_pHostState->m_iCurrentState, flCurrentTime, flFrameTime);
break; break;
} }
case HostStates_t::HS_GAME_SHUTDOWN: case HostStates_t::HS_GAME_SHUTDOWN:
{ {
DevMsg(eDLL_T::ENGINE, "%s: Shutdown host game\n", __FUNCTION__); Msg(eDLL_T::ENGINE, "%s: Shutdown host game\n", __FUNCTION__);
CHostState_State_GameShutDown(g_pHostState); CHostState__State_GameShutDown(g_pHostState);
break; break;
} }
case HostStates_t::HS_RESTART: case HostStates_t::HS_RESTART:
{ {
DevMsg(eDLL_T::ENGINE, "%s: Restarting state machine\n", __FUNCTION__); Msg(eDLL_T::ENGINE, "%s: Restarting state machine\n", __FUNCTION__);
#ifndef DEDICATED #ifndef DEDICATED
CL_EndMovie(); v_CL_EndMovie();
#endif // !DEDICATED #endif // !DEDICATED
Stryder_SendOfflineRequest(); // We have hostnames nulled anyway. v_Stryder_SendOfflineRequest(); // We have hostnames nulled anyway.
g_pEngine->SetNextState(IEngine::DLL_RESTART); g_pEngine->SetNextState(IEngine::DLL_RESTART);
break; break;
} }
case HostStates_t::HS_SHUTDOWN: case HostStates_t::HS_SHUTDOWN:
{ {
DevMsg(eDLL_T::ENGINE, "%s: Shutdown state machine\n", __FUNCTION__); Msg(eDLL_T::ENGINE, "%s: Shutdown state machine\n", __FUNCTION__);
#ifndef DEDICATED #ifndef DEDICATED
CL_EndMovie(); v_CL_EndMovie();
#endif // !DEDICATED #endif // !DEDICATED
Stryder_SendOfflineRequest(); // We have hostnames nulled anyway. v_Stryder_SendOfflineRequest(); // We have hostnames nulled anyway.
g_pEngine->SetNextState(IEngine::DLL_CLOSE); g_pEngine->SetNextState(IEngine::DLL_CLOSE);
break; break;
} }
@ -203,10 +243,15 @@ void CHostState::FrameUpdate(CHostState* pHostState, double flCurrentTime, float
} }
} }
} while ( // only do a single pass at HS_RUN per frame. All other states loop until they reach HS_RUN
(oldState != HostStates_t::HS_RUN || g_pHostState->m_iNextState == HostStates_t::HS_LOAD_GAME && single_frame_shutdown_for_reload->GetBool()) if (oldState == HostStates_t::HS_RUN && (g_pHostState->m_iNextState != HostStates_t::HS_LOAD_GAME || !single_frame_shutdown_for_reload->GetBool()))
&& oldState != HostStates_t::HS_SHUTDOWN break;
&& oldState != HostStates_t::HS_RESTART);
// shutting down
if (oldState == HostStates_t::HS_SHUTDOWN ||
oldState == HostStates_t::HS_RESTART)
break;
}
} }
} }
@ -219,7 +264,7 @@ void CHostState::Init(void)
{ {
if (m_iNextState == HostStates_t::HS_GAME_SHUTDOWN) if (m_iNextState == HostStates_t::HS_GAME_SHUTDOWN)
{ {
CHostState_State_GameShutDown(this); CHostState__State_GameShutDown(this);
} }
else else
{ {
@ -250,7 +295,7 @@ void CHostState::Setup(void)
{ {
g_pHostState->LoadConfig(); g_pHostState->LoadConfig();
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
g_pBanSystem->Load(); g_BanSystem.LoadList();
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
ConVar_PurgeHostNames(); ConVar_PurgeHostNames();
@ -261,7 +306,11 @@ void CHostState::Setup(void)
RCONClient()->Init(); RCONClient()->Init();
#endif // !DEDICATED #endif // !DEDICATED
if (net_useRandomKey->GetBool()) #ifndef CLIENT_DLL
LiveAPISystem()->Init();
#endif // !CLIENT_DLL
if (net_useRandomKey.GetBool())
{ {
NET_GenerateKey(); NET_GenerateKey();
} }
@ -301,50 +350,33 @@ void CHostState::Think(void) const
#endif // DEDICATED #endif // DEDICATED
bInitialized = true; bInitialized = true;
} }
if (sv_autoReloadRate->GetBool()) if (sv_autoReloadRate.GetBool())
{ {
if (g_ServerGlobalVariables->m_flCurTime > sv_autoReloadRate->GetDouble()) if (g_ServerGlobalVariables->m_flCurTime > sv_autoReloadRate.GetFloat())
{ {
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "reload\n", cmd_source_t::kCommandSrcCode); Cbuf_AddText(Cbuf_GetCurrentPlayer(), "reload\n", cmd_source_t::kCommandSrcCode);
} }
} }
if (statsTimer.GetDurationInProgress().GetSeconds() > sv_statusRefreshRate->GetDouble()) if (statsTimer.GetDurationInProgress().GetSeconds() > sv_statusRefreshRate.GetFloat())
{ {
SetConsoleTitleA(Format("%s - %d/%d Players (%s on %s)", SetConsoleTitleA(Format("%s - %d/%d Players (%s on %s) - %d%% Server CPU (%.3f msec on frame %d)",
hostname->GetString(), g_pServer->GetNumClients(), hostname->GetString(), g_pServer->GetNumClients(),
g_ServerGlobalVariables->m_nMaxClients, KeyValues_GetCurrentPlaylist(), m_levelName).c_str()); g_ServerGlobalVariables->m_nMaxClients, v_Playlists_GetCurrent(), m_levelName,
static_cast<int>(g_pServer->GetCPUUsage() * 100.0f), (g_pEngine->GetFrameTime() * 1000.0f),
g_pServer->GetTick()).c_str());
statsTimer.Start(); statsTimer.Start();
} }
if (sv_globalBanlist->GetBool() && if (sv_globalBanlist.GetBool() &&
banListTimer.GetDurationInProgress().GetSeconds() > sv_banlistRefreshRate->GetDouble()) banListTimer.GetDurationInProgress().GetSeconds() > sv_banlistRefreshRate.GetFloat())
{ {
SV_CheckForBan(); SV_CheckClientsForBan();
banListTimer.Start(); banListTimer.Start();
} }
#ifdef DEDICATED #ifdef DEDICATED
if (pylonTimer.GetDurationInProgress().GetSeconds() > sv_pylonRefreshRate->GetDouble()) if (pylonTimer.GetDurationInProgress().GetSeconds() > sv_pylonRefreshRate.GetFloat())
{ {
const NetGameServer_t netGameServer HostState_KeepAlive();
{
hostname->GetString(),
hostdesc->GetString(),
sv_pylonVisibility->GetInt() == EServerVisibility_t::HIDDEN,
g_pHostState->m_levelName,
KeyValues_GetCurrentPlaylist(),
hostip->GetString(),
hostport->GetString(),
g_pNetKey->GetBase64NetKey(),
std::to_string(*g_nServerRemoteChecksum),
SDK_VERSION,
std::to_string(g_pServer->GetNumClients()),
std::to_string(g_ServerGlobalVariables->m_nMaxClients),
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count()
};
std::thread(&HostState_KeepAlive, netGameServer).detach();
pylonTimer.Start(); pylonTimer.Start();
} }
#endif // DEDICATED #endif // DEDICATED
@ -388,6 +420,24 @@ void CHostState::LoadConfig(void) const
} }
} }
//-----------------------------------------------------------------------------
// Purpose: set state machine
// Input : newState -
// clearNext -
//-----------------------------------------------------------------------------
void CHostState::SetState(const HostStates_t newState)
{
m_iCurrentState = newState;
// If our next state isn't a shutdown, or its a forced shutdown then set
// next state to run.
if (m_iNextState != HostStates_t::HS_SHUTDOWN ||
!host_hasIrreversibleShutdown->GetBool())
{
m_iNextState = newState;
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: shutdown active game // Purpose: shutdown active game
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -408,13 +458,13 @@ void CHostState::GameShutDown(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CHostState::State_NewGame(void) void CHostState::State_NewGame(void)
{ {
DevMsg(eDLL_T::ENGINE, "%s: Loading level: '%s'\n", __FUNCTION__, g_pHostState->m_levelName); Msg(eDLL_T::ENGINE, "%s: Loading level: '%s'\n", __FUNCTION__, g_pHostState->m_levelName);
LARGE_INTEGER time{}; LARGE_INTEGER time{};
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
bool bSplitScreenConnect = m_bSplitScreenConnect; const bool bSplitScreenConnect = m_bSplitScreenConnect;
m_bSplitScreenConnect = 0; m_bSplitScreenConnect = false;
if (!g_pServerGameClients) // Init Game if it ain't valid. if (!g_pServerGameClients) // Init Game if it ain't valid.
{ {
@ -434,13 +484,7 @@ void CHostState::State_NewGame(void)
} }
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run. SetState(HostStates_t::HS_RUN);
// If our next state isn't a shutdown or its a forced shutdown then set next state to run.
if (m_iNextState != HostStates_t::HS_SHUTDOWN || !host_hasIrreversibleShutdown->GetBool())
{
m_iNextState = HostStates_t::HS_RUN;
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -448,7 +492,7 @@ void CHostState::State_NewGame(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CHostState::State_ChangeLevelSP(void) void CHostState::State_ChangeLevelSP(void)
{ {
DevMsg(eDLL_T::ENGINE, "%s: Changing singleplayer level to: '%s'\n", __FUNCTION__, m_levelName); Msg(eDLL_T::ENGINE, "%s: Changing singleplayer level to: '%s'\n", __FUNCTION__, m_levelName);
m_flShortFrameTime = 1.5; // Set frame time. m_flShortFrameTime = 1.5; // Set frame time.
if (CModelLoader__Map_IsValid(g_pModelLoader, m_levelName)) // Check if map is valid and if we can start a new game. if (CModelLoader__Map_IsValid(g_pModelLoader, m_levelName)) // Check if map is valid and if we can start a new game.
@ -460,13 +504,8 @@ void CHostState::State_ChangeLevelSP(void)
Error(eDLL_T::ENGINE, NO_ERROR, "%s: Unable to find level: '%s'\n", __FUNCTION__, m_levelName); Error(eDLL_T::ENGINE, NO_ERROR, "%s: Unable to find level: '%s'\n", __FUNCTION__, m_levelName);
} }
m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run. // Set current state to run.
SetState(HostStates_t::HS_RUN);
// If our next state isn't a shutdown or its a forced shutdown then set next state to run.
if (m_iNextState != HostStates_t::HS_SHUTDOWN || !host_hasIrreversibleShutdown->GetBool())
{
m_iNextState = HostStates_t::HS_RUN;
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -474,7 +513,7 @@ void CHostState::State_ChangeLevelSP(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CHostState::State_ChangeLevelMP(void) void CHostState::State_ChangeLevelMP(void)
{ {
DevMsg(eDLL_T::ENGINE, "%s: Changing multiplayer level to: '%s'\n", __FUNCTION__, m_levelName); Msg(eDLL_T::ENGINE, "%s: Changing multiplayer level to: '%s'\n", __FUNCTION__, m_levelName);
m_flShortFrameTime = 0.5; // Set frame time. m_flShortFrameTime = 0.5; // Set frame time.
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
@ -492,13 +531,8 @@ void CHostState::State_ChangeLevelMP(void)
Error(eDLL_T::ENGINE, NO_ERROR, "%s: Unable to find level: '%s'\n", __FUNCTION__, m_levelName); Error(eDLL_T::ENGINE, NO_ERROR, "%s: Unable to find level: '%s'\n", __FUNCTION__, m_levelName);
} }
m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run. // Set current state to run.
SetState(HostStates_t::HS_RUN);
// If our next state isn't a shutdown or its a forced shutdown then set next state to run.
if (m_iNextState != HostStates_t::HS_SHUTDOWN || !host_hasIrreversibleShutdown->GetBool())
{
m_iNextState = HostStates_t::HS_RUN;
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -510,13 +544,9 @@ void CHostState::ResetLevelName(void)
Q_snprintf(const_cast<char*>(m_levelName), sizeof(m_levelName), "%s", szNoMap); Q_snprintf(const_cast<char*>(m_levelName), sizeof(m_levelName), "%s", szNoMap);
} }
void VHostState::Attach(void) const void VHostState::Detour(const bool bAttach) const
{ {
DetourAttach(&CHostState_FrameUpdate, &CHostState::FrameUpdate); DetourSetup(&CHostState__FrameUpdate, &CHostState::FrameUpdate, bAttach);
}
void VHostState::Detach(void) const
{
DetourDetach(&CHostState_FrameUpdate, &CHostState::FrameUpdate);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -23,9 +23,10 @@ public:
void Setup(void); void Setup(void);
void Think(void) const; void Think(void) const;
void SetState(const HostStates_t newState);
void GameShutDown(void); void GameShutDown(void);
void State_NewGame(void);
void State_NewGame(void);
void State_ChangeLevelSP(void); void State_ChangeLevelSP(void);
void State_ChangeLevelMP(void); void State_ChangeLevelMP(void);
@ -50,16 +51,9 @@ public:
}; };
/* ==== CHOSTSTATE ====================================================================================================================================================== */ /* ==== CHOSTSTATE ====================================================================================================================================================== */
inline CMemory p_CHostState_FrameUpdate; inline void(*CHostState__FrameUpdate)(CHostState* pHostState, double flCurrentTime, float flFrameTime);
inline void(*CHostState_FrameUpdate)(CHostState* pHostState, double flCurrentTime, float flFrameTime); inline void(*CHostState__State_Run)(HostStates_t* pState, double flCurrentTime, float flFrameTime);
inline void(*CHostState__State_GameShutDown)(CHostState* thisptr);
inline CMemory p_CHostState_State_Run;
inline void(*CHostState_State_Run)(HostStates_t* pState, double flCurrentTime, float flFrameTime);
inline CMemory p_CHostState_State_GameShutDown;
inline void(*CHostState_State_GameShutDown)(CHostState* thisptr);
inline CMemory p_HostState_ChangeLevelMP;
inline void(*v_HostState_ChangeLevelMP)(char const* pNewLevel, char const* pLandmarkName); inline void(*v_HostState_ChangeLevelMP)(char const* pNewLevel, char const* pLandmarkName);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -70,36 +64,24 @@ class VHostState : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CHostState::FrameUpdate", p_CHostState_FrameUpdate.GetPtr()); LogFunAdr("CHostState::FrameUpdate", CHostState__FrameUpdate);
LogFunAdr("CHostState::State_Run", p_CHostState_State_Run.GetPtr()); LogFunAdr("CHostState::State_Run", CHostState__State_Run);
LogFunAdr("CHostState::State_GameShutDown", p_CHostState_State_GameShutDown.GetPtr()); LogFunAdr("CHostState::State_GameShutDown", CHostState__State_GameShutDown);
LogFunAdr("HostState_ChangeLevelMP", p_HostState_ChangeLevelMP.GetPtr()); LogFunAdr("HostState_ChangeLevelMP", v_HostState_ChangeLevelMP);
LogVarAdr("g_pHostState", reinterpret_cast<uintptr_t>(g_pHostState)); LogVarAdr("g_pHostState", g_pHostState);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_CHostState_FrameUpdate = g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 20 F3 0F 11 54 24 18"); g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 20 F3 0F 11 54 24 18").GetPtr(CHostState__FrameUpdate);
p_CHostState_State_Run = g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D A8 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 0F 29 70 C8 45 33 E4"); g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D A8 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 0F 29 70 C8 45 33 E4").GetPtr(CHostState__State_Run);
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B D9 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ??").GetPtr(CHostState__State_GameShutDown);
p_CHostState_State_GameShutDown = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 56 48 83 EC 20 8B 05 ?? ?? ?? ?? 48 8B F1"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 48 8B F2 8B 0D ?? ?? ?? ??").GetPtr(v_HostState_ChangeLevelMP);
#elif defined (GAMEDLL_S2)
p_CHostState_State_GameShutDown = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 8B 05 ?? ?? ?? ?? 33 FF 48 8B F1");
#elif defined (GAMEDLL_S3)
p_CHostState_State_GameShutDown = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B D9 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ??");
#endif
p_HostState_ChangeLevelMP = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 48 8B F2 8B 0D ?? ?? ?? ??");
CHostState_FrameUpdate = p_CHostState_FrameUpdate.RCast<void(*)(CHostState*, double, float)>(); /*48 89 5C 24 08 48 89 6C 24 20 F3 0F 11 54 24 18*/
CHostState_State_Run = p_CHostState_State_Run.RCast<void(*)(HostStates_t*, double, float)>(); /*48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D A8 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 0F 29 70 C8 45 33 E4*/
CHostState_State_GameShutDown = p_CHostState_State_GameShutDown.RCast<void(*)(CHostState* thisptr)>(); /*48 89 5C 24 ?? 57 48 83 EC 20 48 8B D9 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ??*/
v_HostState_ChangeLevelMP = p_HostState_ChangeLevelMP.RCast<void(*)(char const*, char const*)>(); /*48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B F9 48 8B F2 8B 0D ? ? ? ?*/
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
g_pHostState = p_CHostState_FrameUpdate.FindPattern("48 8D ?? ?? ?? ?? 01", CMemory::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CHostState*>(); g_pHostState = CMemory(CHostState__FrameUpdate).FindPattern("48 8D ?? ?? ?? ?? 01", CMemory::Direction::DOWN, 100).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CHostState*>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

36
r5dev/engine/keys.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "keys.h"
#include "windows/id3dx.h"
#include "geforce/reflex.h"
#include <materialsystem/cmaterialsystem.h>
KeyInfo_t* g_pKeyInfo = nullptr;
ButtonCode_t* g_pKeyEventTicks = nullptr;
short* g_nKeyEventCount = nullptr;
bool Input_Event(const InputEvent_t& inputEvent, const int noKeyUpCheck)
{
bool runTriggerMarker = inputEvent.m_nData == ButtonCode_t::MOUSE_LEFT;
const KeyInfo_t& keyInfo = g_pKeyInfo[inputEvent.m_nData];
if (noKeyUpCheck)
{
const int v = (inputEvent.m_nType & 0xFFFFFFFD) == 0;
if (keyInfo.m_nKeyDownTarget == v)
runTriggerMarker = false;
}
if (runTriggerMarker && (inputEvent.m_nType != IE_ButtonReleased || keyInfo.m_bTrapKeyUp))
{
GFX_SetLatencyMarker(D3D11Device(), TRIGGER_FLASH, MaterialSystem()->GetCurrentFrameCount());
}
return v_Input_Event(inputEvent, noKeyUpCheck);
}
///////////////////////////////////////////////////////////////////////////////
void VKeys::Detour(const bool bAttach) const
{
DetourSetup(&v_Input_Event, &Input_Event, bAttach);
}

81
r5dev/engine/keys.h Normal file
View File

@ -0,0 +1,81 @@
#ifndef ENGINE_KEYS_H
#define ENGINE_KEYS_H
#include "inputsystem/ButtonCode.h"
//-----------------------------------------------------------------------------
// Keypress event
//-----------------------------------------------------------------------------
struct KeyEvent_t
{
const char* m_pCommand;
int m_nTick;
bool m_bDown;
};
//-----------------------------------------------------------------------------
// Current keypress state
//-----------------------------------------------------------------------------
struct KeyInfo_t
{
enum
{
KEY_TAPPED_BIND = 0,
KEY_HELD_BIND,
KEY_BIND_COUNT
};
const char* m_pKeyBinding[KEY_BIND_COUNT];
int m_nKeyUpTarget;
int m_nKeyDownTarget;
uint32_t m_nEventTick; // When was the event issued?
int unknown;
short m_nEventNumber; // The event number.
bool m_bKeyDown;
bool m_bEventIsButtonKey; // Is the event a button key (< ButtonCode_t::KEY_LAST)
bool m_bTrapKeyUp;
bool m_bBoundSecondKey; // Is the key bound to the second row?
short paddingMaybe;
};
inline bool (*v_Input_Event)(const InputEvent_t& inputEvent, const int noKeyUpCheck);
inline bool(*v_Key_Event)(const KeyEvent_t& keyEvent);
extern KeyInfo_t* g_pKeyInfo; // ARRAYSIZE = ButtonCode_t::BUTTON_CODE_LAST
extern ButtonCode_t* g_pKeyEventTicks; // ARRAYSIZE = ButtonCode_t::BUTTON_CODE_LAST
extern short* g_nKeyEventCount;
class VKeys : public IDetour
{
virtual void GetAdr(void) const
{
LogFunAdr("Input_Event", v_Input_Event);
LogFunAdr("Key_Event", v_Key_Event);
LogVarAdr("g_pKeyInfo", g_pKeyInfo);
LogVarAdr("g_pKeyEventTicks", g_pKeyEventTicks);
LogVarAdr("g_nKeyEventCount", g_nKeyEventCount);
}
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 56").GetPtr(v_Input_Event);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 4C 63 41 08").GetPtr(v_Key_Event);
}
virtual void GetVar(void) const
{
g_pKeyInfo = g_GameDll.FindPatternSIMD("48 83 EC 28 33 D2 48 8D 0D ?? ?? ?? ?? 41 B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 C0 C6 05 ?? ?? ?? ?? ??")
.FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 40).ResolveRelativeAddressSelf(3, 7).RCast<KeyInfo_t*>();
CMemory l_EngineApi_PumpMessages = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 48 81 EC ?? ?? ?? ?? 45 33 C9");
// NOTE: g_nKeyEventCount's pattern is found earlier, thus searched for earlier to offset base for g_pKeyEventTicks.
g_nKeyEventCount = l_EngineApi_PumpMessages.FindPatternSelf("0F B7 15").ResolveRelativeAddressSelf(3, 7).RCast<short*>();
g_pKeyEventTicks = l_EngineApi_PumpMessages.FindPatternSelf("48 8D 35").ResolveRelativeAddressSelf(3, 7).RCast<ButtonCode_t*>();
}
virtual void GetCon(void) const { }
virtual void Detour(const bool bAttach) const;
};
#endif // ENGINE_KEYS_H

View File

@ -26,12 +26,7 @@ bool UpdateCurrentVideoConfig(MaterialSystem_Config_t* pConfig)
*/ */
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VMatSys_Interface::Attach() const void VMatSys_Interface::Detour(const bool bAttach) const
{ {
//DetourAttach(&v_UpdateCurrentVideoConfig, &UpdateCurrentVideoConfig); //DetourSetup(&v_UpdateCurrentVideoConfig, &UpdateCurrentVideoConfig, bAttach);
} }
void VMatSys_Interface::Detach() const
{
//DetourDetach(&v_UpdateCurrentVideoConfig, &UpdateCurrentVideoConfig);
}

View File

@ -2,17 +2,16 @@
#define MATSYS_INTERFACE_H #define MATSYS_INTERFACE_H
#include "public/imaterialsystem.h" #include "public/imaterialsystem.h"
#include "public/inputsystem/ButtonCode.h"
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: GAME_CFG // RUNTIME: GAME_CFG
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
inline CMemory p_UpdateCurrentVideoConfig; inline void(*v_UpdateMaterialSystemConfig)(void);
inline CMemory p_UpdateMaterialSystemConfig; inline bool(*v_UpdateCurrentVideoConfig)(MaterialSystem_Config_t* const pConfig);
inline CMemory p_HandleConfigFile; inline bool(*v_HandleConfigFile)(const int configType); //(saved games cfg) 0 = local, 1 = profile.
inline CMemory p_ResetPreviousGameState; inline void(*v_ResetPreviousGameState)(void);
inline CMemory p_LoadPlayerConfig; inline void(*v_LoadPlayerConfig)(ButtonCode_t buttonCode, void* unused);
inline bool(*v_UpdateCurrentVideoConfig)(MaterialSystem_Config_t* pConfig);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -20,30 +19,23 @@ class VMatSys_Interface : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("UpdateMaterialSystemConfig", p_UpdateMaterialSystemConfig.GetPtr()); LogFunAdr("UpdateMaterialSystemConfig", v_UpdateMaterialSystemConfig);
LogFunAdr("UpdateCurrentVideoConfig", p_UpdateCurrentVideoConfig.GetPtr()); LogFunAdr("UpdateCurrentVideoConfig", v_UpdateCurrentVideoConfig);
LogFunAdr("HandleConfigFile", p_HandleConfigFile.GetPtr()); LogFunAdr("HandleConfigFile", v_HandleConfigFile);
LogFunAdr("ResetPreviousGameState", p_ResetPreviousGameState.GetPtr()); LogFunAdr("ResetPreviousGameState", v_ResetPreviousGameState);
LogFunAdr("LoadPlayerConfig", p_LoadPlayerConfig.GetPtr()); LogFunAdr("LoadPlayerConfig", v_LoadPlayerConfig);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_UpdateMaterialSystemConfig = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 80 3D ?? ?? ?? ?? ?? 0F 84 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 80 3D ?? ?? ?? ?? ?? 0F 84 ?? ?? ?? ??").GetPtr(v_UpdateMaterialSystemConfig);
p_UpdateCurrentVideoConfig = g_GameDll.FindPatternSIMD("40 55 ?? 41 56 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 4C 8B F1"); g_GameDll.FindPatternSIMD("40 55 ?? 41 56 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 4C 8B F1").GetPtr(v_UpdateCurrentVideoConfig);
p_HandleConfigFile = g_GameDll.FindPatternSIMD("40 56 48 81 EC ?? ?? ?? ?? 8B F1"); g_GameDll.FindPatternSIMD("40 56 48 81 EC ?? ?? ?? ?? 8B F1").GetPtr(v_HandleConfigFile);
p_ResetPreviousGameState = g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 44 89 3D ?? ?? ?? ?? ?? 8B ?? 24 ??").ResolveRelativeAddressSelf(0x1, 0x5); g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 44 89 3D ?? ?? ?? ?? ?? 8B ?? 24 ??").ResolveRelativeAddressSelf(0x1, 0x5).GetPtr(v_ResetPreviousGameState);
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2) g_GameDll.FindPatternSIMD("E9 ?? ?? ?? ?? CC CC CC CC CC CC CC CC CC CC CC 40 53 48 83 EC 30 4D 8B D1").FollowNearCallSelf().GetPtr(v_LoadPlayerConfig);
p_LoadPlayerConfig = g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ?? 75 0C");
#elif defined (GAMEDLL_S3)
p_LoadPlayerConfig = g_GameDll.FindPatternSIMD("E9 ?? ?? ?? ?? CC CC CC CC CC CC CC CC CC CC CC 40 53 48 83 EC 30 4D 8B D1").FollowNearCallSelf();
#endif
v_UpdateCurrentVideoConfig = p_UpdateCurrentVideoConfig.RCast<bool (*)(MaterialSystem_Config_t*)>();
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -41,10 +41,10 @@ class VModelInfo : public IDetour
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
LogFunAdr("g_pModelInfoServer", reinterpret_cast<uintptr_t>(g_pModelInfoServer)); LogFunAdr("g_pModelInfoServer", g_pModelInfoServer);
#endif // CLIENT_DLL #endif // CLIENT_DLL
#ifndef DEDICATED #ifndef DEDICATED
LogFunAdr("g_pModelInfoClient", reinterpret_cast<uintptr_t>(g_pModelInfoClient)); LogFunAdr("g_pModelInfoClient", g_pModelInfoClient);
#endif // DEDICATED #endif // DEDICATED
} }
virtual void GetFun(void) const { } virtual void GetFun(void) const { }
@ -60,8 +60,7 @@ class VModelInfo : public IDetour
#endif // DEDICATED #endif // DEDICATED
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const { } virtual void Detour(const bool bAttach) const { }
virtual void Detach(void) const { }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -280,7 +280,7 @@ void CMapLoadHelper::Constructor(CMapLoadHelper* loader, int lumpToLoad)
FileHandle_t hLumpFile = FileSystem()->Open(lumpPathBuf, "rb"); FileHandle_t hLumpFile = FileSystem()->Open(lumpPathBuf, "rb");
if (hLumpFile != FILESYSTEM_INVALID_HANDLE) if (hLumpFile != FILESYSTEM_INVALID_HANDLE)
{ {
//DevMsg(eDLL_T::ENGINE, "Loading lump %.4x from file. Buffer: %p\n", lumpToLoad, loader->m_pRawData); DevMsg(eDLL_T::ENGINE, "Loading lump %.4x from file. Buffer: %p\n", lumpToLoad, loader->m_pRawData);
FileSystem()->ReadEx(loader->m_pRawData, lumpSize, lumpSize, hLumpFile); FileSystem()->ReadEx(loader->m_pRawData, lumpSize, lumpSize, hLumpFile);
FileSystem()->Close(hLumpFile); FileSystem()->Close(hLumpFile);
@ -345,20 +345,11 @@ void AddGameLump()
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VModelLoader::Attach() const void VModelLoader::Detour(const bool bAttach) const
{ {
DetourAttach((LPVOID*)&CModelLoader__LoadModel, &CModelLoader::LoadModel); DetourSetup(&CModelLoader__LoadModel, &CModelLoader::LoadModel, bAttach);
DetourAttach((LPVOID*)&CModelLoader__Map_LoadModelGuts, &CModelLoader::Map_LoadModelGuts); DetourSetup(&CModelLoader__Map_LoadModelGuts, &CModelLoader::Map_LoadModelGuts, bAttach);
DetourAttach((LPVOID*)&CMapLoadHelper__CMapLoadHelper, &CMapLoadHelper::Constructor); DetourSetup(&CMapLoadHelper__CMapLoadHelper, &CMapLoadHelper::Constructor, bAttach);
DetourAttach((LPVOID*)&v_AddGameLump, &AddGameLump); DetourSetup(&v_AddGameLump, &AddGameLump, bAttach);
}
void VModelLoader::Detach() const
{
DetourDetach((LPVOID*)&CModelLoader__LoadModel, &CModelLoader::LoadModel);
DetourDetach((LPVOID*)&CModelLoader__Map_LoadModelGuts, &CModelLoader::Map_LoadModelGuts);
DetourDetach((LPVOID*)&CMapLoadHelper__CMapLoadHelper, &CMapLoadHelper::Constructor);
DetourDetach((LPVOID*)&v_AddGameLump, &AddGameLump);
} }

View File

@ -71,38 +71,21 @@ public:
char m_szLumpFilename[260]; char m_szLumpFilename[260];
}; };
inline CMemory p_CModelLoader__FindModel;
inline void*(*CModelLoader__FindModel)(CModelLoader* loader, const char* pszModelName); inline void*(*CModelLoader__FindModel)(CModelLoader* loader, const char* pszModelName);
inline CMemory p_CModelLoader__LoadModel;
inline void(*CModelLoader__LoadModel)(CModelLoader* loader, model_t* model); inline void(*CModelLoader__LoadModel)(CModelLoader* loader, model_t* model);
inline CMemory p_CModelLoader__UnloadModel;
inline uint64_t(*CModelLoader__UnloadModel)(CModelLoader* loader, model_t* model); inline uint64_t(*CModelLoader__UnloadModel)(CModelLoader* loader, model_t* model);
inline CMemory p_CModelLoader__Studio_LoadModel;
inline void*(*CModelLoader__Studio_LoadModel)(CModelLoader* loader); inline void*(*CModelLoader__Studio_LoadModel)(CModelLoader* loader);
inline CMemory p_CModelLoader__Map_LoadModelGuts;
inline uint64_t(*CModelLoader__Map_LoadModelGuts)(CModelLoader* loader, model_t* model); inline uint64_t(*CModelLoader__Map_LoadModelGuts)(CModelLoader* loader, model_t* model);
inline CMemory p_CModelLoader__Map_IsValid;
inline bool(*CModelLoader__Map_IsValid)(CModelLoader* loader, const char* pszMapName); inline bool(*CModelLoader__Map_IsValid)(CModelLoader* loader, const char* pszMapName);
inline CMemory p_CMapLoadHelper__CMapLoadHelper;
inline void(*CMapLoadHelper__CMapLoadHelper)(CMapLoadHelper * helper, int lumpToLoad); inline void(*CMapLoadHelper__CMapLoadHelper)(CMapLoadHelper * helper, int lumpToLoad);
inline CMemory p_AddGameLump;
inline void(*v_AddGameLump)(void); inline void(*v_AddGameLump)(void);
inline CMemory p_Map_LoadModel;
inline void(*v_Map_LoadModel)(void); inline void(*v_Map_LoadModel)(void);
//inline CMemory p_GetSpriteInfo; // DEDICATED PATCH! #ifndef DEDICATED
//inline void*(*GetSpriteInfo)(const char* pName, bool bIsAVI, bool bIsBIK, int& nWidth, int& nHeight, int& nFrameCount, void* a7); inline void*(*v_GetSpriteInfo)(const char* pName, bool bIsAVI, bool bIsBIK, int& nWidth, int& nHeight, int& nFrameCount, void* a7);
inline void*(*v_BuildSpriteLoadName)(const char* pName, char* pOut, int outLen, bool& bIsAVI, bool& bIsBIK);
//inline CMemory p_BuildSpriteLoadName; // DEDICATED PATCH! #endif // !DEDICATED
//inline void*(*BuildSpriteLoadName)(const char* pName, char* pOut, int outLen, bool& bIsAVI, bool& bIsBIK);
inline CModelLoader* g_pModelLoader; inline CModelLoader* g_pModelLoader;
inline FileHandle_t* s_MapFileHandle; inline FileHandle_t* s_MapFileHandle;
@ -114,72 +97,56 @@ class VModelLoader : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CModelLoader::FindModel", p_CModelLoader__FindModel.GetPtr()); LogFunAdr("CModelLoader::FindModel", CModelLoader__FindModel);
LogFunAdr("CModelLoader::LoadModel", p_CModelLoader__LoadModel.GetPtr()); LogFunAdr("CModelLoader::LoadModel", CModelLoader__LoadModel);
LogFunAdr("CModelLoader::UnloadModel", p_CModelLoader__UnloadModel.GetPtr()); LogFunAdr("CModelLoader::UnloadModel", CModelLoader__UnloadModel);
LogFunAdr("CModelLoader::Map_LoadModelGuts", p_CModelLoader__Map_LoadModelGuts.GetPtr()); LogFunAdr("CModelLoader::Map_LoadModelGuts", CModelLoader__Map_LoadModelGuts);
LogFunAdr("CModelLoader::Map_IsValid", p_CModelLoader__Map_IsValid.GetPtr()); LogFunAdr("CModelLoader::Map_IsValid", CModelLoader__Map_IsValid);
LogFunAdr("CModelLoader::Studio_LoadModel", p_CModelLoader__Studio_LoadModel.GetPtr()); LogFunAdr("CModelLoader::Studio_LoadModel", CModelLoader__Studio_LoadModel);
LogFunAdr("CMapLoadHelper::CMapLoadHelper", p_CMapLoadHelper__CMapLoadHelper.GetPtr());
LogFunAdr("AddGameLump", p_AddGameLump.GetPtr()); LogFunAdr("CMapLoadHelper::CMapLoadHelper", CMapLoadHelper__CMapLoadHelper);
LogFunAdr("Map_LoadModel", p_Map_LoadModel.GetPtr());
//LogFunAdr("GetSpriteInfo", p_GetSpriteInfo.GetPtr()); LogFunAdr("AddGameLump", v_AddGameLump);
//LogFunAdr("BuildSpriteLoadName", p_BuildSpriteLoadName.GetPtr()); LogFunAdr("Map_LoadModel", v_Map_LoadModel);
LogVarAdr("g_pModelLoader", reinterpret_cast<uintptr_t>(g_pModelLoader));
LogVarAdr("s_MapFileHandle", reinterpret_cast<uintptr_t>(s_MapFileHandle)); #ifndef DEDICATED
LogVarAdr("s_MapHeader", reinterpret_cast<uintptr_t>(s_MapHeader)); LogFunAdr("GetSpriteInfo", v_GetSpriteInfo);
LogVarAdr("s_szMapPathName", reinterpret_cast<uintptr_t>(s_szMapPathName)); LogFunAdr("BuildSpriteLoadName", v_BuildSpriteLoadName);
#endif // !DEDICATED
LogVarAdr("g_pModelLoader", g_pModelLoader);
LogVarAdr("s_MapFileHandle", s_MapFileHandle);
LogVarAdr("s_MapHeader", s_MapHeader);
LogVarAdr("s_szMapPathName", s_szMapPathName);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("40 55 41 57 48 83 EC 48 80 3A 2A").GetPtr(CModelLoader__FindModel);
p_CModelLoader__FindModel = g_GameDll.FindPatternSIMD("40 55 41 55 41 56 48 8D AC 24 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("40 53 57 41 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ??").GetPtr(CModelLoader__LoadModel);
p_CModelLoader__LoadModel = g_GameDll.FindPatternSIMD("40 53 57 41 56 48 81 EC ?? ?? ?? ?? 48 8B FA"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 33 ED").GetPtr(CModelLoader__UnloadModel);
p_CModelLoader__UnloadModel = g_GameDll.FindPatternSIMD("48 8B C4 48 89 58 18 55 48 81 EC ?? ?? ?? ?? 48 8B DA"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 56 57 41 54 41 57 48 81 EC ?? ?? ?? ??").GetPtr(CModelLoader__Studio_LoadModel);
p_CModelLoader__Studio_LoadModel = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 56 57 41 54 41 56 48 8D AC 24 ?? ?? ?? ??"); g_GameDll.FindPatternSIMD("48 89 54 24 ?? 48 89 4C 24 ?? 55 53 56 57 41 54 41 55 41 57").GetPtr(CModelLoader__Map_LoadModelGuts); // BSP.
p_CModelLoader__Map_LoadModelGuts = g_GameDll.FindPatternSIMD("48 89 54 24 ?? 48 89 4C 24 ?? 55 53 41 54 41 55 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? FF 05 ?? ?? ?? ??"); // BSP. g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 48 8B DA 48 85 D2 0F 84 ?? ?? ?? ?? 80 3A ?? 0F 84 ?? ?? ?? ?? 4C 8B CA").GetPtr(CModelLoader__Map_IsValid);
p_CModelLoader__Map_IsValid = g_GameDll.FindPatternSIMD("48 8B C4 53 48 81 EC ?? ?? ?? ?? 48 8B DA");
//p_GetSpriteInfo = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 54 41 55 41 56 41 57 48 83 EC 30 4C 8B AC 24 ?? ?? ?? ?? BE ?? ?? ?? ??"); #ifndef DEDICATED
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 54 41 55 41 56 41 57 48 83 EC 30 4C 8B BC 24 ?? ?? ?? ??").GetPtr(v_GetSpriteInfo);
p_CModelLoader__FindModel = g_GameDll.FindPatternSIMD("40 55 41 57 48 83 EC 48 80 3A 2A"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 81 EC ?? ?? ?? ?? 4D 8B F1 48 8B F2").GetPtr(v_BuildSpriteLoadName);
p_CModelLoader__LoadModel = g_GameDll.FindPatternSIMD("40 53 57 41 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ??"); #endif // !DEDICATED
p_CModelLoader__UnloadModel = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 33 ED");
p_CModelLoader__Studio_LoadModel = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 56 57 41 54 41 57 48 81 EC ?? ?? ?? ??");
p_CModelLoader__Map_LoadModelGuts = g_GameDll.FindPatternSIMD("48 89 54 24 ?? 48 89 4C 24 ?? 55 53 56 57 41 54 41 55 41 57"); // BSP.
p_CModelLoader__Map_IsValid = g_GameDll.FindPatternSIMD("40 53 48 81 EC ?? ?? ?? ?? 48 8B DA 48 85 D2 0F 84 ?? ?? ?? ?? 80 3A ?? 0F 84 ?? ?? ?? ?? 4C 8B CA");
//p_GetSpriteInfo = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 54 41 55 41 56 41 57 48 83 EC 30 4C 8B BC 24 ?? ?? ?? ??");
#endif
//p_BuildSpriteLoadName = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 81 EC ?? ?? ?? ?? 4D 8B F1 48 8B F2");
p_CMapLoadHelper__CMapLoadHelper = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 7C 24 ?? 41 56 48 81 EC 60"); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 7C 24 ?? 41 56 48 81 EC 60").GetPtr(CMapLoadHelper__CMapLoadHelper);
p_AddGameLump = g_GameDll.FindPatternSIMD("40 ?? 57 48 83 EC 48 33 ?? 48 8D"); g_GameDll.FindPatternSIMD("40 ?? 57 48 83 EC 48 33 ?? 48 8D").GetPtr(v_AddGameLump);
p_Map_LoadModel = g_GameDll.FindPatternSIMD("48 83 EC 28 8B 05 ?? ?? ?? ?? FF C8"); g_GameDll.FindPatternSIMD("48 83 EC 28 8B 05 ?? ?? ?? ?? FF C8").GetPtr(v_Map_LoadModel);
CModelLoader__FindModel = p_CModelLoader__FindModel.RCast<void* (*)(CModelLoader*, const char*)>();
CModelLoader__LoadModel = p_CModelLoader__LoadModel.RCast<void(*)(CModelLoader*, model_t*)>();
CModelLoader__UnloadModel = p_CModelLoader__UnloadModel.RCast<uint64_t(*)(CModelLoader*, model_t*)>();
CModelLoader__Studio_LoadModel = p_CModelLoader__Studio_LoadModel.RCast<void* (*)(CModelLoader*)>();
CModelLoader__Map_LoadModelGuts = p_CModelLoader__Map_LoadModelGuts.RCast<uint64_t(*)(CModelLoader*, model_t* mod)>();
CModelLoader__Map_IsValid = p_CModelLoader__Map_IsValid.RCast<bool(*)(CModelLoader*, const char*)>();
CMapLoadHelper__CMapLoadHelper = p_CMapLoadHelper__CMapLoadHelper.RCast<void(*)(CMapLoadHelper*, int)>();
v_AddGameLump = p_AddGameLump.RCast<void(*)(void)>();
v_Map_LoadModel = p_Map_LoadModel.RCast<void(*)(void)>();
//GetSpriteInfo = p_GetSpriteInfo.RCast<void* (*)(const char*, bool, bool, int&, int&, int&, void*)>();
//BuildSpriteLoadName = p_BuildSpriteLoadName.RCast<void* (*)(const char*, char*, int, bool&, bool&)>();
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
g_pModelLoader = g_GameDll.FindPatternSIMD( g_pModelLoader = g_GameDll.FindPatternSIMD(
"48 89 4C 24 ?? 53 55 56 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ??").FindPatternSelf("48 ?? 0D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(3, 7).RCast<CModelLoader*>(); "48 89 4C 24 ?? 53 55 56 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ??").FindPatternSelf("48 ?? 0D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(3, 7).RCast<CModelLoader*>();
s_MapFileHandle = p_Map_LoadModel.FindPattern("48 8B").ResolveRelativeAddressSelf(0x3, 0x7).RCast<FileHandle_t*>(); s_MapFileHandle = CMemory(v_Map_LoadModel).FindPattern("48 8B").ResolveRelativeAddressSelf(0x3, 0x7).RCast<FileHandle_t*>();
s_MapHeader = p_Map_LoadModel.FindPattern("48 8D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<BSPHeader_t*>(); s_MapHeader = CMemory(v_Map_LoadModel).FindPattern("48 8D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<BSPHeader_t*>();
s_szMapPathName = p_CMapLoadHelper__CMapLoadHelper.FindPattern("4C 8D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<char*>(); s_szMapPathName = CMemory(CMapLoadHelper__CMapLoadHelper).FindPattern("4C 8D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<char*>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -6,7 +6,7 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "engine/net.h" #include "engine/net.h"
#ifndef NETCONSOLE #ifndef _TOOLS
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "mathlib/color.h" #include "mathlib/color.h"
#include "net.h" #include "net.h"
@ -15,9 +15,45 @@
#include "server/server.h" #include "server/server.h"
#include "client/client.h" #include "client/client.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
#endif // !NETCONSOLE #endif // !_TOOLS
#ifndef _TOOLS
static void NET_SetKey_f(const CCommand& args)
{
if (args.ArgC() < 2)
{
return;
}
NET_SetKey(args.Arg(1));
}
static void NET_GenerateKey_f()
{
NET_GenerateKey();
}
void NET_UseRandomKeyChanged_f(IConVar* pConVar, const char* pOldString)
{
if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName()))
{
if (strcmp(pOldString, pConVarRef->GetString()) == NULL)
return; // Same value.
if (pConVarRef->GetBool())
NET_GenerateKey();
else
NET_SetKey(DEFAULT_NET_ENCRYPTION_KEY);
}
}
ConVar net_useRandomKey("net_useRandomKey", "1", FCVAR_RELEASE, "Use random AES encryption key for game packets.", false, 0.f, false, 0.f, &NET_UseRandomKeyChanged_f, nullptr);
static ConVar net_tracePayload("net_tracePayload", "0", FCVAR_DEVELOPMENTONLY, "Log the payload of the send/recv datagram to a file on the disk.");
static ConVar net_encryptionEnable("net_encryptionEnable", "1", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Use AES encryption on game packets.");
static ConCommand net_setkey("net_setkey", NET_SetKey_f, "Sets user specified base64 net key", FCVAR_RELEASE);
static ConCommand net_generatekey("net_generatekey", NET_GenerateKey_f, "Generates and sets a random base64 net key", FCVAR_RELEASE);
#ifndef NETCONSOLE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: hook and log the receive datagram // Purpose: hook and log the receive datagram
// Input : iSocket - // Input : iSocket -
@ -27,13 +63,16 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool NET_ReceiveDatagram(int iSocket, netpacket_s* pInpacket, bool bEncrypted) bool NET_ReceiveDatagram(int iSocket, netpacket_s* pInpacket, bool bEncrypted)
{ {
bool result = v_NET_ReceiveDatagram(iSocket, pInpacket, net_encryptionEnable->GetBool()); const bool decryptPacket = (bEncrypted && net_encryptionEnable.GetBool());
if (result && net_tracePayload->GetBool()) const bool result = v_NET_ReceiveDatagram(iSocket, pInpacket, decryptPacket);
if (result && net_tracePayload.GetBool())
{ {
// Log received packet data. // Log received packet data.
HexDump("[+] NET_ReceiveDatagram ", "net_trace", HexDump("[+] NET_ReceiveDatagram ", "net_trace",
pInpacket->pData, size_t(pInpacket->wiresize)); pInpacket->pData, size_t(pInpacket->wiresize));
} }
return result; return result;
} }
@ -48,15 +87,66 @@ bool NET_ReceiveDatagram(int iSocket, netpacket_s* pInpacket, bool bEncrypted)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int NET_SendDatagram(SOCKET s, void* pPayload, int iLenght, netadr_t* pAdr, bool bEncrypt) int NET_SendDatagram(SOCKET s, void* pPayload, int iLenght, netadr_t* pAdr, bool bEncrypt)
{ {
int result = v_NET_SendDatagram(s, pPayload, iLenght, pAdr, net_encryptionEnable->GetBool()); const bool encryptPacket = (bEncrypt && net_encryptionEnable.GetBool());
if (result && net_tracePayload->GetBool()) const int result = v_NET_SendDatagram(s, pPayload, iLenght, pAdr, encryptPacket);
if (result && net_tracePayload.GetBool())
{ {
// Log transmitted packet data. // Log transmitted packet data.
HexDump("[+] NET_SendDatagram ", "net_trace", pPayload, size_t(iLenght)); HexDump("[+] NET_SendDatagram ", "net_trace", pPayload, size_t(iLenght));
} }
return result; return result;
} }
//-----------------------------------------------------------------------------
// Purpose: compresses the input buffer into the output buffer
// Input : *dest -
// *destLen -
// *source -
// sourceLen -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool NET_BufferToBufferCompress(uint8_t* const dest, size_t* const destLen, uint8_t* const source, const size_t sourceLen)
{
CLZSS lzss;
uint32_t compLen = (uint32_t)sourceLen;
if (!lzss.CompressNoAlloc(source, (uint32_t)sourceLen, dest, &compLen))
{
memcpy(dest, source, sourceLen);
*destLen = sourceLen;
return false;
}
*destLen = compLen;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: decompresses the input buffer into the output buffer
// Input : *source -
// &sourceLen -
// *dest -
// destLen -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
unsigned int NET_BufferToBufferDecompress(uint8_t* const source, size_t& sourceLen, uint8_t* const dest, const size_t destLen)
{
Assert(source);
Assert(sourceLen);
CLZSS lzss;
if (lzss.IsCompressed(source))
{
return lzss.SafeUncompress(source, dest, (unsigned int)destLen);
}
return 0;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: safely decompresses the input buffer into the output buffer // Purpose: safely decompresses the input buffer into the output buffer
// Input : *lzss - // Input : *lzss -
@ -65,7 +155,7 @@ int NET_SendDatagram(SOCKET s, void* pPayload, int iLenght, netadr_t* pAdr, bool
// unBufSize - // unBufSize -
// Output : total decompressed bytes // Output : total decompressed bytes
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
unsigned int NET_Decompress(CLZSS* lzss, unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize) unsigned int NET_BufferToBufferDecompress_LZSS(CLZSS* lzss, unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize)
{ {
return lzss->SafeUncompress(pInput, pOutput, unBufSize); return lzss->SafeUncompress(pInput, pOutput, unBufSize);
} }
@ -92,7 +182,7 @@ void NET_SetKey(const string& svNetKey)
{ {
v_NET_SetKey(g_pNetKey, svTokenizedKey.c_str()); v_NET_SetKey(g_pNetKey, svTokenizedKey.c_str());
DevMsg(eDLL_T::ENGINE, "Installed NetKey: %s'%s%s%s'\n", Msg(eDLL_T::ENGINE, "Installed NetKey: %s'%s%s%s'\n",
g_svReset, g_svGreyB, g_pNetKey->GetBase64NetKey(), g_svReset); g_svReset, g_svGreyB, g_pNetKey->GetBase64NetKey(), g_svReset);
} }
else else
@ -106,9 +196,9 @@ void NET_SetKey(const string& svNetKey)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void NET_GenerateKey() void NET_GenerateKey()
{ {
if (!net_useRandomKey->GetBool()) if (!net_useRandomKey.GetBool())
{ {
net_useRandomKey->SetValue(1); net_useRandomKey.SetValue(1);
return; // Change callback will handle this. return; // Change callback will handle this.
} }
@ -154,7 +244,7 @@ void NET_PrintFunc(const char* fmt, ...)
result.push_back('\n'); result.push_back('\n');
} }
DevMsg(context, "%s", result.c_str()); Msg(context, "%s", result.c_str());
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -175,10 +265,22 @@ void NET_RemoveChannel(CClient* pClient, int nIndex, const char* szReason, uint8
pClient->GetNetChan()->Shutdown(szReason, bBadRep, bRemoveNow); // Shutdown NetChannel. pClient->GetNetChan()->Shutdown(szReason, bBadRep, bRemoveNow); // Shutdown NetChannel.
pClient->Clear(); // Reset CClient slot. pClient->Clear(); // Reset CClient slot.
g_ServerPlayer[nIndex].Reset(); // Reset ServerPlayer slot.
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
} }
#endif // !NETCONSOLE
//-----------------------------------------------------------------------------
// Purpose: reads the net message type from buffer
// Input : &outType -
// &buffer -
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool NET_ReadMessageType(int* outType, bf_read* buffer)
{
*outType = buffer->ReadUBitLong(NETMSG_TYPE_BITS);
return !buffer->IsOverflowed();
}
#endif // !_TOOLS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: returns the WSA error code // Purpose: returns the WSA error code
@ -282,24 +384,17 @@ const char* NET_ErrorString(int iCode)
} }
} }
#ifndef NETCONSOLE #ifndef _TOOLS
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VNet::Attach() const void VNet::Detour(const bool bAttach) const
{ {
DetourAttach((LPVOID*)&v_NET_Config, &NET_Config); DetourSetup(&v_NET_Config, &NET_Config, bAttach);
DetourAttach((LPVOID*)&v_NET_ReceiveDatagram, &NET_ReceiveDatagram); DetourSetup(&v_NET_ReceiveDatagram, &NET_ReceiveDatagram, bAttach);
DetourAttach((LPVOID*)&v_NET_SendDatagram, &NET_SendDatagram); DetourSetup(&v_NET_SendDatagram, &NET_SendDatagram, bAttach);
DetourAttach((LPVOID*)&v_NET_Decompress, &NET_Decompress);
DetourAttach((LPVOID*)&v_NET_PrintFunc, &NET_PrintFunc);
}
void VNet::Detach() const DetourSetup(&v_NET_BufferToBufferCompress, &NET_BufferToBufferCompress, bAttach);
{ DetourSetup(&v_NET_BufferToBufferDecompress_LZSS, &NET_BufferToBufferDecompress_LZSS, bAttach);
DetourDetach((LPVOID*)&v_NET_Config, &NET_Config); DetourSetup(&v_NET_PrintFunc, &NET_PrintFunc, bAttach);
DetourDetach((LPVOID*)&v_NET_ReceiveDatagram, &NET_ReceiveDatagram);
DetourDetach((LPVOID*)&v_NET_SendDatagram, &NET_SendDatagram);
DetourDetach((LPVOID*)&v_NET_Decompress, &NET_Decompress);
DetourDetach((LPVOID*)&v_NET_PrintFunc, &NET_PrintFunc);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -307,4 +402,4 @@ netadr_t* g_pNetAdr = nullptr;
netkey_t* g_pNetKey = nullptr; netkey_t* g_pNetKey = nullptr;
double* g_pNetTime = nullptr; double* g_pNetTime = nullptr;
#endif // !NETCONSOLE #endif // !_TOOLS

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#ifndef NETCONSOLE #ifndef _TOOLS
#include "engine/net_chan.h" #include "engine/net_chan.h"
#include "tier1/lzss.h" #include "tier1/lzss.h"
#define MAX_STREAMS 2 #define MAX_STREAMS 2
@ -19,26 +19,20 @@ constexpr unsigned int AES_128_B64_ENCODED_SIZE = 24;
constexpr const char* DEFAULT_NET_ENCRYPTION_KEY = "WDNWLmJYQ2ZlM0VoTid3Yg=="; constexpr const char* DEFAULT_NET_ENCRYPTION_KEY = "WDNWLmJYQ2ZlM0VoTid3Yg==";
/* ==== CNETCHAN ======================================================================================================================================================== */ /* ==== CNETCHAN ======================================================================================================================================================== */
inline CMemory p_NET_Init;
inline void*(*v_NET_Init)(bool bDeveloper); inline void*(*v_NET_Init)(bool bDeveloper);
inline CMemory p_NET_SetKey;
inline void(*v_NET_SetKey)(netkey_t* pKey, const char* szHash); inline void(*v_NET_SetKey)(netkey_t* pKey, const char* szHash);
inline CMemory p_NET_Config;
inline void(*v_NET_Config)(void); inline void(*v_NET_Config)(void);
inline CMemory p_NET_ReceiveDatagram; inline int(*v_NET_GetPacket)(int iSocket, uint8_t* pScratch, bool bEncrypted);
inline bool(*v_NET_ReceiveDatagram)(int iSocket, netpacket_s* pInpacket, bool bRaw); inline int(*v_NET_SendPacket)(CNetChan* pChan, int iSocket, const netadr_t& toAdr, const uint8_t* pData, unsigned int nLen, void* unused0, bool bCompress, void* unused1, bool bEncrypt);
inline CMemory p_NET_SendDatagram; inline bool(*v_NET_ReceiveDatagram)(int iSocket, netpacket_s* pInpacket, bool bRaw);
inline int(*v_NET_SendDatagram)(SOCKET s, void* pPayload, int iLenght, netadr_t* pAdr, bool bEncrypted); inline int(*v_NET_SendDatagram)(SOCKET s, void* pPayload, int iLenght, netadr_t* pAdr, bool bEncrypted);
inline CMemory p_NET_Decompress; inline bool(*v_NET_BufferToBufferCompress)(uint8_t* const dest, size_t* const destLen, uint8_t* const source, const size_t sourceLen);
inline int(*v_NET_Decompress)(CLZSS* lzss, unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize); inline unsigned int(*v_NET_BufferToBufferDecompress_LZSS)(CLZSS* lzss, unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize);
inline CMemory p_NET_PrintFunc; inline void(*v_NET_PrintFunc)(const char* fmt, ...);
inline void(*v_NET_PrintFunc)(const char* fmt);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
bool NET_ReceiveDatagram(int iSocket, netpacket_s* pInpacket, bool bRaw); bool NET_ReceiveDatagram(int iSocket, netpacket_s* pInpacket, bool bRaw);
@ -48,61 +42,72 @@ void NET_GenerateKey();
void NET_PrintFunc(const char* fmt, ...); void NET_PrintFunc(const char* fmt, ...);
void NET_RemoveChannel(CClient* pClient, int nIndex, const char* szReason, uint8_t bBadRep, bool bRemoveNow); void NET_RemoveChannel(CClient* pClient, int nIndex, const char* szReason, uint8_t bBadRep, bool bRemoveNow);
bool NET_BufferToBufferCompress(uint8_t* const dest, size_t* const destLen, uint8_t* const source, const size_t sourceLen);
unsigned int NET_BufferToBufferDecompress(uint8_t* pInput, size_t& coBufsize, uint8_t* pOutput, const size_t unBufSize);
unsigned int NET_BufferToBufferDecompress_LZSS(CLZSS* lzss, unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize);
bool NET_ReadMessageType(int* outType, bf_read* buffer);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
extern netadr_t* g_pNetAdr; extern netadr_t* g_pNetAdr;
extern netkey_t* g_pNetKey; extern netkey_t* g_pNetKey;
extern double* g_pNetTime; extern double* g_pNetTime;
extern ConVar net_useRandomKey;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class VNet : public IDetour class VNet : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("NET_Init", p_NET_Init.GetPtr()); LogFunAdr("NET_Init", v_NET_Init);
LogFunAdr("NET_Config", p_NET_Config.GetPtr()); LogFunAdr("NET_Config", v_NET_Config);
LogFunAdr("NET_SetKey", p_NET_SetKey.GetPtr()); LogFunAdr("NET_SetKey", v_NET_SetKey);
LogFunAdr("NET_ReceiveDatagram", p_NET_ReceiveDatagram.GetPtr());
LogFunAdr("NET_SendDatagram", p_NET_SendDatagram.GetPtr()); LogFunAdr("NET_GetPacket", v_NET_GetPacket);
LogFunAdr("NET_Decompress", p_NET_Decompress.GetPtr()); LogFunAdr("NET_SendPacket", v_NET_SendPacket);
LogFunAdr("NET_PrintFunc", p_NET_PrintFunc.GetPtr());
LogVarAdr("g_NetAdr", reinterpret_cast<uintptr_t>(g_pNetAdr)); LogFunAdr("NET_ReceiveDatagram", v_NET_ReceiveDatagram);
LogVarAdr("g_NetKey", reinterpret_cast<uintptr_t>(g_pNetKey)); LogFunAdr("NET_SendDatagram", v_NET_SendDatagram);
LogVarAdr("g_NetTime", reinterpret_cast<uintptr_t>(g_pNetTime));
LogFunAdr("NET_BufferToBufferCompress", v_NET_BufferToBufferCompress);
LogFunAdr("NET_BufferToBufferDecompress_LZSS", v_NET_BufferToBufferDecompress_LZSS);
LogFunAdr("NET_PrintFunc", v_NET_PrintFunc);
LogVarAdr("g_NetAdr", g_pNetAdr);
LogVarAdr("g_NetKey", g_pNetKey);
LogVarAdr("g_NetTime", g_pNetTime);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2) g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC F0 01 ??").GetPtr(v_NET_Init);
p_NET_Init = g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC C0 01 ??"); g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 57 C0").GetPtr(v_NET_Config);
#elif defined (GAMEDLL_S3) g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 48 8B F9 41 B8").GetPtr(v_NET_SetKey);
p_NET_Init = g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC F0 01 ??");
#endif
p_NET_Config = g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 57 C0");
p_NET_SetKey = g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 48 8B F9 41 B8");
p_NET_ReceiveDatagram = g_GameDll.FindPatternSIMD("48 89 74 24 18 48 89 7C 24 20 55 41 54 41 55 41 56 41 57 48 8D AC 24 50 EB");
p_NET_SendDatagram = g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ?? 05 ?? ??");
p_NET_Decompress = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 41 56 45 33 F6");
p_NET_PrintFunc = g_GameDll.FindPatternSIMD("48 89 54 24 10 4C 89 44 24 18 4C 89 4C 24 20 C3 48");
v_NET_Init = p_NET_Init.RCast<void* (*)(bool)>(); /*48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC F0 01 00*/
v_NET_Config = p_NET_Config.RCast<void (*)(void)>(); g_GameDll.FindPatternSIMD("48 8B C4 44 88 40 18 48 89 50 10 41 55").GetPtr(v_NET_GetPacket);
v_NET_SetKey = p_NET_SetKey.RCast<void (*)(netkey_t*, const char*)>(); /*48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 48 8B F9 41 B8*/ g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 55 57 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 4C 63 F2").GetPtr(v_NET_SendPacket);
v_NET_ReceiveDatagram = p_NET_ReceiveDatagram.RCast<bool (*)(int, netpacket_s*, bool)>(); /*E8 ?? ?? ?? ?? 84 C0 75 35 48 8B D3*/
v_NET_SendDatagram = p_NET_SendDatagram.RCast<int (*)(SOCKET, void*, int, netadr_t*, bool)>(); /*48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ?? 05 00 00*/ g_GameDll.FindPatternSIMD("48 89 74 24 18 48 89 7C 24 20 55 41 54 41 55 41 56 41 57 48 8D AC 24 50 EB").GetPtr(v_NET_ReceiveDatagram);
v_NET_Decompress = p_NET_Decompress.RCast<int (*)(CLZSS*, unsigned char*, unsigned char*, unsigned int)>(); g_GameDll.FindPatternSIMD("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ?? 05 ?? ??").GetPtr(v_NET_SendDatagram);
v_NET_PrintFunc = p_NET_PrintFunc.RCast<void(*)(const char*)>(); /*48 89 54 24 10 4C 89 44 24 18 4C 89 4C 24 20 C3 48*/
g_GameDll.FindPatternSIMD("48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 50 48 8B 05 ?? ?? ?? ?? 49 8B E9").GetPtr(v_NET_BufferToBufferCompress);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 41 56 45 33 F6").GetPtr(v_NET_BufferToBufferDecompress_LZSS);
g_GameDll.FindPatternSIMD("48 89 54 24 10 4C 89 44 24 18 4C 89 4C 24 20 C3 48").GetPtr(v_NET_PrintFunc);
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {
g_pNetAdr = g_GameDll.FindPatternSIMD("C7 05 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 66 89 05 ?? ?? ?? ?? 88 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 33 C0").ResolveRelativeAddressSelf(0x2, 0xA).RCast<netadr_t*>(); g_pNetAdr = g_GameDll.FindPatternSIMD("C7 05 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 66 89 05 ?? ?? ?? ?? 88 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 33 C0").ResolveRelativeAddressSelf(0x2, 0xA).RCast<netadr_t*>();
g_pNetKey = g_GameDll.FindString("client:NetEncryption_NewKey").FindPatternSelf("48 8D ?? ?? ?? ?? ?? 48 3B", CMemory::Direction::UP, 300).ResolveRelativeAddressSelf(0x3, 0x7).RCast<netkey_t*>(); g_pNetKey = g_GameDll.FindString("client:NetEncryption_NewKey").FindPatternSelf("48 8D ?? ?? ?? ?? ?? 48 3B", CMemory::Direction::UP, 300).ResolveRelativeAddressSelf(0x3, 0x7).RCast<netkey_t*>();
g_pNetTime = p_NET_Init.Offset(0xA).FindPatternSelf("F2 0F").ResolveRelativeAddressSelf(0x4, 0x8).RCast<double*>(); g_pNetTime = CMemory(v_NET_Init).Offset(0xA).FindPatternSelf("F2 0F").ResolveRelativeAddressSelf(0x4, 0x8).RCast<double*>();
} }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#endif // !NETCONSOLE #endif // !_TOOLS
const char* NET_ErrorString(int iCode); const char* NET_ErrorString(int iCode);

View File

@ -7,7 +7,7 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "tier0/frametask.h" #include "tier0/frametask.h"
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "vpc/keyvalues.h" #include "tier1/keyvalues.h"
#include "common/callback.h" #include "common/callback.h"
#include "engine/net.h" #include "engine/net.h"
#include "engine/net_chan.h" #include "engine/net_chan.h"
@ -17,22 +17,28 @@
#include "server/vengineserver_impl.h" #include "server/vengineserver_impl.h"
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
//-----------------------------------------------------------------------------
// Console variables
//-----------------------------------------------------------------------------
static ConVar net_processTimeBudget("net_processTimeBudget", "200", FCVAR_RELEASE, "Net message process time budget in milliseconds (removing netchannel if exceeded).", true, 0.f, false, 0.f, "0 = disabled");
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: gets the netchannel network loss // Purpose: gets the netchannel resend rate
// Output : float // Output : float
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
float CNetChan::GetNetworkLoss() const float CNetChan::GetResendRate() const
{ {
float v1 = *&m_DataFlow[1].frames[0].one; const int64_t totalupdates = this->m_DataFlow[FLOW_INCOMING].totalupdates;
if (!v1 && !m_nSequencesSkipped_MAYBE)
if (!totalupdates && !this->m_nSequencesSkipped_MAYBE)
return 0.0f; return 0.0f;
float v4 = (v1 + m_nSequencesSkipped_MAYBE); float lossRate = (float)(totalupdates + m_nSequencesSkipped_MAYBE);
if (v1 + m_nSequencesSkipped_MAYBE < 0)
v4 = v4 + float(2 ^ 64);
return m_nSequencesSkipped_MAYBE / v4; if (totalupdates + m_nSequencesSkipped_MAYBE < 0.0f)
lossRate += float(2 ^ 64);
return m_nSequencesSkipped_MAYBE / lossRate;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -64,6 +70,287 @@ double CNetChan::GetTimeConnected(void) const
return (t > 0.0) ? t : 0.0; return (t > 0.0) ? t : 0.0;
} }
//-----------------------------------------------------------------------------
// Purpose: gets the number of bits written in selected stream
//-----------------------------------------------------------------------------
int CNetChan::GetNumBitsWritten(const bool bReliable)
{
bf_write* pStream = &m_StreamUnreliable;
if (bReliable)
{
pStream = &m_StreamReliable;
}
return pStream->GetNumBitsWritten();
}
//-----------------------------------------------------------------------------
// Purpose: gets the number of bits written in selected stream
//-----------------------------------------------------------------------------
int CNetChan::GetNumBitsLeft(const bool bReliable)
{
bf_write* pStream = &m_StreamUnreliable;
if (bReliable)
{
pStream = &m_StreamReliable;
}
return pStream->GetNumBitsLeft();
}
//-----------------------------------------------------------------------------
// Purpose: flows a new packet
// Input : *pChan -
// outSeqNr -
// acknr -
// inSeqNr -
// nChoked -
// nDropped -
// nSize -
//-----------------------------------------------------------------------------
void CNetChan::_FlowNewPacket(CNetChan* pChan, int flow, int outSeqNr, int inSeqNr, int nChoked, int nDropped, int nSize)
{
float netTime; // xmm4_8 (was double)
int v8; // r13d
int v9; // r14d
int v12; // r12d
int currentindex; // eax
int nextIndex; // r15d
int v17; // r8d
int v18; // ebp
unsigned int v19; // eax
int v20; // r9 (was char)
int v21; // r8d
__int64 v22; // r14
float time; // xmm0_4
__int64 v24; // rdx
__int64 v25; // rcx
__int64 v26; // rdx
__int64 v27; // rcx
__int64 v28; // rdx
__int64 v29; // rcx
int v30; // edx
int v31; // r8 (was char)
float v32; // xmm0_4
__int64 v33; // r9
__int64 v34; // rax
__int64 v35; // rdx
int v36; // r8d
float v37; // xmm3_4
__int64 result; // rax
float v39; // xmm1_4
float v40; // xmm0_4
float v41; // xmm1_4
netframe_header_t* v42; // rdx
float v43; // xmm0_4
float v44; // xmm2_4
float v45; // xmm0_4
netTime = (float)*g_pNetTime;
v8 = flow;
v9 = inSeqNr;
netflow_t* pFlow = &pChan->m_DataFlow[flow];
v12 = outSeqNr;
netframe_header_t* pFrameHeader = nullptr;
netframe_t* pFrame = nullptr;
currentindex = pFlow->currentindex;
if (outSeqNr > currentindex)
{
nextIndex = currentindex + 1;
if (currentindex + 1 <= outSeqNr)
{
// This variable makes sure the loops below do not execute more
// than NET_FRAMES_BACKUP times. This has to be done as the
// headers and frame arrays in the netflow_t structure is as
// large as NET_FRAMES_BACKUP. Any execution past it is futile
// and only wastes CPU time. Sending an outSeqNr that is higher
// than the current index by something like a million or more will
// hang the engine for several milliseconds to several seconds.
int numPacketFrames = 0;
v17 = outSeqNr - nextIndex;
if (v17 + 1 >= 4)
{
v18 = nChoked + nDropped;
v19 = ((unsigned int)(v12 - nextIndex - 3) >> 2) + 1;
v20 = nextIndex + 2;
v21 = v17 - 2;
v22 = v19;
time = (float)*g_pNetTime;
nextIndex += 4 * v19;
do
{
v24 = (v20 - 2) & NET_FRAMES_MASK;
v25 = v24;
pFlow->frame_headers[v25].time = time;
pFlow->frame_headers[v25].valid = 0;
pFlow->frame_headers[v25].size = 0;
pFlow->frame_headers[v25].latency = -1.0;
pFlow->frames[v24].avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
pFlow->frame_headers[v25].choked = 0;
pFlow->frames[v24].dropped = 0;
if (v21 + 2 < v18)
{
if (v21 + 2 >= nChoked)
pFlow->frames[v24].dropped = 1;
else
pFlow->frame_headers[(v20 - 2) & NET_FRAMES_MASK].choked = 1;
}
v26 = (v20 - 1) & NET_FRAMES_MASK;
v27 = v26;
pFlow->frame_headers[v27].time = time;
pFlow->frame_headers[v27].valid = 0;
pFlow->frame_headers[v27].size = 0;
pFlow->frame_headers[v27].latency = -1.0;
pFlow->frames[v26].avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
pFlow->frame_headers[v27].choked = 0;
pFlow->frames[v26].dropped = 0;
if (v21 + 1 < v18)
{
if (v21 + 1 >= nChoked)
pFlow->frames[v26].dropped = 1;
else
pFlow->frame_headers[(v20 - 1) & NET_FRAMES_MASK].choked = 1;
}
v28 = v20 & NET_FRAMES_MASK;
v29 = v28;
pFlow->frame_headers[v29].time = time;
pFlow->frame_headers[v29].valid = 0;
pFlow->frame_headers[v29].size = 0;
pFlow->frame_headers[v29].latency = -1.0;
pFlow->frames[v28].avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
pFlow->frame_headers[v29].choked = 0;
pFlow->frames[v28].dropped = 0;
if (v21 < v18)
{
if (v21 >= nChoked)
pFlow->frames[v28].dropped = 1;
else
pFlow->frame_headers[v20 & NET_FRAMES_MASK].choked = 1;
}
pFrame = &pFlow->frames[(v20 + 1) & NET_FRAMES_MASK];
pFrameHeader = &pFlow->frame_headers[(v20 + 1) & NET_FRAMES_MASK];
pFrameHeader->time = time;
pFrameHeader->valid = 0;
pFrameHeader->size = 0;
pFrameHeader->latency = -1.0;
pFrame->avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
pFrameHeader->choked = 0;
pFrame->dropped = 0;
if (v21 - 1 < v18)
{
if (v21 - 1 >= nChoked)
pFrame->dropped = 1;
else
pFrameHeader->choked = 1;
}
// Incremented by four since this loop does four frames
// per iteration.
numPacketFrames += 4;
v21 -= 4;
v20 += 4;
--v22;
} while (v22 && numPacketFrames < NET_FRAMES_BACKUP);
v12 = outSeqNr;
v8 = flow;
v9 = inSeqNr;
}
// Check if we did not reach NET_FRAMES_BACKUP, else we will
// execute the 129'th iteration as well. Also check if the next
// index doesn't exceed the outSeqNr.
if (numPacketFrames < NET_FRAMES_BACKUP && nextIndex <= v12)
{
v30 = v12 - nextIndex;
v31 = nextIndex;
v33 = v12 - nextIndex + 1;
do
{
pFrame = &pFlow->frames[v31 & NET_FRAMES_MASK];
pFrameHeader = &pFlow->frame_headers[v31 & NET_FRAMES_MASK];
v32 = netTime;
pFrameHeader->time = v32;
pFrameHeader->valid = 0;
pFrameHeader->size = 0;
pFrameHeader->latency = -1.0;
pFrame->avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
pFrameHeader->choked = 0;
pFrame->dropped = 0;
if (v30 < nChoked + nDropped)
{
if (v30 >= nChoked)
pFrame->dropped = 1;
else
pFrameHeader->choked = 1;
}
--v30;
++v31;
--v33;
++numPacketFrames;
} while (v33 && numPacketFrames < NET_FRAMES_BACKUP);
v9 = inSeqNr;
}
}
pFrame->dropped = nDropped;
pFrameHeader->choked = (short)nChoked;
pFrameHeader->size = nSize;
pFrameHeader->valid = 1;
pFrame->avg_latency = pChan->m_DataFlow[FLOW_OUTGOING].avglatency;
}
++pFlow->totalpackets;
pFlow->currentindex = v12;
v34 = 544i64;
if (!v8)
v34 = 3688i64;
pFlow->current_frame = pFrame;
v35 = 548i64;
v36 = *(_DWORD*)(&pChan->m_bProcessingMessages + v34);
if (v9 > v36 - NET_FRAMES_BACKUP)
{
if (!v8)
v35 = 3692i64;
result = (__int64)pChan + 16 * (v9 & NET_FRAMES_MASK);
v42 = (netframe_header_t*)(result + v35);
if (v42->valid && v42->latency == -1.0)
{
v43 = 0.0;
v44 = fmax(0.0f, netTime - v42->time);
v42->latency = v44;
if (v44 >= 0.0)
v43 = v44;
else
v42->latency = 0.0;
v45 = v43 + pFlow->latency;
++pFlow->totalupdates;
pFlow->latency = v45;
pFlow->maxlatency = fmaxf(pFlow->maxlatency, v42->latency);
}
}
else
{
if (!v8)
v35 = 3692i64;
v37 = *(float*)(&pChan->m_bProcessingMessages + 16 * (v36 & NET_FRAMES_MASK) + v35);
result = v35 + 16i64 * (((_BYTE)v36 + 1) & NET_FRAMES_MASK);
v39 = v37 - *(float*)(&pChan->m_bProcessingMessages + result);
++pFlow->totalupdates;
v40 = (float)((float)(v39 / 127.0) * (float)(v36 - v9)) + netTime - v37;
v41 = fmaxf(pFlow->maxlatency, v40);
pFlow->latency = v40 + pFlow->latency;
pFlow->maxlatency = v41;
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: shutdown netchannel // Purpose: shutdown netchannel
// Input : *this - // Input : *this -
@ -73,7 +360,7 @@ double CNetChan::GetTimeConnected(void) const
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CNetChan::_Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow) void CNetChan::_Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow)
{ {
v_NetChan_Shutdown(pChan, szReason, bBadRep, bRemoveNow); CNetChan__Shutdown(pChan, szReason, bBadRep, bRemoveNow);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -82,46 +369,193 @@ void CNetChan::_Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep,
// *pMsg - // *pMsg -
// Output : true on success, false on failure // Output : true on success, false on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool CNetChan::_ProcessMessages(CNetChan* pChan, bf_read* pMsg) bool CNetChan::_ProcessMessages(CNetChan* pChan, bf_read* pBuf)
{ {
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
if (!ThreadInServerFrameThread() || !net_processTimeBudget->GetInt()) if (!net_processTimeBudget.GetInt() || !ThreadInServerFrameThread())
return v_NetChan_ProcessMessages(pChan, pMsg); return pChan->ProcessMessages(pBuf);
const double flStartTime = Plat_FloatTime(); const double flStartTime = Plat_FloatTime();
const bool bResult = v_NetChan_ProcessMessages(pChan, pMsg); const bool bResult = pChan->ProcessMessages(pBuf);
if (!pChan->m_MessageHandler) // NetChannel removed? if (!pChan->m_MessageHandler) // NetChannel removed?
return bResult; return bResult;
CClient* pClient = reinterpret_cast<CClient*>(pChan->m_MessageHandler); CClient* const pClient = reinterpret_cast<CClient*>(pChan->m_MessageHandler);
ServerPlayer_t* pSlot = &g_ServerPlayer[pClient->GetUserID()]; CClientExtended* const pExtended = pClient->GetClientExtended();
if (flStartTime - pSlot->m_flLastNetProcessTime >= 1.0 || // Reset every second.
pSlot->m_flLastNetProcessTime == -1.0) if ((flStartTime - pExtended->GetNetProcessingTimeBase()) > 1.0)
{ {
pSlot->m_flLastNetProcessTime = flStartTime; pExtended->SetNetProcessingTimeBase(flStartTime);
pSlot->m_flCurrentNetProcessTime = 0.0; pExtended->SetNetProcessingTimeMsecs(0.0, 0.0);
} }
pSlot->m_flCurrentNetProcessTime +=
(Plat_FloatTime() * 1000) - (flStartTime * 1000);
if (pSlot->m_flCurrentNetProcessTime > const double flCurrentTime = Plat_FloatTime();
net_processTimeBudget->GetDouble()) pExtended->SetNetProcessingTimeMsecs(flStartTime, flCurrentTime);
{
Warning(eDLL_T::SERVER, "Removing netchannel '%s' ('%s' exceeded frame budget by '%3.1f'ms!)\n",
pChan->GetName(), pChan->GetAddress(), (pSlot->m_flCurrentNetProcessTime - net_processTimeBudget->GetDouble()));
pClient->Disconnect(Reputation_t::REP_MARK_BAD, "#DISCONNECT_NETCHAN_OVERFLOW");
return false; if (pExtended->GetNetProcessingTimeMsecs() > net_processTimeBudget.GetFloat())
} {
Warning(eDLL_T::SERVER, "Removing netchannel '%s' ('%s' exceeded time budget by '%3.1f'ms!)\n",
pChan->GetName(), pChan->GetAddress(), (pExtended->GetNetProcessingTimeMsecs() - net_processTimeBudget.GetFloat()));
pClient->Disconnect(Reputation_t::REP_MARK_BAD, "#DISCONNECT_NETCHAN_OVERFLOW");
return bResult; return false;
}
return bResult;
#else // !CLIENT_DLL #else // !CLIENT_DLL
return v_NetChan_ProcessMessages(pChan, pMsg); return pChan->ProcessMessages(pBuf);
#endif #endif
} }
//-----------------------------------------------------------------------------
// Purpose: process message
// Input : *buf -
// Output : true on success, false on failure
//-----------------------------------------------------------------------------
bool CNetChan::ProcessMessages(bf_read* buf)
{
m_bStopProcessing = false;
const char* showMsgName = net_showmsg->GetString();
const char* blockMsgName = net_blockmsg->GetString();
const int netPeak = net_showpeaks->GetInt();
if (*showMsgName == '0')
{
showMsgName = NULL; // dont do strcmp all the time
}
if (*blockMsgName == '0')
{
blockMsgName = NULL; // dont do strcmp all the time
}
if (netPeak > 0 && netPeak < buf->GetNumBytesLeft())
{
showMsgName = "1"; // show messages for this packet only
}
while (true)
{
int cmd = net_NOP;
while (true)
{
if (buf->GetNumBitsLeft() < NETMSG_TYPE_BITS)
return true; // Reached the end.
if (!NET_ReadMessageType(&cmd, buf) && buf->m_bOverflow)
{
Error(eDLL_T::ENGINE, 0, "%s(%s): Incoming buffer overflow!\n", __FUNCTION__, GetAddress());
m_MessageHandler->ConnectionCrashed("Buffer overflow in net message");
return false;
}
if (cmd <= net_Disconnect)
break; // Either a Disconnect or NOP packet; process it below.
INetMessage* netMsg = FindMessage(cmd);
if (!netMsg)
{
DevWarning(eDLL_T::ENGINE, "%s(%s): Received unknown net message (%i)!\n",
__FUNCTION__, GetAddress(), cmd);
Assert(0);
return false;
}
if (!netMsg->ReadFromBuffer(buf))
{
DevWarning(eDLL_T::ENGINE, "%s(%s): Failed reading message '%s'!\n",
__FUNCTION__, GetAddress(), netMsg->GetName());
Assert(0);
return false;
}
if (showMsgName)
{
if ((*showMsgName == '1') || !Q_stricmp(showMsgName, netMsg->GetName()))
{
Msg(eDLL_T::ENGINE, "%s(%s): Received: %s\n",
__FUNCTION__, GetAddress(), netMsg->ToString());
}
}
if (blockMsgName)
{
if ((*blockMsgName == '1') || !Q_stricmp(blockMsgName, netMsg->GetName()))
{
Msg(eDLL_T::ENGINE, "%s(%s): Blocked: %s\n",
__FUNCTION__, GetAddress(), netMsg->ToString());
continue;
}
}
// Netmessage calls the Process function that was registered by
// it's MessageHandler.
m_bProcessingMessages = true;
const bool bRet = netMsg->Process();
m_bProcessingMessages = false;
// This means we were deleted during the processing of that message.
if (m_bShouldDelete)
{
delete this;
return false;
}
// This means our message buffer was freed or invalidated during
// the processing of that message.
if (m_bStopProcessing)
return false;
if (!bRet)
{
DevWarning(eDLL_T::ENGINE, "%s(%s): Failed processing message '%s'!\n",
__FUNCTION__, GetAddress(), netMsg->GetName());
Assert(0);
return false;
}
if (IsOverflowed())
return false;
}
m_bProcessingMessages = true;
if (cmd == net_NOP) // NOP; continue to next packet.
{
m_bProcessingMessages = false;
continue;
}
else if (cmd == net_Disconnect) // Disconnect request.
{
char reason[1024];
buf->ReadString(reason, sizeof(reason), false);
m_MessageHandler->ConnectionClosing(reason, 1);
m_bProcessingMessages = false;
}
m_bProcessingMessages = false;
if (m_bShouldDelete)
delete this;
return false;
}
}
bool CNetChan::ReadSubChannelData(bf_read& buf)
{
// TODO: rebuild this and hook
return false;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: send message // Purpose: send message
// Input : &msg - // Input : &msg -
@ -129,10 +563,10 @@ bool CNetChan::_ProcessMessages(CNetChan* pChan, bf_read* pMsg)
// bVoice - // bVoice -
// Output : true on success, false on failure // Output : true on success, false on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool CNetChan::SendNetMsg(INetMessage& msg, bool bForceReliable, bool bVoice) bool CNetChan::SendNetMsg(INetMessage& msg, const bool bForceReliable, const bool bVoice)
{ {
if (remote_address.GetType() == netadrtype_t::NA_NULL) if (remote_address.GetType() == netadrtype_t::NA_NULL)
return false; return true;
bf_write* pStream = &m_StreamUnreliable; bf_write* pStream = &m_StreamUnreliable;
@ -142,29 +576,127 @@ bool CNetChan::SendNetMsg(INetMessage& msg, bool bForceReliable, bool bVoice)
if (bVoice) if (bVoice)
pStream = &m_StreamVoice; pStream = &m_StreamVoice;
if (pStream != &m_StreamUnreliable || if (pStream == &m_StreamUnreliable && pStream->GetNumBytesLeft() < NET_UNRELIABLE_STREAM_MINSIZE)
pStream->GetNumBytesLeft() >= NET_UNRELIABLE_STREAM_MINSIZE) return true;
{
AcquireSRWLockExclusive(&LOCK);
pStream->WriteUBitLong(msg.GetType(), NETMSG_TYPE_BITS); AcquireSRWLockExclusive(&m_Lock);
if (!pStream->IsOverflowed())
msg.WriteToBuffer(pStream);
ReleaseSRWLockExclusive(&LOCK); pStream->WriteUBitLong(msg.GetType(), NETMSG_TYPE_BITS);
} const bool ret = msg.WriteToBuffer(pStream);
return true; ReleaseSRWLockExclusive(&m_Lock);
return !pStream->IsOverflowed() && ret;
}
//-----------------------------------------------------------------------------
// Purpose: send data
// Input : &msg -
// bReliable -
// Output : true on success, false on failure
//-----------------------------------------------------------------------------
bool CNetChan::SendData(bf_write& msg, const bool bReliable)
{
// Always queue any pending reliable data ahead of the fragmentation buffer
if (remote_address.GetType() == netadrtype_t::NA_NULL)
return true;
if (msg.GetNumBitsWritten() <= 0)
return true;
if (msg.IsOverflowed() && !bReliable)
return true;
bf_write& buf = bReliable
? m_StreamReliable
: m_StreamUnreliable;
const int dataBits = msg.GetNumBitsWritten();
const int bitsLeft = buf.GetNumBitsLeft();
if (dataBits > bitsLeft)
{
if (bReliable)
{
Error(eDLL_T::ENGINE, 0, "%s(%s): Data too large for reliable buffer (%i > %i)!\n",
__FUNCTION__, GetAddress(), msg.GetNumBytesWritten(), buf.GetNumBytesLeft());
m_MessageHandler->ChannelDisconnect("reliable buffer is full");
}
return false;
}
return buf.WriteBits(msg.GetData(), dataBits);
}
//-----------------------------------------------------------------------------
// Purpose: finds a registered net message by type
// Input : type -
// Output : net message pointer on success, NULL otherwise
//-----------------------------------------------------------------------------
INetMessage* CNetChan::FindMessage(int type)
{
int numtypes = m_NetMessages.Count();
for (int i = 0; i < numtypes; i++)
{
if (m_NetMessages[i]->GetType() == type)
return m_NetMessages[i];
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: registers a net message
// Input : *msg
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CNetChan::RegisterMessage(INetMessage* msg)
{
Assert(msg);
if (FindMessage(msg->GetType()))
{
Assert(0); // Duplicate registration!
return false;
}
m_NetMessages.AddToTail(msg);
msg->SetNetChannel(this);
return true;
}
//-----------------------------------------------------------------------------
// Purpose: free's the receive data fragment list
//-----------------------------------------------------------------------------
void CNetChan::FreeReceiveList()
{
m_ReceiveList.blockSize = NULL;
m_ReceiveList.transferSize = NULL;
if (m_ReceiveList.buffer)
{
delete m_ReceiveList.buffer;
m_ReceiveList.buffer = nullptr;
}
}
//-----------------------------------------------------------------------------
// Purpose: check if there is still data in the reliable waiting buffers
//-----------------------------------------------------------------------------
bool CNetChan::HasPendingReliableData(void)
{
return (m_StreamReliable.GetNumBitsWritten() > 0)
|| (m_WaitingList.Count() > 0);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void VNetChan::Attach() const void VNetChan::Detour(const bool bAttach) const
{ {
DetourAttach((PVOID*)&v_NetChan_Shutdown, &CNetChan::_Shutdown); DetourSetup(&CNetChan__Shutdown, &CNetChan::_Shutdown, bAttach);
DetourAttach((PVOID*)&v_NetChan_ProcessMessages, &CNetChan::_ProcessMessages); DetourSetup(&CNetChan__FlowNewPacket, &CNetChan::_FlowNewPacket, bAttach);
} DetourSetup(&CNetChan__ProcessMessages, &CNetChan::_ProcessMessages, bAttach);
void VNetChan::Detach() const
{
DetourDetach((PVOID*)&v_NetChan_Shutdown, &CNetChan::_Shutdown);
DetourDetach((PVOID*)&v_NetChan_ProcessMessages, &CNetChan::_ProcessMessages);
} }

View File

@ -28,18 +28,23 @@ class CClient;
class CNetChan; class CNetChan;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
struct netframe_t typedef struct netframe_header_s
{ {
float one; float time;
float two; int size;
float three; short choked;
float four; bool valid;
float five; float latency;
float six; } netframe_header_t;
};
typedef struct netframe_s
{
int dropped;
float avg_latency;
} netframe_t;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
struct netflow_t typedef struct netflow_s
{ {
float nextcompute; float nextcompute;
float avgbytespersec; float avgbytespersec;
@ -48,26 +53,30 @@ struct netflow_t
float avgchoke; float avgchoke;
float avglatency; float avglatency;
float latency; float latency;
float maxlatency;
int64_t totalpackets; int64_t totalpackets;
int64_t totalbytes; int64_t totalbytes;
int64_t totalupdates;
int currentindex;
netframe_header_t frame_headers[NET_FRAMES_BACKUP];
netframe_t frames[NET_FRAMES_BACKUP]; netframe_t frames[NET_FRAMES_BACKUP];
netframe_t current_frame; netframe_t* current_frame;
}; } netflow_t;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
struct dataFragments_t struct dataFragments_t
{ {
char* data; char* buffer;
int64_t block_size; int64_t blockSize;
bool m_bIsCompressed; bool isCompressed;
uint8_t gap11[7]; uint8_t gap11[7];
int64_t m_nRawSize; int64_t uncompressedSize;
bool m_bFirstFragment; bool firstFragment;
bool m_bLastFragment; bool lastFragment;
bool m_bIsOutbound; bool isOutbound;
int transferID; int transferID;
int m_nTransferSize; int transferSize;
int m_nCurrentOffset; int currentOffset;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -78,41 +87,39 @@ enum EBufType
BUF_VOICE BUF_VOICE
}; };
inline CMemory p_NetChan_Clear; inline void(*CNetChan__Clear)(CNetChan* pChan, bool bStopProcessing);
inline void(*v_NetChan_Clear)(CNetChan* pChan, bool bStopProcessing); inline void(*CNetChan__Shutdown)(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow);
inline bool(*CNetChan__CanPacket)(const CNetChan* pChan);
inline CMemory p_NetChan_Shutdown; inline void(*CNetChan__FlowNewPacket)(CNetChan* pChan, int flow, int outSeqNr, int inSeqNr, int nChoked, int nDropped, int nSize);
inline void(*v_NetChan_Shutdown)(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow); inline int(*CNetChan__SendDatagram)(CNetChan* pChan, bf_write* pMsg);
inline bool(*CNetChan__ProcessMessages)(CNetChan* pChan, bf_read* pMsg);
inline CMemory p_NetChan_CanPacket;
inline bool(*v_NetChan_CanPacket)(const CNetChan* pChan);
inline CMemory p_NetChan_SendDatagram;
inline int(*v_NetChan_SendDatagram)(CNetChan* pChan, bf_write* pMsg);
inline CMemory p_NetChan_ProcessMessages;
inline bool(*v_NetChan_ProcessMessages)(CNetChan* pChan, bf_read* pMsg);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class CNetChan class CNetChan
{ {
public: public:
~CNetChan()
{
Shutdown("NetChannel removed.", 1, false);
FreeReceiveList();
}
inline const char* GetName(void) const { return m_Name; } inline const char* GetName(void) const { return m_Name; }
inline const char* GetAddress(bool onlyBase = false) const { return remote_address.ToString(onlyBase); } inline const char* GetAddress(bool onlyBase = false) const { return remote_address.ToString(onlyBase); }
inline int GetPort(void) const { return int(ntohs(remote_address.GetPort())); } inline int GetPort(void) const { return int(ntohs(remote_address.GetPort())); }
inline int GetDataRate(void) const { return m_Rate; } inline int GetDataRate(void) const { return m_Rate; }
inline int GetBufferSize(void) const { return NET_FRAMES_BACKUP; } inline int GetBufferSize(void) const { return NET_FRAMES_BACKUP; }
float GetNetworkLoss() const; float GetResendRate() const;
inline float GetLatency(int flow) const { Assert(flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].latency; } inline float GetLatency(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].latency; }
inline float GetAvgChoke(int flow) const { Assert(flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgchoke; } inline float GetAvgChoke(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgchoke; }
inline float GetAvgLatency(int flow) const { Assert(flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avglatency; } inline float GetAvgLatency(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avglatency; }
inline float GetAvgLoss(int flow) const { Assert(flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgloss; } inline float GetAvgLoss(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgloss; }
inline float GetAvgPackets(int flow) const { Assert(flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgpacketspersec; } inline float GetAvgPackets(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgpacketspersec; }
inline float GetAvgData(int flow) const { Assert(flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgbytespersec; } inline float GetAvgData(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].avgbytespersec; }
inline int64_t GetTotalData(int flow) const { Assert(flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].totalbytes; } inline int64_t GetTotalData(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].totalbytes; }
inline int64_t GetTotalPackets(int flow) const { Assert(flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].totalpackets; } inline int64_t GetTotalPackets(int flow) const { Assert(flow >= 0 && flow < SDK_ARRAYSIZE(m_DataFlow)); return m_DataFlow[flow].totalpackets; }
int GetSequenceNr(int flow) const; int GetSequenceNr(int flow) const;
double GetTimeConnected(void) const; double GetTimeConnected(void) const;
@ -121,19 +128,33 @@ public:
inline int GetSocket(void) const { return m_Socket; } inline int GetSocket(void) const { return m_Socket; }
inline const bf_write& GetStreamVoice(void) const { return m_StreamVoice; } inline const bf_write& GetStreamVoice(void) const { return m_StreamVoice; }
inline const netadr_t& GetRemoteAddress(void) const { return remote_address; } inline const netadr_t& GetRemoteAddress(void) const { return remote_address; }
int GetNumBitsWritten(const bool bReliable);
int GetNumBitsLeft(const bool bReliable);
inline bool IsOverflowed(void) const { return m_StreamReliable.IsOverflowed(); } inline bool IsOverflowed(void) const { return m_StreamReliable.IsOverflowed(); }
inline bool CanPacket(void) const { return v_NetChan_CanPacket(this); } bool HasPendingReliableData(void);
inline int SendDatagram(bf_write* pDatagram) { return v_NetChan_SendDatagram(this, pDatagram); }
bool SendNetMsg(INetMessage& msg, bool bForceReliable, bool bVoice);
inline void Clear(bool bStopProcessing) { v_NetChan_Clear(this, bStopProcessing); } inline bool CanPacket(void) const { return CNetChan__CanPacket(this); }
inline void Shutdown(const char* szReason, uint8_t bBadRep, bool bRemoveNow) inline int SendDatagram(bf_write* pDatagram) { return CNetChan__SendDatagram(this, pDatagram); }
{ v_NetChan_Shutdown(this, szReason, bBadRep, bRemoveNow); } bool SendNetMsg(INetMessage& msg, const bool bForceReliable, const bool bVoice);
bool SendData(bf_write& msg, const bool bReliable);
INetMessage* FindMessage(int type);
bool RegisterMessage(INetMessage* msg);
inline void Clear(bool bStopProcessing) { CNetChan__Clear(this, bStopProcessing); }
inline void Shutdown(const char* szReason, uint8_t bBadRep, bool bRemoveNow) { CNetChan__Shutdown(this, szReason, bBadRep, bRemoveNow); }
void FreeReceiveList();
bool ProcessMessages(bf_read* pMsg);
bool ReadSubChannelData(bf_read& buf);
static void _Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow); static void _Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep, bool bRemoveNow);
static bool _ProcessMessages(CNetChan* pChan, bf_read* pMsg); static bool _ProcessMessages(CNetChan* pChan, bf_read* pMsg);
static void _FlowNewPacket(CNetChan* pChan, int flow, int outSeqNr, int inSeqNr, int nChoked, int nDropped, int nSize);
void SetChoked(); void SetChoked();
void SetRemoteFramerate(float flFrameTime, float flFrameTimeStdDeviation); void SetRemoteFramerate(float flFrameTime, float flFrameTimeStdDeviation);
inline void SetRemoteCPUStatistics(uint8_t nStats) { m_nServerCPU = nStats; } inline void SetRemoteCPUStatistics(uint8_t nStats) { m_nServerCPU = nStats; }
@ -143,19 +164,16 @@ public:
bool m_bProcessingMessages; bool m_bProcessingMessages;
bool m_bShouldDelete; bool m_bShouldDelete;
bool m_bStopProcessing; bool m_bStopProcessing;
bool shutting_down; bool m_bShuttingDown;
int m_nOutSequenceNr; int m_nOutSequenceNr;
int m_nInSequenceNr; int m_nInSequenceNr;
int m_nOutSequenceNrAck; int m_nOutSequenceNrAck;
int m_nChokedPackets; int m_nChokedPackets;
int unknown_challenge_var; int m_nRealTimePackets; // Number of packets without pre-scaled frame times.
private: private:
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2)
char pad[8];
#endif
int m_nLastRecvFlags; int m_nLastRecvFlags;
RTL_SRWLOCK LOCK; RTL_SRWLOCK m_Lock;
bf_write m_StreamReliable; bf_write m_StreamReliable;
CUtlMemory<byte> m_ReliableDataBuffer; CUtlMemory<byte> m_ReliableDataBuffer;
bf_write m_StreamUnreliable; bf_write m_StreamUnreliable;
@ -181,11 +199,11 @@ private:
uint32_t m_nSubOutSequenceNr; uint32_t m_nSubOutSequenceNr;
int m_nLastRecvNonce; int m_nLastRecvNonce;
bool m_bUseCompression; bool m_bUseCompression;
uint32_t dword168; uint32_t m_ChallengeNr;
float m_Timeout; float m_Timeout;
INetChannelHandler* m_MessageHandler; INetChannelHandler* m_MessageHandler;
CUtlVector<INetMessage*> m_NetMessages; CUtlVector<INetMessage*> m_NetMessages;
uint64_t qword198; void* m_UnusedInterfacePointer; // Previously: IDemoRecorder* m_DemoRecorder.
int m_nQueuedPackets; int m_nQueuedPackets;
float m_flRemoteFrameTime; float m_flRemoteFrameTime;
float m_flRemoteFrameTimeStdDeviation; float m_flRemoteFrameTimeStdDeviation;
@ -195,7 +213,7 @@ private:
int64_t m_StreamSendBuffer; int64_t m_StreamSendBuffer;
bf_write m_StreamSend; bf_write m_StreamSend;
uint8_t m_bInMatch_maybe; uint8_t m_bInMatch_maybe;
netflow_t m_DataFlow[2]; netflow_t m_DataFlow[MAX_FLOWS];
int m_nLifetimePacketsDropped; int m_nLifetimePacketsDropped;
int m_nSessionPacketsDropped; int m_nSessionPacketsDropped;
int m_nSequencesSkipped_MAYBE; int m_nSequencesSkipped_MAYBE;
@ -205,11 +223,7 @@ private:
char m_Name[NET_CHANNELNAME_MAXLEN]; char m_Name[NET_CHANNELNAME_MAXLEN];
netadr_t remote_address; netadr_t remote_address;
}; };
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2)
static_assert(sizeof(CNetChan) == 0x1AD0);
#else
static_assert(sizeof(CNetChan) == 0x1AC8); static_assert(sizeof(CNetChan) == 0x1AC8);
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: sets the remote frame times // Purpose: sets the remote frame times
@ -237,33 +251,25 @@ class VNetChan : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CNetChan::Clear", p_NetChan_Clear.GetPtr()); LogFunAdr("CNetChan::Clear", CNetChan__Clear);
LogFunAdr("CNetChan::Shutdown", p_NetChan_Shutdown.GetPtr()); LogFunAdr("CNetChan::Shutdown", CNetChan__Shutdown);
LogFunAdr("CNetChan::CanPacket", p_NetChan_CanPacket.GetPtr()); LogFunAdr("CNetChan::CanPacket", CNetChan__CanPacket);
LogFunAdr("CNetChan::SendDatagram", p_NetChan_SendDatagram.GetPtr()); LogFunAdr("CNetChan::FlowNewPacket", CNetChan__FlowNewPacket);
LogFunAdr("CNetChan::ProcessMessages", p_NetChan_ProcessMessages.GetPtr()); LogFunAdr("CNetChan::SendDatagram", CNetChan__SendDatagram);
LogFunAdr("CNetChan::ProcessMessages", CNetChan__ProcessMessages);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
p_NetChan_Clear = g_GameDll.FindPatternSIMD("88 54 24 10 53 55 57"); g_GameDll.FindPatternSIMD("88 54 24 10 53 55 57").GetPtr(CNetChan__Clear);
v_NetChan_Clear = p_NetChan_Clear.RCast<void (*)(CNetChan*, bool)>(); g_GameDll.FindPatternSIMD("48 89 6C 24 18 56 57 41 56 48 83 EC 30 83 B9").GetPtr(CNetChan__Shutdown);
g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B D9 75 15 48 8B 05 ?? ?? ?? ??").GetPtr(CNetChan__CanPacket);
p_NetChan_Shutdown = g_GameDll.FindPatternSIMD("48 89 6C 24 18 56 57 41 56 48 83 EC 30 83 B9"); g_GameDll.FindPatternSIMD("44 89 4C 24 ?? 44 89 44 24 ?? 89 54 24 10 56").GetPtr(CNetChan__FlowNewPacket);
v_NetChan_Shutdown = p_NetChan_Shutdown.RCast<void (*)(CNetChan*, const char*, uint8_t, bool)>(); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 56 57 41 56 41 57 48 83 EC 70").GetPtr(CNetChan__SendDatagram);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B FA").GetPtr(CNetChan__ProcessMessages);
p_NetChan_CanPacket = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 83 B9 ?? ?? ?? ?? ?? 48 8B D9 75 15 48 8B 05 ?? ?? ?? ??");
v_NetChan_CanPacket = p_NetChan_CanPacket.RCast<bool (*)(const CNetChan*)>();
p_NetChan_SendDatagram = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 56 57 41 56 41 57 48 83 EC 70");
v_NetChan_SendDatagram = p_NetChan_SendDatagram.RCast<int (*)(CNetChan*, bf_write*)>();
p_NetChan_ProcessMessages = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B FA");
v_NetChan_ProcessMessages = p_NetChan_ProcessMessages.RCast<bool (*)(CNetChan*, bf_read*)>();
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -95,33 +95,29 @@ void CNetworkStringTableContainer::WriteUpdateMessage(CNetworkStringTableContain
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
if (sv_stats->GetBool()) if (sv_stats->GetBool())
{ {
uint8_t nCPUPercentage = static_cast<uint8_t>(g_pServer->GetCPUUsage() * 100.0f); const uint8_t nCPUPercentage = static_cast<uint8_t>(g_pServer->GetCPUUsage() * 100.0f);
SVC_ServerTick serverTick(g_pServer->GetTick(), *host_frametime_unbounded, *host_frametime_stddeviation, nCPUPercentage); SVC_ServerTick serverTick(g_pServer->GetTick(), *host_frametime_unbounded, *host_frametime_stddeviation, nCPUPercentage);
serverTick.m_nGroup = 0; serverTick.m_nGroup = 0;
serverTick.m_bReliable = true; serverTick.m_bReliable = true;
serverTick.m_NetTick.m_nCommandTick = -1; // Statistics only, see 'CClientState::VProcessServerTick'.
// -1 means we update statistics only; see 'CClientState::VProcessServerTick()'.
serverTick.m_NetTick.m_nCommandTick = -1;
pMsg->WriteUBitLong(serverTick.GetType(), NETMSG_TYPE_BITS); pMsg->WriteUBitLong(serverTick.GetType(), NETMSG_TYPE_BITS);
if (!pMsg->IsOverflowed()) if (!pMsg->IsOverflowed())
{ {
serverTick.WriteToBuffer(pMsg); serverTick.WriteToBuffer(pMsg);
} }
} }
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
v_CNetworkStringTableContainer__WriteUpdateMessage(thisp, pClient, nTickAck, pMsg);
Assert(!pMsg->IsOverflowed(), "Snapshot buffer overflowed before string table update!");
CNetworkStringTableContainer__WriteUpdateMessage(thisp, pClient, nTickAck, pMsg);
} }
void VNetworkStringTableContainer::Attach() const void VNetworkStringTableContainer::Detour(const bool bAttach) const
{ {
#if !defined (CLIENT_DLL) && !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) // TODO: doesn't work properly for S0/S1 yet. DetourSetup(&CNetworkStringTableContainer__WriteUpdateMessage, &CNetworkStringTableContainer::WriteUpdateMessage, bAttach);
DetourAttach(&v_CNetworkStringTableContainer__WriteUpdateMessage, &CNetworkStringTableContainer::WriteUpdateMessage);
#endif // !CLIENT_DLL && !GAMEDLL_S0 && !GAMEDLL_S1
} }
void VNetworkStringTableContainer::Detach() const
{
#if !defined (CLIENT_DLL) && !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) // TODO: doesn't work properly for S0/S1 yet.
DetourDetach(&v_CNetworkStringTableContainer__WriteUpdateMessage, &CNetworkStringTableContainer::WriteUpdateMessage);
#endif // !CLIENT_DLL && !GAMEDLL_S0 && !GAMEDLL_S1
}

View File

@ -9,19 +9,32 @@
#define NETWORKSTRINGTABLE_H #define NETWORKSTRINGTABLE_H
#include "tier0/fasttimer.h" #include "tier0/fasttimer.h"
#include "tier1/utlvector.h" #include "tier1/utlvector.h"
#include "tier1/utlhashtable.h"
#include "tier1/bitbuf.h" #include "tier1/bitbuf.h"
#include "public/networkstringtabledefs.h"
#include "client/client.h" #include "client/client.h"
typedef int TABLEID;
class INetworkStringTable
{
INetworkStringTable* m_pVTable;
};
class CNetworkStringTable : public INetworkStringTable class CNetworkStringTable : public INetworkStringTable
{ {
public: public:
// Updating/Writing
virtual bool WriteStringTable(bf_write& buf) = 0;
virtual bool ReadStringTable(bf_read& buf) = 0;
virtual void ParseUpdate(bf_read& buf, int numStrings) = 0;
virtual pfnStringChanged GetCallback(void) = 0;
virtual int WriteUpdate(CClient* const client, bf_write& buf, int tickAck) = 0;
virtual bool WriteBaselines(SVC_CreateStringTable& msg, char* msgBuffer, int msgBufferSize) = 0;
virtual void PurgeAllClientSide(void) = 0;
virtual void EnableRollback(bool bState) = 0;
// TODO[ AMOS ]: there are a few more entries below in the vftable that
// need to be mapped out, most of them set/get bit fields;
// see [ r5apex_ds + 0x1329888 ]
TABLEID GetTableId(void) const; TABLEID GetTableId(void) const;
int GetMaxStrings(void) const; int GetMaxStrings(void) const;
const char* GetTableName(void) const; const char* GetTableName(void) const;
@ -41,42 +54,39 @@ private:
// !TODO // !TODO
}; };
class CNetworkStringTableContainer : public INetworkStringTable class CNetworkStringTableContainer : public INetworkStringTableContainer
{ {
public: public:
static void WriteUpdateMessage(CNetworkStringTableContainer* thisp, CClient* client, unsigned int tick_ack, bf_write* msg); static void WriteUpdateMessage(CNetworkStringTableContainer* thisp, CClient* client, unsigned int tick_ack, bf_write* msg);
// Guards so game .dll can't create tables at the wrong time
inline void AllowCreation(bool state) { m_bAllowCreation = state; }
private: private:
bool m_bAllowCreation; // create guard bool m_bAllowCreation; // create guard
int m_nTickCount; // current tick int m_nTickCount; // current tick
bool m_bLocked; // currently locked? bool m_bLocked; // currently locked?
bool m_bEnableRollback; // enables rollback feature bool m_bEnableRollback; // enables rollback feature
CUtlVector < CNetworkStringTable* > m_Tables; // the string tables CUtlVector < CNetworkStringTable* > m_Tables; // the string tables
}; };
inline CMemory p_CNetworkStringTableContainer__WriteUpdateMessage; inline void (*CNetworkStringTableContainer__WriteUpdateMessage)(CNetworkStringTableContainer* thisp, CClient* client, unsigned int tick_ack, bf_write* msg);
inline void (*v_CNetworkStringTableContainer__WriteUpdateMessage)(CNetworkStringTableContainer* thisp, CClient* client, unsigned int tick_ack, bf_write* msg);
class VNetworkStringTableContainer : public IDetour class VNetworkStringTableContainer : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
LogFunAdr("CNetworkStringTableContainer::WriteUpdateMessage", p_CNetworkStringTableContainer__WriteUpdateMessage.GetPtr()); LogFunAdr("CNetworkStringTableContainer::WriteUpdateMessage", CNetworkStringTableContainer__WriteUpdateMessage);
} }
virtual void GetFun(void) const virtual void GetFun(void) const
{ {
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) g_GameDll.FindPatternSIMD("48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 45 33 ED")
p_CNetworkStringTableContainer__WriteUpdateMessage = g_GameDll.FindPatternSIMD("48 89 74 24 ?? 55 57 41 54 41 55 41 56 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ??"); .GetPtr(CNetworkStringTableContainer__WriteUpdateMessage);
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_CNetworkStringTableContainer__WriteUpdateMessage = g_GameDll.FindPatternSIMD("48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 45 33 ED");
#endif
v_CNetworkStringTableContainer__WriteUpdateMessage =
p_CNetworkStringTableContainer__WriteUpdateMessage.RCast<void (*)(CNetworkStringTableContainer*, CClient*, unsigned int, bf_write*)>();
} }
virtual void GetVar(void) const { } virtual void GetVar(void) const { }
virtual void GetCon(void) const { } virtual void GetCon(void) const { }
virtual void Attach(void) const; virtual void Detour(const bool bAttach) const;
virtual void Detach(void) const;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -7,24 +7,5 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "tier1/cvar.h" #include "tier1/cvar.h"
#include "engine/sdk_dll.h" #include "engine/sdk_dll.h"
#ifndef DEDICATED
#include "gameui/IBrowser.h"
#include "gameui/IConsole.h"
#endif // !DEDICATED
//----------------------------------------------------------------------------- CEngineSDK g_EngineSDK;
// Purpose:
//-----------------------------------------------------------------------------
void CEngineSDK::FixedFrame()
{
for (;;)
{
#ifndef DEDICATED
g_pBrowser->Think();
g_pConsole->Think();
#endif // !DEDICATED
std::this_thread::sleep_for(IntervalToDuration(sdk_fixedframe_tickinterval->GetFloat()));
}
}
CEngineSDK* g_EngineSDK = new CEngineSDK();

View File

@ -4,9 +4,8 @@
class CEngineSDK class CEngineSDK
{ {
public: public:
void FixedFrame();
}; };
extern CEngineSDK* g_EngineSDK; extern CEngineSDK g_EngineSDK;
#endif // SDK_DLL_H #endif // SDK_DLL_H

View File

@ -1,27 +1,62 @@
//===========================================================================// //===========================================================================//
// //
// Purpose: server side datablock sender // Purpose: server side data block sender
// //
//===========================================================================// //===========================================================================//
#include "engine/client/client.h" #include "engine/client/client.h"
#include "common/proto_oob.h"
#include "datablock_sender.h" #include "datablock_sender.h"
//----------------------------------------------------------------------------- static ConVar net_compressDataBlockLzAcceleration("net_compressDataBlockLzAcceleration", "1", FCVAR_DEVELOPMENTONLY, "The acceleration value for LZ4 data block compression");
// Purpose:
//-----------------------------------------------------------------------------
ServerDataBlockSender::~ServerDataBlockSender()
{
v_ServerDataBlockSender__Destructor(this);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: sends the datablock // Purpose: sends the data block
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ServerDataBlockSender::SendDataBlock(short unk0, int unk1, void ServerDataBlockSender::SendDataBlock(const short transferId, const int transferSize,
short unk2, short unk3, const void* buffer, int length) const short transferNr, const short blockNr, const uint8_t* const blockData, const int blockSize)
{ {
v_ServerDataBlockSender__SendDataBlock(this, unk0, unk1, const CClient* const cl = m_pClient;
unk2, unk3, buffer, length);
if (!cl)
{
Assert(0, "ServerDataBlockSender::SendDataBlock() called without a valid client handle!");
return;
}
const CNetChan* const chan = cl->m_NetChannel;
if (!chan)
{
Assert(0, "ServerDataBlockSender::SendDataBlock() called without a valid net channel!");
return;
}
char dataBuf[DATABLOCK_FRAGMENT_PACKET_SIZE];
bf_write buf(&dataBuf, sizeof(dataBuf));
// msg data (gets processed on client's out of band packet handler)
buf.WriteLong(CONNECTIONLESS_HEADER);
buf.WriteByte(S2C_DATABLOCK_FRAGMENT);
// transfer info
buf.WriteByte(transferId);
buf.WriteLong(transferSize);
buf.WriteByte(transferNr);
// block info
buf.WriteByte(blockNr);
buf.WriteLong(blockSize);
// block data
buf.WriteBytes(blockData, blockSize);
// send the data block packet
v_NET_SendPacket(NULL,
chan->GetSocket(),
chan->GetRemoteAddress(),
buf.GetData(),
buf.GetNumBytesWritten(),
NULL, false, NULL, true);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -29,26 +64,25 @@ void ServerDataBlockSender::SendDataBlock(short unk0, int unk1,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
float ServerDataBlockSender::GetResendRate() const float ServerDataBlockSender::GetResendRate() const
{ {
float flRet = 0.0f; const CClient* const pClient = m_pClient;
if (!m_pClient) if (!pClient)
return flRet; return 0.0f;
const CNetChan* const pChan = pClient->GetNetChan();
CNetChan* pChan = m_pClient->GetNetChan();
if (!pChan) if (!pChan)
return flRet; return 0.0f;
if (!m_bStartedTransfer) if (m_bStartedTransfer)
{ return 0.0f;
flRet = pChan->GetNetworkLoss();
if (flRet < net_datablock_networkLossForSlowSpeed->GetFloat()) const float netResendRate = pChan->GetResendRate();
{
return m_flResendRate;
}
}
return flRet; if (netResendRate < net_datablock_networkLossForSlowSpeed->GetFloat())
return m_flResendRate;
return netResendRate;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -58,3 +92,57 @@ const char* ServerDataBlockSender::GetReceiverName() const
{ {
return m_pClient->m_szServerName; return m_pClient->m_szServerName;
} }
//-----------------------------------------------------------------------------
// Purpose: write the whole data in the data block scratch buffer
//-----------------------------------------------------------------------------
void ServerDataBlockSender::WriteDataBlock(const uint8_t* const sourceData, const int dataSize,
const bool isMultiplayer, const char* const debugName)
{
AcquireSRWLockExclusive(&m_Lock);
ServerDataBlockHeader_s* const pHeader = reinterpret_cast<ServerDataBlockHeader_s*>(m_pScratchBuffer);
bool copyRaw = true;
int actualDataSize = dataSize;
if (net_compressDataBlock->GetBool())
{
const int encodedSize = LZ4_compress_fast((const char*)sourceData, (char*)m_pScratchBuffer + sizeof(ServerDataBlockHeader_s),
dataSize, SNAPSHOT_SCRATCH_BUFFER_SIZE, net_compressDataBlockLzAcceleration.GetInt());
// this shouldn't happen at all
if (!encodedSize)
{
Assert(0);
Error(eDLL_T::SERVER, 0, "LZ4 error compressing data block for client.\n");
}
// make sure the encoded data is smaller than the raw data, in some cases
// this might turn larger which means we should just send raw data
else if (encodedSize < dataSize)
{
actualDataSize = encodedSize;
pHeader->isCompressed = true;
copyRaw = false;
}
}
// in case no compression was performed, we send the raw data
if (copyRaw)
{
// this should equal the dataSize at this point, even if compression failed
Assert(actualDataSize == dataSize);
pHeader->isCompressed = false;
memcpy(m_pScratchBuffer + sizeof(ServerDataBlockHeader_s), sourceData, actualDataSize);
}
// NOTE: we copy data in the scratch buffer with an offset of
// sizeof(ServerDataBlockHeader_s), the header gets send up as well so we
// have to take this into account !!!
StartBlockSender(actualDataSize + sizeof(ServerDataBlockHeader_s), isMultiplayer, debugName);
ReleaseSRWLockExclusive(&m_Lock);
}

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