aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig11
-rw-r--r--.git-blame-ignore-revs3
-rw-r--r--.github/pull_request_template.md18
-rw-r--r--.github/workflows/ci.yml4
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj (renamed from NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj)1341
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj.filters (renamed from NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters)3576
-rw-r--r--NorthstarDLL/audio.cpp (renamed from NorthstarDedicatedTest/audio.cpp)92
-rw-r--r--NorthstarDLL/audio.h (renamed from NorthstarDedicatedTest/audio.h)4
-rw-r--r--NorthstarDLL/audio_asm.asm (renamed from NorthstarDedicatedTest/audio_asm.asm)2
-rw-r--r--NorthstarDLL/bansystem.cpp222
-rw-r--r--NorthstarDLL/bansystem.h (renamed from NorthstarDedicatedTest/bansystem.h)5
-rw-r--r--NorthstarDLL/bitbuf.h (renamed from NorthstarDedicatedTest/bitbuf.h)2
-rw-r--r--NorthstarDLL/bits.cpp (renamed from NorthstarDedicatedTest/bits.cpp)0
-rw-r--r--NorthstarDLL/bits.h (renamed from NorthstarDedicatedTest/bits.h)0
-rw-r--r--NorthstarDLL/buildainfile.cpp (renamed from NorthstarDedicatedTest/buildainfile.cpp)74
-rw-r--r--NorthstarDLL/chatcommand.cpp (renamed from NorthstarDedicatedTest/chatcommand.cpp)8
-rw-r--r--NorthstarDLL/clientauthhooks.cpp (renamed from NorthstarDedicatedTest/clientauthhooks.cpp)29
-rw-r--r--NorthstarDLL/clientchathooks.cpp83
-rw-r--r--NorthstarDLL/clientruihooks.cpp24
-rw-r--r--NorthstarDLL/clientvideooverrides.cpp42
-rw-r--r--NorthstarDLL/color.h (renamed from NorthstarDedicatedTest/color.h)0
-rw-r--r--NorthstarDLL/concommand.cpp (renamed from NorthstarDedicatedTest/concommand.cpp)53
-rw-r--r--NorthstarDLL/concommand.h (renamed from NorthstarDedicatedTest/concommand.h)23
-rw-r--r--NorthstarDLL/convar.cpp (renamed from NorthstarDedicatedTest/convar.cpp)36
-rw-r--r--NorthstarDLL/convar.h (renamed from NorthstarDedicatedTest/convar.h)51
-rw-r--r--NorthstarDLL/crashhandler.cpp (renamed from NorthstarDedicatedTest/logging.cpp)289
-rw-r--r--NorthstarDLL/crashhandler.h4
-rw-r--r--NorthstarDLL/cvar.cpp (renamed from NorthstarDedicatedTest/cvar.cpp)8
-rw-r--r--NorthstarDLL/cvar.h (renamed from NorthstarDedicatedTest/cvar.h)8
-rw-r--r--NorthstarDLL/debugoverlay.cpp (renamed from NorthstarDedicatedTest/debugoverlay.cpp)64
-rw-r--r--NorthstarDLL/dedicated.cpp293
-rw-r--r--NorthstarDLL/dedicated.h3
-rw-r--r--NorthstarDLL/dedicatedmaterialsystem.cpp41
-rw-r--r--NorthstarDLL/demofixes.cpp26
-rw-r--r--NorthstarDLL/dllmain.cpp168
-rw-r--r--NorthstarDLL/exploitfixes.cpp449
-rw-r--r--NorthstarDLL/exploitfixes_lzss.cpp79
-rw-r--r--NorthstarDLL/exploitfixes_utf8parser.cpp200
-rw-r--r--NorthstarDLL/filesystem.cpp186
-rw-r--r--NorthstarDLL/filesystem.h (renamed from NorthstarDedicatedTest/filesystem.h)14
-rw-r--r--NorthstarDLL/hooks.cpp398
-rw-r--r--NorthstarDLL/hooks.h311
-rw-r--r--NorthstarDLL/host.cpp73
-rw-r--r--NorthstarDLL/hoststate.cpp116
-rw-r--r--NorthstarDLL/hoststate.h45
-rw-r--r--NorthstarDLL/include/MinHook.h (renamed from NorthstarDedicatedTest/include/MinHook.h)0
-rw-r--r--NorthstarDLL/include/MinHook.x64.lib (renamed from NorthstarDedicatedTest/include/MinHook.x64.lib)bin32400 -> 32401 bytes
-rw-r--r--NorthstarDLL/include/crypto/__DECC_INCLUDE_EPILOGUE.H (renamed from NorthstarDedicatedTest/include/crypto/__DECC_INCLUDE_EPILOGUE.H)0
-rw-r--r--NorthstarDLL/include/crypto/__DECC_INCLUDE_PROLOGUE.H (renamed from NorthstarDedicatedTest/include/crypto/__DECC_INCLUDE_PROLOGUE.H)0
-rw-r--r--NorthstarDLL/include/crypto/aes_platform.h (renamed from NorthstarDedicatedTest/include/crypto/aes_platform.h)0
-rw-r--r--NorthstarDLL/include/crypto/aria.h (renamed from NorthstarDedicatedTest/include/crypto/aria.h)0
-rw-r--r--NorthstarDLL/include/crypto/asn1.h (renamed from NorthstarDedicatedTest/include/crypto/asn1.h)0
-rw-r--r--NorthstarDLL/include/crypto/asn1_dsa.h (renamed from NorthstarDedicatedTest/include/crypto/asn1_dsa.h)0
-rw-r--r--NorthstarDLL/include/crypto/asn1err.h (renamed from NorthstarDedicatedTest/include/crypto/asn1err.h)0
-rw-r--r--NorthstarDLL/include/crypto/async.h (renamed from NorthstarDedicatedTest/include/crypto/async.h)0
-rw-r--r--NorthstarDLL/include/crypto/asyncerr.h (renamed from NorthstarDedicatedTest/include/crypto/asyncerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/bioerr.h (renamed from NorthstarDedicatedTest/include/crypto/bioerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/bn.h (renamed from NorthstarDedicatedTest/include/crypto/bn.h)0
-rw-r--r--NorthstarDLL/include/crypto/bn_conf.h (renamed from NorthstarDedicatedTest/include/crypto/bn_conf.h)0
-rw-r--r--NorthstarDLL/include/crypto/bn_conf.h.in (renamed from NorthstarDedicatedTest/include/crypto/bn_conf.h.in)0
-rw-r--r--NorthstarDLL/include/crypto/bn_dh.h (renamed from NorthstarDedicatedTest/include/crypto/bn_dh.h)0
-rw-r--r--NorthstarDLL/include/crypto/bn_srp.h (renamed from NorthstarDedicatedTest/include/crypto/bn_srp.h)0
-rw-r--r--NorthstarDLL/include/crypto/bnerr.h (renamed from NorthstarDedicatedTest/include/crypto/bnerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/buffererr.h (renamed from NorthstarDedicatedTest/include/crypto/buffererr.h)0
-rw-r--r--NorthstarDLL/include/crypto/chacha.h (renamed from NorthstarDedicatedTest/include/crypto/chacha.h)0
-rw-r--r--NorthstarDLL/include/crypto/cmll_platform.h (renamed from NorthstarDedicatedTest/include/crypto/cmll_platform.h)0
-rw-r--r--NorthstarDLL/include/crypto/cmperr.h (renamed from NorthstarDedicatedTest/include/crypto/cmperr.h)0
-rw-r--r--NorthstarDLL/include/crypto/cmserr.h (renamed from NorthstarDedicatedTest/include/crypto/cmserr.h)0
-rw-r--r--NorthstarDLL/include/crypto/comperr.h (renamed from NorthstarDedicatedTest/include/crypto/comperr.h)0
-rw-r--r--NorthstarDLL/include/crypto/conferr.h (renamed from NorthstarDedicatedTest/include/crypto/conferr.h)0
-rw-r--r--NorthstarDLL/include/crypto/crmferr.h (renamed from NorthstarDedicatedTest/include/crypto/crmferr.h)0
-rw-r--r--NorthstarDLL/include/crypto/cryptlib.h (renamed from NorthstarDedicatedTest/include/crypto/cryptlib.h)0
-rw-r--r--NorthstarDLL/include/crypto/cryptoerr.h (renamed from NorthstarDedicatedTest/include/crypto/cryptoerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/cterr.h (renamed from NorthstarDedicatedTest/include/crypto/cterr.h)0
-rw-r--r--NorthstarDLL/include/crypto/ctype.h (renamed from NorthstarDedicatedTest/include/crypto/ctype.h)0
-rw-r--r--NorthstarDLL/include/crypto/decoder.h (renamed from NorthstarDedicatedTest/include/crypto/decoder.h)0
-rw-r--r--NorthstarDLL/include/crypto/decodererr.h (renamed from NorthstarDedicatedTest/include/crypto/decodererr.h)0
-rw-r--r--NorthstarDLL/include/crypto/des_platform.h (renamed from NorthstarDedicatedTest/include/crypto/des_platform.h)0
-rw-r--r--NorthstarDLL/include/crypto/dh.h (renamed from NorthstarDedicatedTest/include/crypto/dh.h)0
-rw-r--r--NorthstarDLL/include/crypto/dherr.h (renamed from NorthstarDedicatedTest/include/crypto/dherr.h)0
-rw-r--r--NorthstarDLL/include/crypto/dsa.h (renamed from NorthstarDedicatedTest/include/crypto/dsa.h)0
-rw-r--r--NorthstarDLL/include/crypto/dsaerr.h (renamed from NorthstarDedicatedTest/include/crypto/dsaerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/dso_conf.h (renamed from NorthstarDedicatedTest/include/crypto/dso_conf.h)0
-rw-r--r--NorthstarDLL/include/crypto/dso_conf.h.in (renamed from NorthstarDedicatedTest/include/crypto/dso_conf.h.in)0
-rw-r--r--NorthstarDLL/include/crypto/ec.h (renamed from NorthstarDedicatedTest/include/crypto/ec.h)0
-rw-r--r--NorthstarDLL/include/crypto/ecerr.h (renamed from NorthstarDedicatedTest/include/crypto/ecerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/ecx.h (renamed from NorthstarDedicatedTest/include/crypto/ecx.h)0
-rw-r--r--NorthstarDLL/include/crypto/encoder.h (renamed from NorthstarDedicatedTest/include/crypto/encoder.h)0
-rw-r--r--NorthstarDLL/include/crypto/encodererr.h (renamed from NorthstarDedicatedTest/include/crypto/encodererr.h)0
-rw-r--r--NorthstarDLL/include/crypto/engine.h (renamed from NorthstarDedicatedTest/include/crypto/engine.h)0
-rw-r--r--NorthstarDLL/include/crypto/engineerr.h (renamed from NorthstarDedicatedTest/include/crypto/engineerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/err.h (renamed from NorthstarDedicatedTest/include/crypto/err.h)0
-rw-r--r--NorthstarDLL/include/crypto/ess.h (renamed from NorthstarDedicatedTest/include/crypto/ess.h)0
-rw-r--r--NorthstarDLL/include/crypto/esserr.h (renamed from NorthstarDedicatedTest/include/crypto/esserr.h)0
-rw-r--r--NorthstarDLL/include/crypto/evp.h (renamed from NorthstarDedicatedTest/include/crypto/evp.h)0
-rw-r--r--NorthstarDLL/include/crypto/evperr.h (renamed from NorthstarDedicatedTest/include/crypto/evperr.h)0
-rw-r--r--NorthstarDLL/include/crypto/httperr.h (renamed from NorthstarDedicatedTest/include/crypto/httperr.h)0
-rw-r--r--NorthstarDLL/include/crypto/lhash.h (renamed from NorthstarDedicatedTest/include/crypto/lhash.h)0
-rw-r--r--NorthstarDLL/include/crypto/md32_common.h (renamed from NorthstarDedicatedTest/include/crypto/md32_common.h)0
-rw-r--r--NorthstarDLL/include/crypto/modes.h (renamed from NorthstarDedicatedTest/include/crypto/modes.h)0
-rw-r--r--NorthstarDLL/include/crypto/objects.h (renamed from NorthstarDedicatedTest/include/crypto/objects.h)0
-rw-r--r--NorthstarDLL/include/crypto/objectserr.h (renamed from NorthstarDedicatedTest/include/crypto/objectserr.h)0
-rw-r--r--NorthstarDLL/include/crypto/ocsperr.h (renamed from NorthstarDedicatedTest/include/crypto/ocsperr.h)0
-rw-r--r--NorthstarDLL/include/crypto/pem.h (renamed from NorthstarDedicatedTest/include/crypto/pem.h)0
-rw-r--r--NorthstarDLL/include/crypto/pemerr.h (renamed from NorthstarDedicatedTest/include/crypto/pemerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/pkcs12err.h (renamed from NorthstarDedicatedTest/include/crypto/pkcs12err.h)0
-rw-r--r--NorthstarDLL/include/crypto/pkcs7.h (renamed from NorthstarDedicatedTest/include/crypto/pkcs7.h)0
-rw-r--r--NorthstarDLL/include/crypto/pkcs7err.h (renamed from NorthstarDedicatedTest/include/crypto/pkcs7err.h)0
-rw-r--r--NorthstarDLL/include/crypto/poly1305.h (renamed from NorthstarDedicatedTest/include/crypto/poly1305.h)0
-rw-r--r--NorthstarDLL/include/crypto/ppc_arch.h (renamed from NorthstarDedicatedTest/include/crypto/ppc_arch.h)0
-rw-r--r--NorthstarDLL/include/crypto/punycode.h (renamed from NorthstarDedicatedTest/include/crypto/punycode.h)0
-rw-r--r--NorthstarDLL/include/crypto/rand.h (renamed from NorthstarDedicatedTest/include/crypto/rand.h)0
-rw-r--r--NorthstarDLL/include/crypto/rand_pool.h (renamed from NorthstarDedicatedTest/include/crypto/rand_pool.h)0
-rw-r--r--NorthstarDLL/include/crypto/randerr.h (renamed from NorthstarDedicatedTest/include/crypto/randerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/rsa.h (renamed from NorthstarDedicatedTest/include/crypto/rsa.h)0
-rw-r--r--NorthstarDLL/include/crypto/rsaerr.h (renamed from NorthstarDedicatedTest/include/crypto/rsaerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/security_bits.h (renamed from NorthstarDedicatedTest/include/crypto/security_bits.h)0
-rw-r--r--NorthstarDLL/include/crypto/sha.h (renamed from NorthstarDedicatedTest/include/crypto/sha.h)0
-rw-r--r--NorthstarDLL/include/crypto/siphash.h (renamed from NorthstarDedicatedTest/include/crypto/siphash.h)0
-rw-r--r--NorthstarDLL/include/crypto/siv.h (renamed from NorthstarDedicatedTest/include/crypto/siv.h)0
-rw-r--r--NorthstarDLL/include/crypto/sm2.h (renamed from NorthstarDedicatedTest/include/crypto/sm2.h)0
-rw-r--r--NorthstarDLL/include/crypto/sm2err.h (renamed from NorthstarDedicatedTest/include/crypto/sm2err.h)0
-rw-r--r--NorthstarDLL/include/crypto/sm4.h (renamed from NorthstarDedicatedTest/include/crypto/sm4.h)0
-rw-r--r--NorthstarDLL/include/crypto/sparc_arch.h (renamed from NorthstarDedicatedTest/include/crypto/sparc_arch.h)0
-rw-r--r--NorthstarDLL/include/crypto/sparse_array.h (renamed from NorthstarDedicatedTest/include/crypto/sparse_array.h)0
-rw-r--r--NorthstarDLL/include/crypto/store.h (renamed from NorthstarDedicatedTest/include/crypto/store.h)0
-rw-r--r--NorthstarDLL/include/crypto/storeerr.h (renamed from NorthstarDedicatedTest/include/crypto/storeerr.h)0
-rw-r--r--NorthstarDLL/include/crypto/tserr.h (renamed from NorthstarDedicatedTest/include/crypto/tserr.h)0
-rw-r--r--NorthstarDLL/include/crypto/types.h (renamed from NorthstarDedicatedTest/include/crypto/types.h)0
-rw-r--r--NorthstarDLL/include/crypto/uierr.h (renamed from NorthstarDedicatedTest/include/crypto/uierr.h)0
-rw-r--r--NorthstarDLL/include/crypto/x509.h (renamed from NorthstarDedicatedTest/include/crypto/x509.h)0
-rw-r--r--NorthstarDLL/include/crypto/x509err.h (renamed from NorthstarDedicatedTest/include/crypto/x509err.h)0
-rw-r--r--NorthstarDLL/include/crypto/x509v3err.h (renamed from NorthstarDedicatedTest/include/crypto/x509v3err.h)0
-rw-r--r--NorthstarDLL/include/httplib.h (renamed from NorthstarDedicatedTest/include/httplib.h)0
-rw-r--r--NorthstarDLL/include/internal/__DECC_INCLUDE_EPILOGUE.H (renamed from NorthstarDedicatedTest/include/internal/__DECC_INCLUDE_EPILOGUE.H)0
-rw-r--r--NorthstarDLL/include/internal/__DECC_INCLUDE_PROLOGUE.H (renamed from NorthstarDedicatedTest/include/internal/__DECC_INCLUDE_PROLOGUE.H)0
-rw-r--r--NorthstarDLL/include/internal/asn1.h (renamed from NorthstarDedicatedTest/include/internal/asn1.h)0
-rw-r--r--NorthstarDLL/include/internal/bio.h (renamed from NorthstarDedicatedTest/include/internal/bio.h)0
-rw-r--r--NorthstarDLL/include/internal/comp.h (renamed from NorthstarDedicatedTest/include/internal/comp.h)0
-rw-r--r--NorthstarDLL/include/internal/conf.h (renamed from NorthstarDedicatedTest/include/internal/conf.h)0
-rw-r--r--NorthstarDLL/include/internal/constant_time.h (renamed from NorthstarDedicatedTest/include/internal/constant_time.h)0
-rw-r--r--NorthstarDLL/include/internal/core.h (renamed from NorthstarDedicatedTest/include/internal/core.h)0
-rw-r--r--NorthstarDLL/include/internal/cryptlib.h (renamed from NorthstarDedicatedTest/include/internal/cryptlib.h)0
-rw-r--r--NorthstarDLL/include/internal/dane.h (renamed from NorthstarDedicatedTest/include/internal/dane.h)0
-rw-r--r--NorthstarDLL/include/internal/deprecated.h (renamed from NorthstarDedicatedTest/include/internal/deprecated.h)0
-rw-r--r--NorthstarDLL/include/internal/der.h (renamed from NorthstarDedicatedTest/include/internal/der.h)0
-rw-r--r--NorthstarDLL/include/internal/dso.h (renamed from NorthstarDedicatedTest/include/internal/dso.h)0
-rw-r--r--NorthstarDLL/include/internal/dsoerr.h (renamed from NorthstarDedicatedTest/include/internal/dsoerr.h)0
-rw-r--r--NorthstarDLL/include/internal/endian.h (renamed from NorthstarDedicatedTest/include/internal/endian.h)0
-rw-r--r--NorthstarDLL/include/internal/err.h (renamed from NorthstarDedicatedTest/include/internal/err.h)0
-rw-r--r--NorthstarDLL/include/internal/ffc.h (renamed from NorthstarDedicatedTest/include/internal/ffc.h)0
-rw-r--r--NorthstarDLL/include/internal/ktls.h (renamed from NorthstarDedicatedTest/include/internal/ktls.h)0
-rw-r--r--NorthstarDLL/include/internal/namemap.h (renamed from NorthstarDedicatedTest/include/internal/namemap.h)0
-rw-r--r--NorthstarDLL/include/internal/nelem.h (renamed from NorthstarDedicatedTest/include/internal/nelem.h)0
-rw-r--r--NorthstarDLL/include/internal/numbers.h (renamed from NorthstarDedicatedTest/include/internal/numbers.h)0
-rw-r--r--NorthstarDLL/include/internal/o_dir.h (renamed from NorthstarDedicatedTest/include/internal/o_dir.h)0
-rw-r--r--NorthstarDLL/include/internal/packet.h (renamed from NorthstarDedicatedTest/include/internal/packet.h)0
-rw-r--r--NorthstarDLL/include/internal/param_build_set.h (renamed from NorthstarDedicatedTest/include/internal/param_build_set.h)0
-rw-r--r--NorthstarDLL/include/internal/passphrase.h (renamed from NorthstarDedicatedTest/include/internal/passphrase.h)0
-rw-r--r--NorthstarDLL/include/internal/property.h (renamed from NorthstarDedicatedTest/include/internal/property.h)0
-rw-r--r--NorthstarDLL/include/internal/propertyerr.h (renamed from NorthstarDedicatedTest/include/internal/propertyerr.h)0
-rw-r--r--NorthstarDLL/include/internal/provider.h (renamed from NorthstarDedicatedTest/include/internal/provider.h)0
-rw-r--r--NorthstarDLL/include/internal/refcount.h (renamed from NorthstarDedicatedTest/include/internal/refcount.h)0
-rw-r--r--NorthstarDLL/include/internal/sha3.h (renamed from NorthstarDedicatedTest/include/internal/sha3.h)0
-rw-r--r--NorthstarDLL/include/internal/sizes.h (renamed from NorthstarDedicatedTest/include/internal/sizes.h)0
-rw-r--r--NorthstarDLL/include/internal/sm3.h (renamed from NorthstarDedicatedTest/include/internal/sm3.h)0
-rw-r--r--NorthstarDLL/include/internal/sockets.h (renamed from NorthstarDedicatedTest/include/internal/sockets.h)0
-rw-r--r--NorthstarDLL/include/internal/sslconf.h (renamed from NorthstarDedicatedTest/include/internal/sslconf.h)0
-rw-r--r--NorthstarDLL/include/internal/symhacks.h (renamed from NorthstarDedicatedTest/include/internal/symhacks.h)0
-rw-r--r--NorthstarDLL/include/internal/thread_once.h (renamed from NorthstarDedicatedTest/include/internal/thread_once.h)0
-rw-r--r--NorthstarDLL/include/internal/tlsgroups.h (renamed from NorthstarDedicatedTest/include/internal/tlsgroups.h)0
-rw-r--r--NorthstarDLL/include/internal/tsan_assist.h (renamed from NorthstarDedicatedTest/include/internal/tsan_assist.h)0
-rw-r--r--NorthstarDLL/include/internal/unicode.h (renamed from NorthstarDedicatedTest/include/internal/unicode.h)0
-rw-r--r--NorthstarDLL/include/libcrypto_static.lib (renamed from NorthstarDedicatedTest/include/libcrypto_static.lib)bin35832382 -> 35832383 bytes
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/curl.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/curl.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/curlver.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/curlver.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/easy.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/easy.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/mprintf.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/mprintf.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/multi.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/multi.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/options.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/options.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/stdcheaders.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/stdcheaders.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/system.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/system.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/typecheck-gcc.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/typecheck-gcc.h)0
-rw-r--r--NorthstarDLL/include/libcurl/include/curl/urlapi.h (renamed from NorthstarDedicatedTest/include/libcurl/include/curl/urlapi.h)0
-rw-r--r--NorthstarDLL/include/libcurl/lib/libcurl_a.lib (renamed from NorthstarDedicatedTest/include/libcurl/lib/libcurl_a.lib)bin2140640 -> 2140641 bytes
-rw-r--r--NorthstarDLL/include/libssl_static.lib (renamed from NorthstarDedicatedTest/include/libssl_static.lib)bin4851208 -> 4851209 bytes
-rw-r--r--NorthstarDLL/include/openssl/__DECC_INCLUDE_EPILOGUE.H (renamed from NorthstarDedicatedTest/include/openssl/__DECC_INCLUDE_EPILOGUE.H)0
-rw-r--r--NorthstarDLL/include/openssl/__DECC_INCLUDE_PROLOGUE.H (renamed from NorthstarDedicatedTest/include/openssl/__DECC_INCLUDE_PROLOGUE.H)0
-rw-r--r--NorthstarDLL/include/openssl/aes.h (renamed from NorthstarDedicatedTest/include/openssl/aes.h)0
-rw-r--r--NorthstarDLL/include/openssl/asn1.h (renamed from NorthstarDedicatedTest/include/openssl/asn1.h)0
-rw-r--r--NorthstarDLL/include/openssl/asn1.h.in (renamed from NorthstarDedicatedTest/include/openssl/asn1.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/asn1_mac.h (renamed from NorthstarDedicatedTest/include/openssl/asn1_mac.h)0
-rw-r--r--NorthstarDLL/include/openssl/asn1err.h (renamed from NorthstarDedicatedTest/include/openssl/asn1err.h)0
-rw-r--r--NorthstarDLL/include/openssl/asn1t.h (renamed from NorthstarDedicatedTest/include/openssl/asn1t.h)0
-rw-r--r--NorthstarDLL/include/openssl/asn1t.h.in (renamed from NorthstarDedicatedTest/include/openssl/asn1t.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/async.h (renamed from NorthstarDedicatedTest/include/openssl/async.h)0
-rw-r--r--NorthstarDLL/include/openssl/asyncerr.h (renamed from NorthstarDedicatedTest/include/openssl/asyncerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/bio.h (renamed from NorthstarDedicatedTest/include/openssl/bio.h)0
-rw-r--r--NorthstarDLL/include/openssl/bio.h.in (renamed from NorthstarDedicatedTest/include/openssl/bio.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/bioerr.h (renamed from NorthstarDedicatedTest/include/openssl/bioerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/blowfish.h (renamed from NorthstarDedicatedTest/include/openssl/blowfish.h)0
-rw-r--r--NorthstarDLL/include/openssl/bn.h (renamed from NorthstarDedicatedTest/include/openssl/bn.h)0
-rw-r--r--NorthstarDLL/include/openssl/bnerr.h (renamed from NorthstarDedicatedTest/include/openssl/bnerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/buffer.h (renamed from NorthstarDedicatedTest/include/openssl/buffer.h)0
-rw-r--r--NorthstarDLL/include/openssl/buffererr.h (renamed from NorthstarDedicatedTest/include/openssl/buffererr.h)0
-rw-r--r--NorthstarDLL/include/openssl/camellia.h (renamed from NorthstarDedicatedTest/include/openssl/camellia.h)0
-rw-r--r--NorthstarDLL/include/openssl/cast.h (renamed from NorthstarDedicatedTest/include/openssl/cast.h)0
-rw-r--r--NorthstarDLL/include/openssl/cmac.h (renamed from NorthstarDedicatedTest/include/openssl/cmac.h)0
-rw-r--r--NorthstarDLL/include/openssl/cmp.h (renamed from NorthstarDedicatedTest/include/openssl/cmp.h)0
-rw-r--r--NorthstarDLL/include/openssl/cmp.h.in (renamed from NorthstarDedicatedTest/include/openssl/cmp.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/cmp_util.h (renamed from NorthstarDedicatedTest/include/openssl/cmp_util.h)0
-rw-r--r--NorthstarDLL/include/openssl/cmperr.h (renamed from NorthstarDedicatedTest/include/openssl/cmperr.h)0
-rw-r--r--NorthstarDLL/include/openssl/cms.h (renamed from NorthstarDedicatedTest/include/openssl/cms.h)0
-rw-r--r--NorthstarDLL/include/openssl/cms.h.in (renamed from NorthstarDedicatedTest/include/openssl/cms.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/cmserr.h (renamed from NorthstarDedicatedTest/include/openssl/cmserr.h)0
-rw-r--r--NorthstarDLL/include/openssl/comp.h (renamed from NorthstarDedicatedTest/include/openssl/comp.h)0
-rw-r--r--NorthstarDLL/include/openssl/comperr.h (renamed from NorthstarDedicatedTest/include/openssl/comperr.h)0
-rw-r--r--NorthstarDLL/include/openssl/conf.h (renamed from NorthstarDedicatedTest/include/openssl/conf.h)0
-rw-r--r--NorthstarDLL/include/openssl/conf.h.in (renamed from NorthstarDedicatedTest/include/openssl/conf.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/conf_api.h (renamed from NorthstarDedicatedTest/include/openssl/conf_api.h)0
-rw-r--r--NorthstarDLL/include/openssl/conferr.h (renamed from NorthstarDedicatedTest/include/openssl/conferr.h)0
-rw-r--r--NorthstarDLL/include/openssl/configuration.h (renamed from NorthstarDedicatedTest/include/openssl/configuration.h)0
-rw-r--r--NorthstarDLL/include/openssl/configuration.h.in (renamed from NorthstarDedicatedTest/include/openssl/configuration.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/conftypes.h (renamed from NorthstarDedicatedTest/include/openssl/conftypes.h)0
-rw-r--r--NorthstarDLL/include/openssl/core.h (renamed from NorthstarDedicatedTest/include/openssl/core.h)0
-rw-r--r--NorthstarDLL/include/openssl/core_dispatch.h (renamed from NorthstarDedicatedTest/include/openssl/core_dispatch.h)0
-rw-r--r--NorthstarDLL/include/openssl/core_names.h (renamed from NorthstarDedicatedTest/include/openssl/core_names.h)0
-rw-r--r--NorthstarDLL/include/openssl/core_object.h (renamed from NorthstarDedicatedTest/include/openssl/core_object.h)0
-rw-r--r--NorthstarDLL/include/openssl/crmf.h (renamed from NorthstarDedicatedTest/include/openssl/crmf.h)0
-rw-r--r--NorthstarDLL/include/openssl/crmf.h.in (renamed from NorthstarDedicatedTest/include/openssl/crmf.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/crmferr.h (renamed from NorthstarDedicatedTest/include/openssl/crmferr.h)0
-rw-r--r--NorthstarDLL/include/openssl/crypto.h (renamed from NorthstarDedicatedTest/include/openssl/crypto.h)0
-rw-r--r--NorthstarDLL/include/openssl/crypto.h.in (renamed from NorthstarDedicatedTest/include/openssl/crypto.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/cryptoerr.h (renamed from NorthstarDedicatedTest/include/openssl/cryptoerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/cryptoerr_legacy.h (renamed from NorthstarDedicatedTest/include/openssl/cryptoerr_legacy.h)0
-rw-r--r--NorthstarDLL/include/openssl/ct.h (renamed from NorthstarDedicatedTest/include/openssl/ct.h)0
-rw-r--r--NorthstarDLL/include/openssl/ct.h.in (renamed from NorthstarDedicatedTest/include/openssl/ct.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/cterr.h (renamed from NorthstarDedicatedTest/include/openssl/cterr.h)0
-rw-r--r--NorthstarDLL/include/openssl/decoder.h (renamed from NorthstarDedicatedTest/include/openssl/decoder.h)0
-rw-r--r--NorthstarDLL/include/openssl/decodererr.h (renamed from NorthstarDedicatedTest/include/openssl/decodererr.h)0
-rw-r--r--NorthstarDLL/include/openssl/des.h (renamed from NorthstarDedicatedTest/include/openssl/des.h)0
-rw-r--r--NorthstarDLL/include/openssl/dh.h (renamed from NorthstarDedicatedTest/include/openssl/dh.h)0
-rw-r--r--NorthstarDLL/include/openssl/dherr.h (renamed from NorthstarDedicatedTest/include/openssl/dherr.h)0
-rw-r--r--NorthstarDLL/include/openssl/dsa.h (renamed from NorthstarDedicatedTest/include/openssl/dsa.h)0
-rw-r--r--NorthstarDLL/include/openssl/dsaerr.h (renamed from NorthstarDedicatedTest/include/openssl/dsaerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/dtls1.h (renamed from NorthstarDedicatedTest/include/openssl/dtls1.h)0
-rw-r--r--NorthstarDLL/include/openssl/e_os2.h (renamed from NorthstarDedicatedTest/include/openssl/e_os2.h)0
-rw-r--r--NorthstarDLL/include/openssl/ebcdic.h (renamed from NorthstarDedicatedTest/include/openssl/ebcdic.h)0
-rw-r--r--NorthstarDLL/include/openssl/ec.h (renamed from NorthstarDedicatedTest/include/openssl/ec.h)0
-rw-r--r--NorthstarDLL/include/openssl/ecdh.h (renamed from NorthstarDedicatedTest/include/openssl/ecdh.h)0
-rw-r--r--NorthstarDLL/include/openssl/ecdsa.h (renamed from NorthstarDedicatedTest/include/openssl/ecdsa.h)0
-rw-r--r--NorthstarDLL/include/openssl/ecerr.h (renamed from NorthstarDedicatedTest/include/openssl/ecerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/encoder.h (renamed from NorthstarDedicatedTest/include/openssl/encoder.h)0
-rw-r--r--NorthstarDLL/include/openssl/encodererr.h (renamed from NorthstarDedicatedTest/include/openssl/encodererr.h)0
-rw-r--r--NorthstarDLL/include/openssl/engine.h (renamed from NorthstarDedicatedTest/include/openssl/engine.h)0
-rw-r--r--NorthstarDLL/include/openssl/engineerr.h (renamed from NorthstarDedicatedTest/include/openssl/engineerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/err.h (renamed from NorthstarDedicatedTest/include/openssl/err.h)0
-rw-r--r--NorthstarDLL/include/openssl/err.h.in (renamed from NorthstarDedicatedTest/include/openssl/err.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/ess.h (renamed from NorthstarDedicatedTest/include/openssl/ess.h)0
-rw-r--r--NorthstarDLL/include/openssl/ess.h.in (renamed from NorthstarDedicatedTest/include/openssl/ess.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/esserr.h (renamed from NorthstarDedicatedTest/include/openssl/esserr.h)0
-rw-r--r--NorthstarDLL/include/openssl/evp.h (renamed from NorthstarDedicatedTest/include/openssl/evp.h)0
-rw-r--r--NorthstarDLL/include/openssl/evperr.h (renamed from NorthstarDedicatedTest/include/openssl/evperr.h)0
-rw-r--r--NorthstarDLL/include/openssl/fips_names.h (renamed from NorthstarDedicatedTest/include/openssl/fips_names.h)0
-rw-r--r--NorthstarDLL/include/openssl/fipskey.h (renamed from NorthstarDedicatedTest/include/openssl/fipskey.h)0
-rw-r--r--NorthstarDLL/include/openssl/fipskey.h.in (renamed from NorthstarDedicatedTest/include/openssl/fipskey.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/hmac.h (renamed from NorthstarDedicatedTest/include/openssl/hmac.h)0
-rw-r--r--NorthstarDLL/include/openssl/http.h (renamed from NorthstarDedicatedTest/include/openssl/http.h)0
-rw-r--r--NorthstarDLL/include/openssl/httperr.h (renamed from NorthstarDedicatedTest/include/openssl/httperr.h)0
-rw-r--r--NorthstarDLL/include/openssl/idea.h (renamed from NorthstarDedicatedTest/include/openssl/idea.h)0
-rw-r--r--NorthstarDLL/include/openssl/kdf.h (renamed from NorthstarDedicatedTest/include/openssl/kdf.h)0
-rw-r--r--NorthstarDLL/include/openssl/kdferr.h (renamed from NorthstarDedicatedTest/include/openssl/kdferr.h)0
-rw-r--r--NorthstarDLL/include/openssl/lhash.h (renamed from NorthstarDedicatedTest/include/openssl/lhash.h)0
-rw-r--r--NorthstarDLL/include/openssl/lhash.h.in (renamed from NorthstarDedicatedTest/include/openssl/lhash.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/macros.h (renamed from NorthstarDedicatedTest/include/openssl/macros.h)0
-rw-r--r--NorthstarDLL/include/openssl/md2.h (renamed from NorthstarDedicatedTest/include/openssl/md2.h)0
-rw-r--r--NorthstarDLL/include/openssl/md4.h (renamed from NorthstarDedicatedTest/include/openssl/md4.h)0
-rw-r--r--NorthstarDLL/include/openssl/md5.h (renamed from NorthstarDedicatedTest/include/openssl/md5.h)0
-rw-r--r--NorthstarDLL/include/openssl/mdc2.h (renamed from NorthstarDedicatedTest/include/openssl/mdc2.h)0
-rw-r--r--NorthstarDLL/include/openssl/modes.h (renamed from NorthstarDedicatedTest/include/openssl/modes.h)0
-rw-r--r--NorthstarDLL/include/openssl/obj_mac.h (renamed from NorthstarDedicatedTest/include/openssl/obj_mac.h)0
-rw-r--r--NorthstarDLL/include/openssl/objects.h (renamed from NorthstarDedicatedTest/include/openssl/objects.h)0
-rw-r--r--NorthstarDLL/include/openssl/objectserr.h (renamed from NorthstarDedicatedTest/include/openssl/objectserr.h)0
-rw-r--r--NorthstarDLL/include/openssl/ocsp.h (renamed from NorthstarDedicatedTest/include/openssl/ocsp.h)0
-rw-r--r--NorthstarDLL/include/openssl/ocsp.h.in (renamed from NorthstarDedicatedTest/include/openssl/ocsp.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/ocsperr.h (renamed from NorthstarDedicatedTest/include/openssl/ocsperr.h)0
-rw-r--r--NorthstarDLL/include/openssl/opensslconf.h (renamed from NorthstarDedicatedTest/include/openssl/opensslconf.h)0
-rw-r--r--NorthstarDLL/include/openssl/opensslv.h (renamed from NorthstarDedicatedTest/include/openssl/opensslv.h)0
-rw-r--r--NorthstarDLL/include/openssl/opensslv.h.in (renamed from NorthstarDedicatedTest/include/openssl/opensslv.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/ossl_typ.h (renamed from NorthstarDedicatedTest/include/openssl/ossl_typ.h)0
-rw-r--r--NorthstarDLL/include/openssl/param_build.h (renamed from NorthstarDedicatedTest/include/openssl/param_build.h)0
-rw-r--r--NorthstarDLL/include/openssl/params.h (renamed from NorthstarDedicatedTest/include/openssl/params.h)0
-rw-r--r--NorthstarDLL/include/openssl/pem.h (renamed from NorthstarDedicatedTest/include/openssl/pem.h)0
-rw-r--r--NorthstarDLL/include/openssl/pem2.h (renamed from NorthstarDedicatedTest/include/openssl/pem2.h)0
-rw-r--r--NorthstarDLL/include/openssl/pemerr.h (renamed from NorthstarDedicatedTest/include/openssl/pemerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/pkcs12.h (renamed from NorthstarDedicatedTest/include/openssl/pkcs12.h)0
-rw-r--r--NorthstarDLL/include/openssl/pkcs12.h.in (renamed from NorthstarDedicatedTest/include/openssl/pkcs12.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/pkcs12err.h (renamed from NorthstarDedicatedTest/include/openssl/pkcs12err.h)0
-rw-r--r--NorthstarDLL/include/openssl/pkcs7.h (renamed from NorthstarDedicatedTest/include/openssl/pkcs7.h)0
-rw-r--r--NorthstarDLL/include/openssl/pkcs7.h.in (renamed from NorthstarDedicatedTest/include/openssl/pkcs7.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/pkcs7err.h (renamed from NorthstarDedicatedTest/include/openssl/pkcs7err.h)0
-rw-r--r--NorthstarDLL/include/openssl/prov_ssl.h (renamed from NorthstarDedicatedTest/include/openssl/prov_ssl.h)0
-rw-r--r--NorthstarDLL/include/openssl/proverr.h (renamed from NorthstarDedicatedTest/include/openssl/proverr.h)0
-rw-r--r--NorthstarDLL/include/openssl/provider.h (renamed from NorthstarDedicatedTest/include/openssl/provider.h)0
-rw-r--r--NorthstarDLL/include/openssl/rand.h (renamed from NorthstarDedicatedTest/include/openssl/rand.h)0
-rw-r--r--NorthstarDLL/include/openssl/randerr.h (renamed from NorthstarDedicatedTest/include/openssl/randerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/rc2.h (renamed from NorthstarDedicatedTest/include/openssl/rc2.h)0
-rw-r--r--NorthstarDLL/include/openssl/rc4.h (renamed from NorthstarDedicatedTest/include/openssl/rc4.h)0
-rw-r--r--NorthstarDLL/include/openssl/rc5.h (renamed from NorthstarDedicatedTest/include/openssl/rc5.h)0
-rw-r--r--NorthstarDLL/include/openssl/ripemd.h (renamed from NorthstarDedicatedTest/include/openssl/ripemd.h)0
-rw-r--r--NorthstarDLL/include/openssl/rsa.h (renamed from NorthstarDedicatedTest/include/openssl/rsa.h)0
-rw-r--r--NorthstarDLL/include/openssl/rsaerr.h (renamed from NorthstarDedicatedTest/include/openssl/rsaerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/safestack.h (renamed from NorthstarDedicatedTest/include/openssl/safestack.h)0
-rw-r--r--NorthstarDLL/include/openssl/safestack.h.in (renamed from NorthstarDedicatedTest/include/openssl/safestack.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/seed.h (renamed from NorthstarDedicatedTest/include/openssl/seed.h)0
-rw-r--r--NorthstarDLL/include/openssl/self_test.h (renamed from NorthstarDedicatedTest/include/openssl/self_test.h)0
-rw-r--r--NorthstarDLL/include/openssl/sha.h (renamed from NorthstarDedicatedTest/include/openssl/sha.h)0
-rw-r--r--NorthstarDLL/include/openssl/srp.h (renamed from NorthstarDedicatedTest/include/openssl/srp.h)0
-rw-r--r--NorthstarDLL/include/openssl/srp.h.in (renamed from NorthstarDedicatedTest/include/openssl/srp.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/srtp.h (renamed from NorthstarDedicatedTest/include/openssl/srtp.h)0
-rw-r--r--NorthstarDLL/include/openssl/ssl.h (renamed from NorthstarDedicatedTest/include/openssl/ssl.h)0
-rw-r--r--NorthstarDLL/include/openssl/ssl.h.in (renamed from NorthstarDedicatedTest/include/openssl/ssl.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/ssl2.h (renamed from NorthstarDedicatedTest/include/openssl/ssl2.h)0
-rw-r--r--NorthstarDLL/include/openssl/ssl3.h (renamed from NorthstarDedicatedTest/include/openssl/ssl3.h)0
-rw-r--r--NorthstarDLL/include/openssl/sslerr.h (renamed from NorthstarDedicatedTest/include/openssl/sslerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/sslerr_legacy.h (renamed from NorthstarDedicatedTest/include/openssl/sslerr_legacy.h)0
-rw-r--r--NorthstarDLL/include/openssl/stack.h (renamed from NorthstarDedicatedTest/include/openssl/stack.h)0
-rw-r--r--NorthstarDLL/include/openssl/store.h (renamed from NorthstarDedicatedTest/include/openssl/store.h)0
-rw-r--r--NorthstarDLL/include/openssl/storeerr.h (renamed from NorthstarDedicatedTest/include/openssl/storeerr.h)0
-rw-r--r--NorthstarDLL/include/openssl/symhacks.h (renamed from NorthstarDedicatedTest/include/openssl/symhacks.h)0
-rw-r--r--NorthstarDLL/include/openssl/tls1.h (renamed from NorthstarDedicatedTest/include/openssl/tls1.h)0
-rw-r--r--NorthstarDLL/include/openssl/trace.h (renamed from NorthstarDedicatedTest/include/openssl/trace.h)0
-rw-r--r--NorthstarDLL/include/openssl/ts.h (renamed from NorthstarDedicatedTest/include/openssl/ts.h)0
-rw-r--r--NorthstarDLL/include/openssl/tserr.h (renamed from NorthstarDedicatedTest/include/openssl/tserr.h)0
-rw-r--r--NorthstarDLL/include/openssl/txt_db.h (renamed from NorthstarDedicatedTest/include/openssl/txt_db.h)0
-rw-r--r--NorthstarDLL/include/openssl/types.h (renamed from NorthstarDedicatedTest/include/openssl/types.h)0
-rw-r--r--NorthstarDLL/include/openssl/ui.h (renamed from NorthstarDedicatedTest/include/openssl/ui.h)0
-rw-r--r--NorthstarDLL/include/openssl/ui.h.in (renamed from NorthstarDedicatedTest/include/openssl/ui.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/uierr.h (renamed from NorthstarDedicatedTest/include/openssl/uierr.h)0
-rw-r--r--NorthstarDLL/include/openssl/whrlpool.h (renamed from NorthstarDedicatedTest/include/openssl/whrlpool.h)0
-rw-r--r--NorthstarDLL/include/openssl/x509.h (renamed from NorthstarDedicatedTest/include/openssl/x509.h)0
-rw-r--r--NorthstarDLL/include/openssl/x509.h.in (renamed from NorthstarDedicatedTest/include/openssl/x509.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/x509_vfy.h (renamed from NorthstarDedicatedTest/include/openssl/x509_vfy.h)0
-rw-r--r--NorthstarDLL/include/openssl/x509_vfy.h.in (renamed from NorthstarDedicatedTest/include/openssl/x509_vfy.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/x509err.h (renamed from NorthstarDedicatedTest/include/openssl/x509err.h)0
-rw-r--r--NorthstarDLL/include/openssl/x509v3.h (renamed from NorthstarDedicatedTest/include/openssl/x509v3.h)0
-rw-r--r--NorthstarDLL/include/openssl/x509v3.h.in (renamed from NorthstarDedicatedTest/include/openssl/x509v3.h.in)0
-rw-r--r--NorthstarDLL/include/openssl/x509v3err.h (renamed from NorthstarDedicatedTest/include/openssl/x509v3err.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/allocators.h (renamed from NorthstarDedicatedTest/include/rapidjson/allocators.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/document.h (renamed from NorthstarDedicatedTest/include/rapidjson/document.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/encodedstream.h (renamed from NorthstarDedicatedTest/include/rapidjson/encodedstream.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/encodings.h (renamed from NorthstarDedicatedTest/include/rapidjson/encodings.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/error/en.h (renamed from NorthstarDedicatedTest/include/rapidjson/error/en.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/error/error.h (renamed from NorthstarDedicatedTest/include/rapidjson/error/error.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/filereadstream.h (renamed from NorthstarDedicatedTest/include/rapidjson/filereadstream.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/filewritestream.h (renamed from NorthstarDedicatedTest/include/rapidjson/filewritestream.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/fwd.h (renamed from NorthstarDedicatedTest/include/rapidjson/fwd.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/biginteger.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/biginteger.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/diyfp.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/diyfp.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/dtoa.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/dtoa.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/ieee754.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/ieee754.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/itoa.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/itoa.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/meta.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/meta.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/pow10.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/pow10.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/regex.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/regex.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/stack.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/stack.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/strfunc.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/strfunc.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/strtod.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/strtod.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/internal/swap.h (renamed from NorthstarDedicatedTest/include/rapidjson/internal/swap.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/istreamwrapper.h (renamed from NorthstarDedicatedTest/include/rapidjson/istreamwrapper.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/memorybuffer.h (renamed from NorthstarDedicatedTest/include/rapidjson/memorybuffer.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/memorystream.h (renamed from NorthstarDedicatedTest/include/rapidjson/memorystream.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/msinttypes/inttypes.h (renamed from NorthstarDedicatedTest/include/rapidjson/msinttypes/inttypes.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/msinttypes/stdint.h (renamed from NorthstarDedicatedTest/include/rapidjson/msinttypes/stdint.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/ostreamwrapper.h (renamed from NorthstarDedicatedTest/include/rapidjson/ostreamwrapper.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/pointer.h (renamed from NorthstarDedicatedTest/include/rapidjson/pointer.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/prettywriter.h (renamed from NorthstarDedicatedTest/include/rapidjson/prettywriter.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/rapidjson.h (renamed from NorthstarDedicatedTest/include/rapidjson/rapidjson.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/reader.h (renamed from NorthstarDedicatedTest/include/rapidjson/reader.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/schema.h (renamed from NorthstarDedicatedTest/include/rapidjson/schema.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/stream.h (renamed from NorthstarDedicatedTest/include/rapidjson/stream.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/stringbuffer.h (renamed from NorthstarDedicatedTest/include/rapidjson/stringbuffer.h)0
-rw-r--r--NorthstarDLL/include/rapidjson/writer.h (renamed from NorthstarDedicatedTest/include/rapidjson/writer.h)0
-rw-r--r--NorthstarDLL/include/spdlog/async.h (renamed from NorthstarDedicatedTest/include/spdlog/async.h)0
-rw-r--r--NorthstarDLL/include/spdlog/async_logger-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/async_logger-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/async_logger.h (renamed from NorthstarDedicatedTest/include/spdlog/async_logger.h)0
-rw-r--r--NorthstarDLL/include/spdlog/cfg/argv.h (renamed from NorthstarDedicatedTest/include/spdlog/cfg/argv.h)0
-rw-r--r--NorthstarDLL/include/spdlog/cfg/env.h (renamed from NorthstarDedicatedTest/include/spdlog/cfg/env.h)0
-rw-r--r--NorthstarDLL/include/spdlog/cfg/helpers-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/cfg/helpers-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/cfg/helpers.h (renamed from NorthstarDedicatedTest/include/spdlog/cfg/helpers.h)0
-rw-r--r--NorthstarDLL/include/spdlog/common-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/common-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/common.h (renamed from NorthstarDedicatedTest/include/spdlog/common.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/backtracer-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/details/backtracer-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/backtracer.h (renamed from NorthstarDedicatedTest/include/spdlog/details/backtracer.h)2
-rw-r--r--NorthstarDLL/include/spdlog/details/circular_q.h (renamed from NorthstarDedicatedTest/include/spdlog/details/circular_q.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/console_globals.h (renamed from NorthstarDedicatedTest/include/spdlog/details/console_globals.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/file_helper-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/details/file_helper-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/file_helper.h (renamed from NorthstarDedicatedTest/include/spdlog/details/file_helper.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/fmt_helper.h (renamed from NorthstarDedicatedTest/include/spdlog/details/fmt_helper.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/log_msg-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/details/log_msg-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/log_msg.h (renamed from NorthstarDedicatedTest/include/spdlog/details/log_msg.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/log_msg_buffer-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/details/log_msg_buffer-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/log_msg_buffer.h (renamed from NorthstarDedicatedTest/include/spdlog/details/log_msg_buffer.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/mpmc_blocking_q.h (renamed from NorthstarDedicatedTest/include/spdlog/details/mpmc_blocking_q.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/null_mutex.h (renamed from NorthstarDedicatedTest/include/spdlog/details/null_mutex.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/os-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/details/os-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/os.h (renamed from NorthstarDedicatedTest/include/spdlog/details/os.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/periodic_worker-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/details/periodic_worker-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/periodic_worker.h (renamed from NorthstarDedicatedTest/include/spdlog/details/periodic_worker.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/registry-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/details/registry-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/registry.h (renamed from NorthstarDedicatedTest/include/spdlog/details/registry.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/synchronous_factory.h (renamed from NorthstarDedicatedTest/include/spdlog/details/synchronous_factory.h)2
-rw-r--r--NorthstarDLL/include/spdlog/details/tcp_client-windows.h (renamed from NorthstarDedicatedTest/include/spdlog/details/tcp_client-windows.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/tcp_client.h (renamed from NorthstarDedicatedTest/include/spdlog/details/tcp_client.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/thread_pool-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/details/thread_pool-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/thread_pool.h (renamed from NorthstarDedicatedTest/include/spdlog/details/thread_pool.h)0
-rw-r--r--NorthstarDLL/include/spdlog/details/windows_include.h (renamed from NorthstarDedicatedTest/include/spdlog/details/windows_include.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bin_to_hex.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bin_to_hex.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/LICENSE.rst (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/LICENSE.rst)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/chrono.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/chrono.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/color.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/color.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/compile.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/compile.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/core.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/core.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/format-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/format-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/format.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/format.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/locale.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/locale.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/os.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/os.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/ostream.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/ostream.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/posix.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/posix.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/printf.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/printf.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/bundled/ranges.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/bundled/ranges.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/chrono.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/chrono.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fmt/fmt.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/fmt.h)2
-rw-r--r--NorthstarDLL/include/spdlog/fmt/ostr.h (renamed from NorthstarDedicatedTest/include/spdlog/fmt/ostr.h)0
-rw-r--r--NorthstarDLL/include/spdlog/formatter.h (renamed from NorthstarDedicatedTest/include/spdlog/formatter.h)0
-rw-r--r--NorthstarDLL/include/spdlog/fwd.h (renamed from NorthstarDedicatedTest/include/spdlog/fwd.h)0
-rw-r--r--NorthstarDLL/include/spdlog/logger-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/logger-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/logger.h (renamed from NorthstarDedicatedTest/include/spdlog/logger.h)0
-rw-r--r--NorthstarDLL/include/spdlog/pattern_formatter-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/pattern_formatter-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/pattern_formatter.h (renamed from NorthstarDedicatedTest/include/spdlog/pattern_formatter.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/android_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/android_sink.h)2
-rw-r--r--NorthstarDLL/include/spdlog/sinks/ansicolor_sink-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/ansicolor_sink-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/ansicolor_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/ansicolor_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/base_sink-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/base_sink-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/base_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/base_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/basic_file_sink-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/basic_file_sink-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/basic_file_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/basic_file_sink.h)2
-rw-r--r--NorthstarDLL/include/spdlog/sinks/daily_file_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/daily_file_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/dist_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/dist_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/dup_filter_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/dup_filter_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/hourly_file_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/hourly_file_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/msvc_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/msvc_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/null_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/null_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/ostream_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/ostream_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/ringbuffer_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/ringbuffer_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/rotating_file_sink-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/rotating_file_sink-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/rotating_file_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/rotating_file_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/sink-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/sink-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/stdout_color_sinks-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/stdout_color_sinks-inl.h)2
-rw-r--r--NorthstarDLL/include/spdlog/sinks/stdout_color_sinks.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/stdout_color_sinks.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/stdout_sinks-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/stdout_sinks-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/stdout_sinks.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/stdout_sinks.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/syslog_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/syslog_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/systemd_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/systemd_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/tcp_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/tcp_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/win_eventlog_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/win_eventlog_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/wincolor_sink-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/wincolor_sink-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/sinks/wincolor_sink.h (renamed from NorthstarDedicatedTest/include/spdlog/sinks/wincolor_sink.h)0
-rw-r--r--NorthstarDLL/include/spdlog/spdlog-inl.h (renamed from NorthstarDedicatedTest/include/spdlog/spdlog-inl.h)0
-rw-r--r--NorthstarDLL/include/spdlog/spdlog.h (renamed from NorthstarDedicatedTest/include/spdlog/spdlog.h)0
-rw-r--r--NorthstarDLL/include/spdlog/stopwatch.h (renamed from NorthstarDedicatedTest/include/spdlog/stopwatch.h)0
-rw-r--r--NorthstarDLL/include/spdlog/tweakme.h (renamed from NorthstarDedicatedTest/include/spdlog/tweakme.h)0
-rw-r--r--NorthstarDLL/include/spdlog/version.h (renamed from NorthstarDedicatedTest/include/spdlog/version.h)0
-rw-r--r--NorthstarDLL/keyvalues.cpp (renamed from NorthstarDedicatedTest/keyvalues.cpp)83
-rw-r--r--NorthstarDLL/languagehooks.cpp (renamed from NorthstarDedicatedTest/languagehooks.cpp)29
-rw-r--r--NorthstarDLL/latencyflex.cpp44
-rw-r--r--NorthstarDLL/limits.cpp299
-rw-r--r--NorthstarDLL/limits.h51
-rw-r--r--NorthstarDLL/localchatwriter.cpp (renamed from NorthstarDedicatedTest/localchatwriter.cpp)87
-rw-r--r--NorthstarDLL/localchatwriter.h (renamed from NorthstarDedicatedTest/localchatwriter.h)21
-rw-r--r--NorthstarDLL/logging.cpp259
-rw-r--r--NorthstarDLL/logging.h4
-rw-r--r--NorthstarDLL/main.h (renamed from NorthstarDedicatedTest/main.h)2
-rw-r--r--NorthstarDLL/masterserver.cpp1076
-rw-r--r--NorthstarDLL/masterserver.h126
-rw-r--r--NorthstarDLL/maxplayers.cpp645
-rw-r--r--NorthstarDLL/maxplayers.h7
-rw-r--r--NorthstarDLL/memalloc.cpp (renamed from NorthstarDedicatedTest/memalloc.cpp)24
-rw-r--r--NorthstarDLL/memalloc.h (renamed from NorthstarDedicatedTest/memalloc.h)2
-rw-r--r--NorthstarDLL/memory.cpp348
-rw-r--r--NorthstarDLL/memory.h90
-rw-r--r--NorthstarDLL/misccommands.cpp65
-rw-r--r--NorthstarDLL/misccommands.h2
-rw-r--r--NorthstarDLL/miscserverfixes.cpp7
-rw-r--r--NorthstarDLL/miscserverscript.cpp65
-rw-r--r--NorthstarDLL/modlocalisation.cpp35
-rw-r--r--NorthstarDLL/modmanager.cpp (renamed from NorthstarDedicatedTest/modmanager.cpp)267
-rw-r--r--NorthstarDLL/modmanager.h (renamed from NorthstarDedicatedTest/modmanager.h)46
-rw-r--r--NorthstarDLL/ns_version.h (renamed from NorthstarDedicatedTest/ns_version.h)0
-rw-r--r--NorthstarDLL/nsprefix.cpp (renamed from NorthstarDedicatedTest/configurables.cpp)6
-rw-r--r--NorthstarDLL/nsprefix.h (renamed from NorthstarDedicatedTest/configurables.h)2
-rw-r--r--NorthstarDLL/pch.cpp (renamed from NorthstarDedicatedTest/pch.cpp)0
-rw-r--r--NorthstarDLL/pch.h (renamed from NorthstarDedicatedTest/pch.h)15
-rw-r--r--NorthstarDLL/pdef.cpp (renamed from NorthstarDedicatedTest/pdef.cpp)20
-rw-r--r--NorthstarDLL/pdef.h (renamed from NorthstarDedicatedTest/pdef.h)2
-rw-r--r--NorthstarDLL/playlist.cpp130
-rw-r--r--NorthstarDLL/playlist.h10
-rw-r--r--NorthstarDLL/plugin_abi.h (renamed from NorthstarDedicatedTest/plugin_abi.h)2
-rw-r--r--NorthstarDLL/plugins.cpp (renamed from NorthstarDedicatedTest/plugins.cpp)96
-rw-r--r--NorthstarDLL/plugins.h (renamed from NorthstarDedicatedTest/plugins.h)2
-rw-r--r--NorthstarDLL/printcommand.h6
-rw-r--r--NorthstarDLL/printcommands.cpp174
-rw-r--r--NorthstarDLL/printmaps.cpp168
-rw-r--r--NorthstarDLL/printmaps.h2
-rw-r--r--NorthstarDLL/r2client.cpp20
-rw-r--r--NorthstarDLL/r2client.h11
-rw-r--r--NorthstarDLL/r2engine.cpp36
-rw-r--r--NorthstarDLL/r2engine.h199
-rw-r--r--NorthstarDLL/r2server.cpp17
-rw-r--r--NorthstarDLL/r2server.h19
-rw-r--r--NorthstarDLL/rpakfilesystem.cpp299
-rw-r--r--NorthstarDLL/rpakfilesystem.h39
-rw-r--r--NorthstarDLL/runframe.cpp20
-rw-r--r--NorthstarDLL/scriptbrowserhooks.cpp25
-rw-r--r--NorthstarDLL/scriptdatatables.cpp940
-rw-r--r--NorthstarDLL/scriptjson.cpp282
-rw-r--r--NorthstarDLL/scriptmainmenupromos.cpp136
-rw-r--r--NorthstarDLL/scriptmodmenu.cpp203
-rw-r--r--NorthstarDLL/scriptserverbrowser.cpp458
-rw-r--r--NorthstarDLL/scriptservertoclientstringcommand.cpp25
-rw-r--r--NorthstarDLL/scriptsrson.cpp (renamed from NorthstarDedicatedTest/scriptsrson.cpp)23
-rw-r--r--NorthstarDLL/scriptsrson.h (renamed from NorthstarDedicatedTest/scriptsrson.h)2
-rw-r--r--NorthstarDLL/scriptutility.cpp23
-rw-r--r--NorthstarDLL/serverauthentication.cpp401
-rw-r--r--NorthstarDLL/serverauthentication.h57
-rw-r--r--NorthstarDLL/serverchathooks.cpp183
-rw-r--r--NorthstarDLL/serverchathooks.h (renamed from NorthstarDedicatedTest/serverchathooks.h)4
-rw-r--r--NorthstarDLL/serverpresence.cpp233
-rw-r--r--NorthstarDLL/serverpresence.h91
-rw-r--r--NorthstarDLL/sourceconsole.cpp73
-rw-r--r--NorthstarDLL/sourceconsole.h (renamed from NorthstarDedicatedTest/sourceconsole.h)17
-rw-r--r--NorthstarDLL/sourceinterface.cpp49
-rw-r--r--NorthstarDLL/sourceinterface.h (renamed from NorthstarDedicatedTest/sourceinterface.h)3
-rw-r--r--NorthstarDLL/squirrel.cpp592
-rw-r--r--NorthstarDLL/squirrel.h318
-rw-r--r--NorthstarDLL/squirreldatatypes.h484
-rw-r--r--NorthstarDLL/tier0.cpp37
-rw-r--r--NorthstarDLL/tier0.h68
-rw-r--r--NorthstarDLL/vector.h52
-rw-r--r--NorthstarDLL/version.cpp (renamed from NorthstarDedicatedTest/version.cpp)0
-rw-r--r--NorthstarDLL/version.h (renamed from NorthstarDedicatedTest/version.h)2
-rw-r--r--NorthstarDedicatedTest/ExploitFixes.cpp419
-rw-r--r--NorthstarDedicatedTest/ExploitFixes.h9
-rw-r--r--NorthstarDedicatedTest/ExploitFixes_UTF8Parser.h175
-rw-r--r--NorthstarDedicatedTest/NSMem.h211
-rw-r--r--NorthstarDedicatedTest/bansystem.cpp106
-rw-r--r--NorthstarDedicatedTest/buildainfile.h3
-rw-r--r--NorthstarDedicatedTest/chatcommand.h3
-rw-r--r--NorthstarDedicatedTest/clientauthhooks.h2
-rw-r--r--NorthstarDedicatedTest/clientchathooks.cpp95
-rw-r--r--NorthstarDedicatedTest/clientchathooks.h5
-rw-r--r--NorthstarDedicatedTest/clientruihooks.cpp24
-rw-r--r--NorthstarDedicatedTest/clientruihooks.h2
-rw-r--r--NorthstarDedicatedTest/clientvideooverrides.cpp39
-rw-r--r--NorthstarDedicatedTest/clientvideooverrides.h2
-rw-r--r--NorthstarDedicatedTest/context.cpp14
-rw-r--r--NorthstarDedicatedTest/context.h11
-rw-r--r--NorthstarDedicatedTest/debugoverlay.h3
-rw-r--r--NorthstarDedicatedTest/dedicated.cpp329
-rw-r--r--NorthstarDedicatedTest/dedicated.h7
-rw-r--r--NorthstarDedicatedTest/dedicatedmaterialsystem.cpp123
-rw-r--r--NorthstarDedicatedTest/dedicatedmaterialsystem.h3
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp297
-rw-r--r--NorthstarDedicatedTest/emit_blocker.cpp26
-rw-r--r--NorthstarDedicatedTest/emit_blocker.h3
-rw-r--r--NorthstarDedicatedTest/filesystem.cpp197
-rw-r--r--NorthstarDedicatedTest/gameutils.cpp119
-rw-r--r--NorthstarDedicatedTest/gameutils.h249
-rw-r--r--NorthstarDedicatedTest/hooks.cpp255
-rw-r--r--NorthstarDedicatedTest/hooks.h11
-rw-r--r--NorthstarDedicatedTest/hookutils.cpp44
-rw-r--r--NorthstarDedicatedTest/hookutils.h22
-rw-r--r--NorthstarDedicatedTest/keyvalues.h3
-rw-r--r--NorthstarDedicatedTest/languagehooks.h3
-rw-r--r--NorthstarDedicatedTest/latencyflex.cpp44
-rw-r--r--NorthstarDedicatedTest/latencyflex.h2
-rw-r--r--NorthstarDedicatedTest/logging.h7
-rw-r--r--NorthstarDedicatedTest/masterserver.cpp1366
-rw-r--r--NorthstarDedicatedTest/masterserver.h133
-rw-r--r--NorthstarDedicatedTest/maxplayers.cpp682
-rw-r--r--NorthstarDedicatedTest/maxplayers.h4
-rw-r--r--NorthstarDedicatedTest/miscclientfixes.cpp49
-rw-r--r--NorthstarDedicatedTest/miscclientfixes.h2
-rw-r--r--NorthstarDedicatedTest/misccommands.cpp60
-rw-r--r--NorthstarDedicatedTest/misccommands.h2
-rw-r--r--NorthstarDedicatedTest/miscserverfixes.cpp28
-rw-r--r--NorthstarDedicatedTest/miscserverfixes.h1
-rw-r--r--NorthstarDedicatedTest/miscserverscript.cpp66
-rw-r--r--NorthstarDedicatedTest/miscserverscript.h2
-rw-r--r--NorthstarDedicatedTest/modlocalisation.cpp37
-rw-r--r--NorthstarDedicatedTest/modlocalisation.h3
-rw-r--r--NorthstarDedicatedTest/playlist.cpp106
-rw-r--r--NorthstarDedicatedTest/playlist.h2
-rw-r--r--NorthstarDedicatedTest/rpakfilesystem.cpp246
-rw-r--r--NorthstarDedicatedTest/rpakfilesystem.h16
-rw-r--r--NorthstarDedicatedTest/scriptbrowserhooks.cpp27
-rw-r--r--NorthstarDedicatedTest/scriptbrowserhooks.h3
-rw-r--r--NorthstarDedicatedTest/scriptmainmenupromos.cpp136
-rw-r--r--NorthstarDedicatedTest/scriptmainmenupromos.h3
-rw-r--r--NorthstarDedicatedTest/scriptmodmenu.cpp203
-rw-r--r--NorthstarDedicatedTest/scriptmodmenu.h3
-rw-r--r--NorthstarDedicatedTest/scriptserverbrowser.cpp441
-rw-r--r--NorthstarDedicatedTest/scriptserverbrowser.h4
-rw-r--r--NorthstarDedicatedTest/scriptservertoclientstringcommand.cpp24
-rw-r--r--NorthstarDedicatedTest/scriptservertoclientstringcommand.h3
-rw-r--r--NorthstarDedicatedTest/serverauthentication.cpp743
-rw-r--r--NorthstarDedicatedTest/serverauthentication.h112
-rw-r--r--NorthstarDedicatedTest/serverchathooks.cpp209
-rw-r--r--NorthstarDedicatedTest/sigscanning.cpp41
-rw-r--r--NorthstarDedicatedTest/sigscanning.h7
-rw-r--r--NorthstarDedicatedTest/sourceconsole.cpp80
-rw-r--r--NorthstarDedicatedTest/sourceinterface.cpp82
-rw-r--r--NorthstarDedicatedTest/squirrel.cpp450
-rw-r--r--NorthstarDedicatedTest/squirrel.h294
-rw-r--r--NorthstarLauncher/NorthstarLauncher.vcxproj (renamed from LauncherInjector/LauncherInjector.vcxproj)10
-rw-r--r--NorthstarLauncher/NorthstarLauncher.vcxproj.filters (renamed from LauncherInjector/LauncherInjector.vcxproj.filters)4
-rw-r--r--NorthstarLauncher/main.cpp (renamed from LauncherInjector/main.cpp)94
-rw-r--r--NorthstarLauncher/ns_icon.ico (renamed from LauncherInjector/ns_icon.ico)bin1441814 -> 1441814 bytes
-rw-r--r--NorthstarLauncher/resource1.h (renamed from LauncherInjector/resource1.h)0
-rw-r--r--NorthstarLauncher/resources.rc (renamed from LauncherInjector/resources.rc)2
-rw-r--r--R2Northstar.sln6
-rw-r--r--README.md2
-rw-r--r--loader_launcher_proxy/Memory.cpp82
-rw-r--r--loader_launcher_proxy/Memory.h24
-rw-r--r--loader_launcher_proxy/dllmain.cpp229
-rw-r--r--loader_launcher_proxy/framework.h4
-rw-r--r--loader_launcher_proxy/loader_launcher_proxy.vcxproj4
-rw-r--r--loader_launcher_proxy/loader_launcher_proxy.vcxproj.filters4
-rw-r--r--loader_launcher_proxy/pch.h2
-rw-r--r--loader_wsock32_proxy/dllmain.cpp64
-rw-r--r--loader_wsock32_proxy/hookutils.cpp54
-rw-r--r--loader_wsock32_proxy/include/MinHook.h186
-rw-r--r--loader_wsock32_proxy/include/MinHook.x64.libbin0 -> 32401 bytes
-rw-r--r--loader_wsock32_proxy/loader.cpp32
-rw-r--r--loader_wsock32_proxy/loader_wsock32_proxy.vcxproj10
-rw-r--r--loader_wsock32_proxy/loader_wsock32_proxy.vcxproj.filters13
-rw-r--r--loader_wsock32_proxy/pch.h4
648 files changed, 15425 insertions, 12192 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..bc423183
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,11 @@
+# For more info on `.editorconfig` file see https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Newline ending every file
+[*]
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+indent_style = tab
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 6838b387..10640d70 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -2,3 +2,6 @@
# Format commit
75bf194b2fca06de805a7bc025c6dd8379250fa5
+
+# Folder rename
+f9bc3c9d1834cb8bd5f872b749b057c33e8b0102
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..727a3060
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,18 @@
+<!--
+WHEN OPENING A PULL REQUEST KEEP IN MIND:
+-> If the changes you made can be summarised in a screenshot, add one (e.g. you changed the layout of an in-game menu)
+-> If the changes you made can be summarised in a screenrecording, add one (e.g. proof that you fixed a certain bug)
+
+-> For fixes, description on how to reproduce the bug are appreciated and help your PR get merged faster
+-> For features, description on how to use the feature is appreciated and will help your PR get merged faster
+
+-> Please use a sensible title for your pull request
+
+-> Please describe the changes you made. The easier it is to understand what you changed, the higher the chances of your PR being merged (in a timely manner).
+
+-> If you made multiple independent changes, please make a new PR for each one. This prevents your PR being blocked from merging by one of the changes you made.
+
+Note that commit messages in PRs will generally be squashed to keep commit history clean.
+-->
+
+Replace this line with a description of your change (and screenshots/screenrecordings if applicable).
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index affe0a37..d49a62f7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,8 +34,8 @@ jobs:
- uses: actions/checkout@v2
- uses: DoozyX/clang-format-lint-action@v0.13
with:
- source: 'NorthstarDedicatedTest LauncherInjector'
- exclude: 'NorthstarDedicatedTest/include loader_launcher_proxy loader_wsock32_proxy'
+ source: 'NorthstarDLL NorthstarLauncher'
+ exclude: 'NorthstarDLL/include loader_launcher_proxy loader_wsock32_proxy'
extensions: 'h,cpp'
clangFormatVersion: 13
style: file
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj
index cddbd3a7..b6f3ea37 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDLL/NorthstarDLL.vcxproj
@@ -1,669 +1,674 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <VCProjectVersion>16.0</VCProjectVersion>
- <Keyword>Win32Proj</Keyword>
- <ProjectGuid>{cfad2623-064f-453c-8196-79ee10292e32}</ProjectGuid>
- <RootNamespace>NorthstarDedicatedTest</RootNamespace>
- <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
- <ProjectName>Northstar</ProjectName>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v143</PlatformToolset>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v143</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
- </ImportGroup>
- <ImportGroup Label="Shared">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <LinkIncremental>true</LinkIncremental>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <LinkIncremental>false</LinkIncremental>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>_DEBUG;NORTHSTARDEDICATEDTEST_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);CURL_STATICLIB</PreprocessorDefinitions>
- <ConformanceMode>true</ConformanceMode>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <LanguageStandard>stdcpp17</LanguageStandard>
- <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableUAC>false</EnableUAC>
- <AdditionalDependencies>$(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcurl\lib\libcurl_a.lib;dbghelp.lib;Wldap32.lib;Normaliz.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <ForceSymbolReferences>
- </ForceSymbolReferences>
- <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- </Link>
- <PreBuildEvent>
- <Command>
- </Command>
- </PreBuildEvent>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>NDEBUG;NORTHSTARDEDICATEDTEST_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);CURL_STATICLIB</PreprocessorDefinitions>
- <ConformanceMode>true</ConformanceMode>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <LanguageStandard>stdcpp17</LanguageStandard>
- <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableUAC>false</EnableUAC>
- <AdditionalDependencies>$(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcurl\lib\libcurl_a.lib;dbghelp.lib;Wldap32.lib;Normaliz.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <ForceSymbolReferences>
- </ForceSymbolReferences>
- <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- </Link>
- <PreBuildEvent>
- <Command>
- </Command>
- </PreBuildEvent>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClInclude Include="audio.h" />
- <ClInclude Include="bansystem.h" />
- <ClInclude Include="bitbuf.h" />
- <ClInclude Include="bits.h" />
- <ClInclude Include="buildainfile.h" />
- <ClInclude Include="chatcommand.h" />
- <ClInclude Include="clientchathooks.h" />
- <ClInclude Include="debugoverlay.h" />
- <ClInclude Include="clientruihooks.h" />
- <ClInclude Include="clientvideooverrides.h" />
- <ClInclude Include="emit_blocker.h" />
- <ClInclude Include="localchatwriter.h" />
- <ClInclude Include="ns_version.h" />
- <ClInclude Include="plugins.h" />
- <ClInclude Include="plugin_abi.h" />
- <ClInclude Include="serverchathooks.h" />
- <ClInclude Include="clientauthhooks.h" />
- <ClInclude Include="color.h" />
- <ClInclude Include="concommand.h" />
- <ClInclude Include="configurables.h" />
- <ClInclude Include="context.h" />
- <ClInclude Include="convar.h" />
- <ClInclude Include="cvar.h" />
- <ClInclude Include="dedicated.h" />
- <ClInclude Include="dedicatedmaterialsystem.h" />
- <ClInclude Include="filesystem.h" />
- <ClInclude Include="gameutils.h" />
- <ClInclude Include="hooks.h" />
- <ClInclude Include="hookutils.h" />
- <ClInclude Include="include\crypto\aes_platform.h" />
- <ClInclude Include="include\crypto\aria.h" />
- <ClInclude Include="include\crypto\asn1.h" />
- <ClInclude Include="include\crypto\asn1err.h" />
- <ClInclude Include="include\crypto\asn1_dsa.h" />
- <ClInclude Include="include\crypto\async.h" />
- <ClInclude Include="include\crypto\asyncerr.h" />
- <ClInclude Include="include\crypto\bioerr.h" />
- <ClInclude Include="include\crypto\bn.h" />
- <ClInclude Include="include\crypto\bnerr.h" />
- <ClInclude Include="include\crypto\bn_conf.h" />
- <ClInclude Include="include\crypto\bn_dh.h" />
- <ClInclude Include="include\crypto\bn_srp.h" />
- <ClInclude Include="include\crypto\buffererr.h" />
- <ClInclude Include="include\crypto\chacha.h" />
- <ClInclude Include="include\crypto\cmll_platform.h" />
- <ClInclude Include="include\crypto\cmperr.h" />
- <ClInclude Include="include\crypto\cmserr.h" />
- <ClInclude Include="include\crypto\comperr.h" />
- <ClInclude Include="include\crypto\conferr.h" />
- <ClInclude Include="include\crypto\crmferr.h" />
- <ClInclude Include="include\crypto\cryptlib.h" />
- <ClInclude Include="include\crypto\cryptoerr.h" />
- <ClInclude Include="include\crypto\cterr.h" />
- <ClInclude Include="include\crypto\ctype.h" />
- <ClInclude Include="include\crypto\decoder.h" />
- <ClInclude Include="include\crypto\decodererr.h" />
- <ClInclude Include="include\crypto\des_platform.h" />
- <ClInclude Include="include\crypto\dh.h" />
- <ClInclude Include="include\crypto\dherr.h" />
- <ClInclude Include="include\crypto\dsa.h" />
- <ClInclude Include="include\crypto\dsaerr.h" />
- <ClInclude Include="include\crypto\dso_conf.h" />
- <ClInclude Include="include\crypto\ec.h" />
- <ClInclude Include="include\crypto\ecerr.h" />
- <ClInclude Include="include\crypto\ecx.h" />
- <ClInclude Include="include\crypto\encoder.h" />
- <ClInclude Include="include\crypto\encodererr.h" />
- <ClInclude Include="include\crypto\engine.h" />
- <ClInclude Include="include\crypto\engineerr.h" />
- <ClInclude Include="include\crypto\err.h" />
- <ClInclude Include="include\crypto\ess.h" />
- <ClInclude Include="include\crypto\esserr.h" />
- <ClInclude Include="include\crypto\evp.h" />
- <ClInclude Include="include\crypto\evperr.h" />
- <ClInclude Include="include\crypto\httperr.h" />
- <ClInclude Include="include\crypto\lhash.h" />
- <ClInclude Include="include\crypto\md32_common.h" />
- <ClInclude Include="include\crypto\modes.h" />
- <ClInclude Include="include\crypto\objects.h" />
- <ClInclude Include="include\crypto\objectserr.h" />
- <ClInclude Include="include\crypto\ocsperr.h" />
- <ClInclude Include="include\crypto\pem.h" />
- <ClInclude Include="include\crypto\pemerr.h" />
- <ClInclude Include="include\crypto\pkcs12err.h" />
- <ClInclude Include="include\crypto\pkcs7.h" />
- <ClInclude Include="include\crypto\pkcs7err.h" />
- <ClInclude Include="include\crypto\poly1305.h" />
- <ClInclude Include="include\crypto\ppc_arch.h" />
- <ClInclude Include="include\crypto\punycode.h" />
- <ClInclude Include="include\crypto\rand.h" />
- <ClInclude Include="include\crypto\randerr.h" />
- <ClInclude Include="include\crypto\rand_pool.h" />
- <ClInclude Include="include\crypto\rsa.h" />
- <ClInclude Include="include\crypto\rsaerr.h" />
- <ClInclude Include="include\crypto\security_bits.h" />
- <ClInclude Include="include\crypto\sha.h" />
- <ClInclude Include="include\crypto\siphash.h" />
- <ClInclude Include="include\crypto\siv.h" />
- <ClInclude Include="include\crypto\sm2.h" />
- <ClInclude Include="include\crypto\sm2err.h" />
- <ClInclude Include="include\crypto\sm4.h" />
- <ClInclude Include="include\crypto\sparc_arch.h" />
- <ClInclude Include="include\crypto\sparse_array.h" />
- <ClInclude Include="include\crypto\store.h" />
- <ClInclude Include="include\crypto\storeerr.h" />
- <ClInclude Include="include\crypto\tserr.h" />
- <ClInclude Include="include\crypto\types.h" />
- <ClInclude Include="include\crypto\uierr.h" />
- <ClInclude Include="include\crypto\x509.h" />
- <ClInclude Include="include\crypto\x509err.h" />
- <ClInclude Include="include\crypto\x509v3err.h" />
- <ClInclude Include="include\crypto\__DECC_INCLUDE_EPILOGUE.H" />
- <ClInclude Include="include\crypto\__DECC_INCLUDE_PROLOGUE.H" />
- <ClInclude Include="include\httplib.h" />
- <ClInclude Include="include\internal\asn1.h" />
- <ClInclude Include="include\internal\bio.h" />
- <ClInclude Include="include\internal\comp.h" />
- <ClInclude Include="include\internal\conf.h" />
- <ClInclude Include="include\internal\constant_time.h" />
- <ClInclude Include="include\internal\core.h" />
- <ClInclude Include="include\internal\cryptlib.h" />
- <ClInclude Include="include\internal\dane.h" />
- <ClInclude Include="include\internal\deprecated.h" />
- <ClInclude Include="include\internal\der.h" />
- <ClInclude Include="include\internal\dso.h" />
- <ClInclude Include="include\internal\dsoerr.h" />
- <ClInclude Include="include\internal\endian.h" />
- <ClInclude Include="include\internal\err.h" />
- <ClInclude Include="include\internal\ffc.h" />
- <ClInclude Include="include\internal\ktls.h" />
- <ClInclude Include="include\internal\namemap.h" />
- <ClInclude Include="include\internal\nelem.h" />
- <ClInclude Include="include\internal\numbers.h" />
- <ClInclude Include="include\internal\o_dir.h" />
- <ClInclude Include="include\internal\packet.h" />
- <ClInclude Include="include\internal\param_build_set.h" />
- <ClInclude Include="include\internal\passphrase.h" />
- <ClInclude Include="include\internal\property.h" />
- <ClInclude Include="include\internal\propertyerr.h" />
- <ClInclude Include="include\internal\provider.h" />
- <ClInclude Include="include\internal\refcount.h" />
- <ClInclude Include="include\internal\sha3.h" />
- <ClInclude Include="include\internal\sizes.h" />
- <ClInclude Include="include\internal\sm3.h" />
- <ClInclude Include="include\internal\sockets.h" />
- <ClInclude Include="include\internal\sslconf.h" />
- <ClInclude Include="include\internal\symhacks.h" />
- <ClInclude Include="include\internal\thread_once.h" />
- <ClInclude Include="include\internal\tlsgroups.h" />
- <ClInclude Include="include\internal\tsan_assist.h" />
- <ClInclude Include="include\internal\unicode.h" />
- <ClInclude Include="include\internal\__DECC_INCLUDE_EPILOGUE.H" />
- <ClInclude Include="include\internal\__DECC_INCLUDE_PROLOGUE.H" />
- <ClInclude Include="include\libcurl\include\curl\curl.h" />
- <ClInclude Include="include\libcurl\include\curl\curlver.h" />
- <ClInclude Include="include\libcurl\include\curl\easy.h" />
- <ClInclude Include="include\libcurl\include\curl\mprintf.h" />
- <ClInclude Include="include\libcurl\include\curl\multi.h" />
- <ClInclude Include="include\libcurl\include\curl\options.h" />
- <ClInclude Include="include\libcurl\include\curl\stdcheaders.h" />
- <ClInclude Include="include\libcurl\include\curl\system.h" />
- <ClInclude Include="include\libcurl\include\curl\typecheck-gcc.h" />
- <ClInclude Include="include\libcurl\include\curl\urlapi.h" />
- <ClInclude Include="include\MinHook.h" />
- <ClInclude Include="include\openssl\aes.h" />
- <ClInclude Include="include\openssl\asn1.h" />
- <ClInclude Include="include\openssl\asn1err.h" />
- <ClInclude Include="include\openssl\asn1t.h" />
- <ClInclude Include="include\openssl\asn1_mac.h" />
- <ClInclude Include="include\openssl\async.h" />
- <ClInclude Include="include\openssl\asyncerr.h" />
- <ClInclude Include="include\openssl\bio.h" />
- <ClInclude Include="include\openssl\bioerr.h" />
- <ClInclude Include="include\openssl\blowfish.h" />
- <ClInclude Include="include\openssl\bn.h" />
- <ClInclude Include="include\openssl\bnerr.h" />
- <ClInclude Include="include\openssl\buffer.h" />
- <ClInclude Include="include\openssl\buffererr.h" />
- <ClInclude Include="include\openssl\camellia.h" />
- <ClInclude Include="include\openssl\cast.h" />
- <ClInclude Include="include\openssl\cmac.h" />
- <ClInclude Include="include\openssl\cmp.h" />
- <ClInclude Include="include\openssl\cmperr.h" />
- <ClInclude Include="include\openssl\cmp_util.h" />
- <ClInclude Include="include\openssl\cms.h" />
- <ClInclude Include="include\openssl\cmserr.h" />
- <ClInclude Include="include\openssl\comp.h" />
- <ClInclude Include="include\openssl\comperr.h" />
- <ClInclude Include="include\openssl\conf.h" />
- <ClInclude Include="include\openssl\conferr.h" />
- <ClInclude Include="include\openssl\configuration.h" />
- <ClInclude Include="include\openssl\conftypes.h" />
- <ClInclude Include="include\openssl\conf_api.h" />
- <ClInclude Include="include\openssl\core.h" />
- <ClInclude Include="include\openssl\core_dispatch.h" />
- <ClInclude Include="include\openssl\core_names.h" />
- <ClInclude Include="include\openssl\core_object.h" />
- <ClInclude Include="include\openssl\crmf.h" />
- <ClInclude Include="include\openssl\crmferr.h" />
- <ClInclude Include="include\openssl\crypto.h" />
- <ClInclude Include="include\openssl\cryptoerr.h" />
- <ClInclude Include="include\openssl\cryptoerr_legacy.h" />
- <ClInclude Include="include\openssl\ct.h" />
- <ClInclude Include="include\openssl\cterr.h" />
- <ClInclude Include="include\openssl\decoder.h" />
- <ClInclude Include="include\openssl\decodererr.h" />
- <ClInclude Include="include\openssl\des.h" />
- <ClInclude Include="include\openssl\dh.h" />
- <ClInclude Include="include\openssl\dherr.h" />
- <ClInclude Include="include\openssl\dsa.h" />
- <ClInclude Include="include\openssl\dsaerr.h" />
- <ClInclude Include="include\openssl\dtls1.h" />
- <ClInclude Include="include\openssl\ebcdic.h" />
- <ClInclude Include="include\openssl\ec.h" />
- <ClInclude Include="include\openssl\ecdh.h" />
- <ClInclude Include="include\openssl\ecdsa.h" />
- <ClInclude Include="include\openssl\ecerr.h" />
- <ClInclude Include="include\openssl\encoder.h" />
- <ClInclude Include="include\openssl\encodererr.h" />
- <ClInclude Include="include\openssl\engine.h" />
- <ClInclude Include="include\openssl\engineerr.h" />
- <ClInclude Include="include\openssl\err.h" />
- <ClInclude Include="include\openssl\ess.h" />
- <ClInclude Include="include\openssl\esserr.h" />
- <ClInclude Include="include\openssl\evp.h" />
- <ClInclude Include="include\openssl\evperr.h" />
- <ClInclude Include="include\openssl\e_os2.h" />
- <ClInclude Include="include\openssl\fipskey.h" />
- <ClInclude Include="include\openssl\fips_names.h" />
- <ClInclude Include="include\openssl\hmac.h" />
- <ClInclude Include="include\openssl\http.h" />
- <ClInclude Include="include\openssl\httperr.h" />
- <ClInclude Include="include\openssl\idea.h" />
- <ClInclude Include="include\openssl\kdf.h" />
- <ClInclude Include="include\openssl\kdferr.h" />
- <ClInclude Include="include\openssl\lhash.h" />
- <ClInclude Include="include\openssl\macros.h" />
- <ClInclude Include="include\openssl\md2.h" />
- <ClInclude Include="include\openssl\md4.h" />
- <ClInclude Include="include\openssl\md5.h" />
- <ClInclude Include="include\openssl\mdc2.h" />
- <ClInclude Include="include\openssl\modes.h" />
- <ClInclude Include="include\openssl\objects.h" />
- <ClInclude Include="include\openssl\objectserr.h" />
- <ClInclude Include="include\openssl\obj_mac.h" />
- <ClInclude Include="include\openssl\ocsp.h" />
- <ClInclude Include="include\openssl\ocsperr.h" />
- <ClInclude Include="include\openssl\opensslconf.h" />
- <ClInclude Include="include\openssl\opensslv.h" />
- <ClInclude Include="include\openssl\ossl_typ.h" />
- <ClInclude Include="include\openssl\params.h" />
- <ClInclude Include="include\openssl\param_build.h" />
- <ClInclude Include="include\openssl\pem.h" />
- <ClInclude Include="include\openssl\pem2.h" />
- <ClInclude Include="include\openssl\pemerr.h" />
- <ClInclude Include="include\openssl\pkcs12.h" />
- <ClInclude Include="include\openssl\pkcs12err.h" />
- <ClInclude Include="include\openssl\pkcs7.h" />
- <ClInclude Include="include\openssl\pkcs7err.h" />
- <ClInclude Include="include\openssl\proverr.h" />
- <ClInclude Include="include\openssl\provider.h" />
- <ClInclude Include="include\openssl\prov_ssl.h" />
- <ClInclude Include="include\openssl\rand.h" />
- <ClInclude Include="include\openssl\randerr.h" />
- <ClInclude Include="include\openssl\rc2.h" />
- <ClInclude Include="include\openssl\rc4.h" />
- <ClInclude Include="include\openssl\rc5.h" />
- <ClInclude Include="include\openssl\ripemd.h" />
- <ClInclude Include="include\openssl\rsa.h" />
- <ClInclude Include="include\openssl\rsaerr.h" />
- <ClInclude Include="include\openssl\safestack.h" />
- <ClInclude Include="include\openssl\seed.h" />
- <ClInclude Include="include\openssl\self_test.h" />
- <ClInclude Include="include\openssl\sha.h" />
- <ClInclude Include="include\openssl\srp.h" />
- <ClInclude Include="include\openssl\srtp.h" />
- <ClInclude Include="include\openssl\ssl.h" />
- <ClInclude Include="include\openssl\ssl2.h" />
- <ClInclude Include="include\openssl\ssl3.h" />
- <ClInclude Include="include\openssl\sslerr.h" />
- <ClInclude Include="include\openssl\sslerr_legacy.h" />
- <ClInclude Include="include\openssl\stack.h" />
- <ClInclude Include="include\openssl\store.h" />
- <ClInclude Include="include\openssl\storeerr.h" />
- <ClInclude Include="include\openssl\symhacks.h" />
- <ClInclude Include="include\openssl\tls1.h" />
- <ClInclude Include="include\openssl\trace.h" />
- <ClInclude Include="include\openssl\ts.h" />
- <ClInclude Include="include\openssl\tserr.h" />
- <ClInclude Include="include\openssl\txt_db.h" />
- <ClInclude Include="include\openssl\types.h" />
- <ClInclude Include="include\openssl\ui.h" />
- <ClInclude Include="include\openssl\uierr.h" />
- <ClInclude Include="include\openssl\whrlpool.h" />
- <ClInclude Include="include\openssl\x509.h" />
- <ClInclude Include="include\openssl\x509err.h" />
- <ClInclude Include="include\openssl\x509v3.h" />
- <ClInclude Include="include\openssl\x509v3err.h" />
- <ClInclude Include="include\openssl\x509_vfy.h" />
- <ClInclude Include="include\openssl\__DECC_INCLUDE_EPILOGUE.H" />
- <ClInclude Include="include\openssl\__DECC_INCLUDE_PROLOGUE.H" />
- <ClInclude Include="include\rapidjson\allocators.h" />
- <ClInclude Include="include\rapidjson\document.h" />
- <ClInclude Include="include\rapidjson\encodedstream.h" />
- <ClInclude Include="include\rapidjson\encodings.h" />
- <ClInclude Include="include\rapidjson\error\en.h" />
- <ClInclude Include="include\rapidjson\error\error.h" />
- <ClInclude Include="include\rapidjson\filereadstream.h" />
- <ClInclude Include="include\rapidjson\filewritestream.h" />
- <ClInclude Include="include\rapidjson\fwd.h" />
- <ClInclude Include="include\rapidjson\internal\biginteger.h" />
- <ClInclude Include="include\rapidjson\internal\diyfp.h" />
- <ClInclude Include="include\rapidjson\internal\dtoa.h" />
- <ClInclude Include="include\rapidjson\internal\ieee754.h" />
- <ClInclude Include="include\rapidjson\internal\itoa.h" />
- <ClInclude Include="include\rapidjson\internal\meta.h" />
- <ClInclude Include="include\rapidjson\internal\pow10.h" />
- <ClInclude Include="include\rapidjson\internal\regex.h" />
- <ClInclude Include="include\rapidjson\internal\stack.h" />
- <ClInclude Include="include\rapidjson\internal\strfunc.h" />
- <ClInclude Include="include\rapidjson\internal\strtod.h" />
- <ClInclude Include="include\rapidjson\internal\swap.h" />
- <ClInclude Include="include\rapidjson\istreamwrapper.h" />
- <ClInclude Include="include\rapidjson\memorybuffer.h" />
- <ClInclude Include="include\rapidjson\memorystream.h" />
- <ClInclude Include="include\rapidjson\msinttypes\inttypes.h" />
- <ClInclude Include="include\rapidjson\msinttypes\stdint.h" />
- <ClInclude Include="include\rapidjson\ostreamwrapper.h" />
- <ClInclude Include="include\rapidjson\pointer.h" />
- <ClInclude Include="include\rapidjson\prettywriter.h" />
- <ClInclude Include="include\rapidjson\rapidjson.h" />
- <ClInclude Include="include\rapidjson\reader.h" />
- <ClInclude Include="include\rapidjson\schema.h" />
- <ClInclude Include="include\rapidjson\stream.h" />
- <ClInclude Include="include\rapidjson\stringbuffer.h" />
- <ClInclude Include="include\rapidjson\writer.h" />
- <ClInclude Include="include\spdlog\async.h" />
- <ClInclude Include="include\spdlog\async_logger-inl.h" />
- <ClInclude Include="include\spdlog\async_logger.h" />
- <ClInclude Include="include\spdlog\cfg\argv.h" />
- <ClInclude Include="include\spdlog\cfg\env.h" />
- <ClInclude Include="include\spdlog\cfg\helpers-inl.h" />
- <ClInclude Include="include\spdlog\cfg\helpers.h" />
- <ClInclude Include="include\spdlog\common-inl.h" />
- <ClInclude Include="include\spdlog\common.h" />
- <ClInclude Include="include\spdlog\details\backtracer-inl.h" />
- <ClInclude Include="include\spdlog\details\backtracer.h" />
- <ClInclude Include="include\spdlog\details\circular_q.h" />
- <ClInclude Include="include\spdlog\details\console_globals.h" />
- <ClInclude Include="include\spdlog\details\file_helper-inl.h" />
- <ClInclude Include="include\spdlog\details\file_helper.h" />
- <ClInclude Include="include\spdlog\details\fmt_helper.h" />
- <ClInclude Include="include\spdlog\details\log_msg-inl.h" />
- <ClInclude Include="include\spdlog\details\log_msg.h" />
- <ClInclude Include="include\spdlog\details\log_msg_buffer-inl.h" />
- <ClInclude Include="include\spdlog\details\log_msg_buffer.h" />
- <ClInclude Include="include\spdlog\details\mpmc_blocking_q.h" />
- <ClInclude Include="include\spdlog\details\null_mutex.h" />
- <ClInclude Include="include\spdlog\details\os-inl.h" />
- <ClInclude Include="include\spdlog\details\os.h" />
- <ClInclude Include="include\spdlog\details\periodic_worker-inl.h" />
- <ClInclude Include="include\spdlog\details\periodic_worker.h" />
- <ClInclude Include="include\spdlog\details\registry-inl.h" />
- <ClInclude Include="include\spdlog\details\registry.h" />
- <ClInclude Include="include\spdlog\details\synchronous_factory.h" />
- <ClInclude Include="include\spdlog\details\tcp_client-windows.h" />
- <ClInclude Include="include\spdlog\details\tcp_client.h" />
- <ClInclude Include="include\spdlog\details\thread_pool-inl.h" />
- <ClInclude Include="include\spdlog\details\thread_pool.h" />
- <ClInclude Include="include\spdlog\details\windows_include.h" />
- <ClInclude Include="include\spdlog\fmt\bin_to_hex.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\chrono.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\color.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\compile.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\core.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\format-inl.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\format.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\locale.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\os.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\ostream.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\posix.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\printf.h" />
- <ClInclude Include="include\spdlog\fmt\bundled\ranges.h" />
- <ClInclude Include="include\spdlog\fmt\chrono.h" />
- <ClInclude Include="include\spdlog\fmt\fmt.h" />
- <ClInclude Include="include\spdlog\fmt\ostr.h" />
- <ClInclude Include="include\spdlog\formatter.h" />
- <ClInclude Include="include\spdlog\fwd.h" />
- <ClInclude Include="include\spdlog\logger-inl.h" />
- <ClInclude Include="include\spdlog\logger.h" />
- <ClInclude Include="include\spdlog\pattern_formatter-inl.h" />
- <ClInclude Include="include\spdlog\pattern_formatter.h" />
- <ClInclude Include="include\spdlog\sinks\android_sink.h" />
- <ClInclude Include="include\spdlog\sinks\ansicolor_sink-inl.h" />
- <ClInclude Include="include\spdlog\sinks\ansicolor_sink.h" />
- <ClInclude Include="include\spdlog\sinks\base_sink-inl.h" />
- <ClInclude Include="include\spdlog\sinks\base_sink.h" />
- <ClInclude Include="include\spdlog\sinks\basic_file_sink-inl.h" />
- <ClInclude Include="include\spdlog\sinks\basic_file_sink.h" />
- <ClInclude Include="include\spdlog\sinks\daily_file_sink.h" />
- <ClInclude Include="include\spdlog\sinks\dist_sink.h" />
- <ClInclude Include="include\spdlog\sinks\dup_filter_sink.h" />
- <ClInclude Include="include\spdlog\sinks\hourly_file_sink.h" />
- <ClInclude Include="include\spdlog\sinks\msvc_sink.h" />
- <ClInclude Include="include\spdlog\sinks\null_sink.h" />
- <ClInclude Include="include\spdlog\sinks\ostream_sink.h" />
- <ClInclude Include="include\spdlog\sinks\ringbuffer_sink.h" />
- <ClInclude Include="include\spdlog\sinks\rotating_file_sink-inl.h" />
- <ClInclude Include="include\spdlog\sinks\rotating_file_sink.h" />
- <ClInclude Include="include\spdlog\sinks\sink-inl.h" />
- <ClInclude Include="include\spdlog\sinks\sink.h" />
- <ClInclude Include="include\spdlog\sinks\stdout_color_sinks-inl.h" />
- <ClInclude Include="include\spdlog\sinks\stdout_color_sinks.h" />
- <ClInclude Include="include\spdlog\sinks\stdout_sinks-inl.h" />
- <ClInclude Include="include\spdlog\sinks\stdout_sinks.h" />
- <ClInclude Include="include\spdlog\sinks\syslog_sink.h" />
- <ClInclude Include="include\spdlog\sinks\systemd_sink.h" />
- <ClInclude Include="include\spdlog\sinks\tcp_sink.h" />
- <ClInclude Include="include\spdlog\sinks\wincolor_sink-inl.h" />
- <ClInclude Include="include\spdlog\sinks\wincolor_sink.h" />
- <ClInclude Include="include\spdlog\sinks\win_eventlog_sink.h" />
- <ClInclude Include="include\spdlog\spdlog-inl.h" />
- <ClInclude Include="include\spdlog\spdlog.h" />
- <ClInclude Include="include\spdlog\stopwatch.h" />
- <ClInclude Include="include\spdlog\tweakme.h" />
- <ClInclude Include="include\spdlog\version.h" />
- <ClInclude Include="keyvalues.h" />
- <ClInclude Include="languagehooks.h" />
- <ClInclude Include="latencyflex.h" />
- <ClInclude Include="logging.h" />
- <ClInclude Include="main.h" />
- <ClInclude Include="masterserver.h" />
- <ClInclude Include="maxplayers.h" />
- <ClInclude Include="memalloc.h" />
- <ClInclude Include="miscclientfixes.h" />
- <ClInclude Include="misccommands.h" />
- <ClInclude Include="miscserverfixes.h" />
- <ClInclude Include="modlocalisation.h" />
- <ClInclude Include="modmanager.h" />
- <ClInclude Include="pch.h" />
- <ClInclude Include="pdef.h" />
- <ClInclude Include="playlist.h" />
- <ClInclude Include="miscserverscript.h" />
- <ClInclude Include="rpakfilesystem.h" />
- <ClInclude Include="scriptbrowserhooks.h" />
- <ClInclude Include="scriptmainmenupromos.h" />
- <ClInclude Include="scriptmodmenu.h" />
- <ClInclude Include="scriptserverbrowser.h" />
- <ClInclude Include="scriptsrson.h" />
- <ClInclude Include="serverauthentication.h" />
- <ClInclude Include="scriptservertoclientstringcommand.h" />
- <ClInclude Include="sigscanning.h" />
- <ClInclude Include="sourceconsole.h" />
- <ClInclude Include="sourceinterface.h" />
- <ClInclude Include="squirrel.h" />
- <ClInclude Include="state.h" />
- <ClInclude Include="ExploitFixes.h" />
- <ClInclude Include="ExploitFixes_UTF8Parser.h" />
- <ClInclude Include="NSMem.h" />
- <ClInclude Include="version.h" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="audio.cpp" />
- <ClCompile Include="bansystem.cpp" />
- <ClCompile Include="bits.cpp" />
- <ClCompile Include="buildainfile.cpp" />
- <ClCompile Include="chatcommand.cpp" />
- <ClCompile Include="clientauthhooks.cpp" />
- <ClCompile Include="clientchathooks.cpp" />
- <ClCompile Include="clientruihooks.cpp" />
- <ClCompile Include="clientvideooverrides.cpp" />
- <ClCompile Include="concommand.cpp" />
- <ClCompile Include="configurables.cpp" />
- <ClCompile Include="context.cpp" />
- <ClCompile Include="convar.cpp" />
- <ClCompile Include="cvar.cpp" />
- <ClCompile Include="debugoverlay.cpp" />
- <ClCompile Include="dedicated.cpp" />
- <ClCompile Include="dedicatedmaterialsystem.cpp" />
- <ClCompile Include="dllmain.cpp" />
- <ClCompile Include="emit_blocker.cpp" />
- <ClCompile Include="filesystem.cpp" />
- <ClCompile Include="gameutils.cpp" />
- <ClCompile Include="hooks.cpp" />
- <ClCompile Include="hookutils.cpp" />
- <ClCompile Include="keyvalues.cpp" />
- <ClCompile Include="latencyflex.cpp" />
- <ClCompile Include="localchatwriter.cpp" />
- <ClCompile Include="maxplayers.cpp" />
- <ClCompile Include="languagehooks.cpp" />
- <ClCompile Include="memalloc.cpp" />
- <ClCompile Include="miscclientfixes.cpp" />
- <ClCompile Include="misccommands.cpp" />
- <ClCompile Include="miscserverfixes.cpp" />
- <ClCompile Include="modlocalisation.cpp" />
- <ClCompile Include="logging.cpp" />
- <ClCompile Include="masterserver.cpp" />
- <ClCompile Include="modmanager.cpp" />
- <ClCompile Include="pch.cpp">
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
- </ClCompile>
- <ClCompile Include="pdef.cpp" />
- <ClCompile Include="playlist.cpp" />
- <ClCompile Include="plugins.cpp" />
- <ClCompile Include="rpakfilesystem.cpp" />
- <ClCompile Include="scriptbrowserhooks.cpp" />
- <ClCompile Include="scriptmainmenupromos.cpp" />
- <ClCompile Include="scriptmodmenu.cpp" />
- <ClCompile Include="scriptserverbrowser.cpp" />
- <ClCompile Include="scriptsrson.cpp" />
- <ClCompile Include="serverauthentication.cpp" />
- <ClCompile Include="miscserverscript.cpp" />
- <ClCompile Include="serverchathooks.cpp" />
- <ClCompile Include="scriptservertoclientstringcommand.cpp" />
- <ClCompile Include="sigscanning.cpp" />
- <ClCompile Include="sourceconsole.cpp" />
- <ClCompile Include="sourceinterface.cpp" />
- <ClCompile Include="squirrel.cpp" />
- <ClCompile Include="ExploitFixes.cpp" />
- <ClCompile Include="version.cpp" />
- </ItemGroup>
- <ItemGroup>
- <None Include="include\crypto\bn_conf.h.in" />
- <None Include="include\crypto\dso_conf.h.in" />
- <None Include="include\openssl\asn1.h.in" />
- <None Include="include\openssl\asn1t.h.in" />
- <None Include="include\openssl\bio.h.in" />
- <None Include="include\openssl\cmp.h.in" />
- <None Include="include\openssl\cms.h.in" />
- <None Include="include\openssl\conf.h.in" />
- <None Include="include\openssl\configuration.h.in" />
- <None Include="include\openssl\crmf.h.in" />
- <None Include="include\openssl\crypto.h.in" />
- <None Include="include\openssl\ct.h.in" />
- <None Include="include\openssl\err.h.in" />
- <None Include="include\openssl\ess.h.in" />
- <None Include="include\openssl\fipskey.h.in" />
- <None Include="include\openssl\lhash.h.in" />
- <None Include="include\openssl\ocsp.h.in" />
- <None Include="include\openssl\opensslv.h.in" />
- <None Include="include\openssl\pkcs12.h.in" />
- <None Include="include\openssl\pkcs7.h.in" />
- <None Include="include\openssl\safestack.h.in" />
- <None Include="include\openssl\srp.h.in" />
- <None Include="include\openssl\ssl.h.in" />
- <None Include="include\openssl\ui.h.in" />
- <None Include="include\openssl\x509.h.in" />
- <None Include="include\openssl\x509v3.h.in" />
- <None Include="include\openssl\x509_vfy.h.in" />
- <None Include="include\spdlog\fmt\bundled\LICENSE.rst" />
- </ItemGroup>
- <ItemGroup>
- <MASM Include="audio_asm.asm" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
- </ImportGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>16.0</VCProjectVersion>
+ <Keyword>Win32Proj</Keyword>
+ <ProjectGuid>{cfad2623-064f-453c-8196-79ee10292e32}</ProjectGuid>
+ <RootNamespace>NorthstarDedicatedTest</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+ <ProjectName>NorthstarDLL</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v143</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v143</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <TargetName>Northstar</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <TargetName>Northstar</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;NORTHSTARDEDICATEDTEST_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);CURL_STATICLIB</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <LanguageStandard>stdcpp20</LanguageStandard>
+ <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableUAC>false</EnableUAC>
+ <AdditionalDependencies>$(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcurl\lib\libcurl_a.lib;dbghelp.lib;Wldap32.lib;Normaliz.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ForceSymbolReferences>
+ </ForceSymbolReferences>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ <PostBuildEvent>
+ <Command>copy /Y "$(TargetPath)" "$(SolutionDir)..\..\"</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;NORTHSTARDEDICATEDTEST_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);CURL_STATICLIB</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <LanguageStandard>stdcpp20</LanguageStandard>
+ <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableUAC>false</EnableUAC>
+ <AdditionalDependencies>$(ProjectDir)include\MinHook.x64.lib;$(ProjectDir)include\libcurl\lib\libcurl_a.lib;dbghelp.lib;Wldap32.lib;Normaliz.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ForceSymbolReferences>
+ </ForceSymbolReferences>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ <PostBuildEvent>
+ <Command>copy /Y "$(TargetPath)" "$(SolutionDir)..\..\"</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="audio.h" />
+ <ClInclude Include="bansystem.h" />
+ <ClInclude Include="bitbuf.h" />
+ <ClInclude Include="bits.h" />
+ <ClInclude Include="crashhandler.h" />
+ <ClInclude Include="squirreldatatypes.h" />
+ <ClInclude Include="limits.h" />
+ <ClInclude Include="maxplayers.h" />
+ <ClInclude Include="memory.h" />
+ <ClInclude Include="printcommand.h" />
+ <ClInclude Include="hoststate.h" />
+ <ClInclude Include="localchatwriter.h" />
+ <ClInclude Include="printmaps.h" />
+ <ClInclude Include="ns_version.h" />
+ <ClInclude Include="plugins.h" />
+ <ClInclude Include="plugin_abi.h" />
+ <ClInclude Include="r2client.h" />
+ <ClInclude Include="r2engine.h" />
+ <ClInclude Include="r2server.h" />
+ <ClInclude Include="serverchathooks.h" />
+ <ClInclude Include="color.h" />
+ <ClInclude Include="concommand.h" />
+ <ClInclude Include="nsprefix.h" />
+ <ClInclude Include="convar.h" />
+ <ClInclude Include="cvar.h" />
+ <ClInclude Include="dedicated.h" />
+ <ClInclude Include="filesystem.h" />
+ <ClInclude Include="hooks.h" />
+ <ClInclude Include="include\crypto\aes_platform.h" />
+ <ClInclude Include="include\crypto\aria.h" />
+ <ClInclude Include="include\crypto\asn1.h" />
+ <ClInclude Include="include\crypto\asn1err.h" />
+ <ClInclude Include="include\crypto\asn1_dsa.h" />
+ <ClInclude Include="include\crypto\async.h" />
+ <ClInclude Include="include\crypto\asyncerr.h" />
+ <ClInclude Include="include\crypto\bioerr.h" />
+ <ClInclude Include="include\crypto\bn.h" />
+ <ClInclude Include="include\crypto\bnerr.h" />
+ <ClInclude Include="include\crypto\bn_conf.h" />
+ <ClInclude Include="include\crypto\bn_dh.h" />
+ <ClInclude Include="include\crypto\bn_srp.h" />
+ <ClInclude Include="include\crypto\buffererr.h" />
+ <ClInclude Include="include\crypto\chacha.h" />
+ <ClInclude Include="include\crypto\cmll_platform.h" />
+ <ClInclude Include="include\crypto\cmperr.h" />
+ <ClInclude Include="include\crypto\cmserr.h" />
+ <ClInclude Include="include\crypto\comperr.h" />
+ <ClInclude Include="include\crypto\conferr.h" />
+ <ClInclude Include="include\crypto\crmferr.h" />
+ <ClInclude Include="include\crypto\cryptlib.h" />
+ <ClInclude Include="include\crypto\cryptoerr.h" />
+ <ClInclude Include="include\crypto\cterr.h" />
+ <ClInclude Include="include\crypto\ctype.h" />
+ <ClInclude Include="include\crypto\decoder.h" />
+ <ClInclude Include="include\crypto\decodererr.h" />
+ <ClInclude Include="include\crypto\des_platform.h" />
+ <ClInclude Include="include\crypto\dh.h" />
+ <ClInclude Include="include\crypto\dherr.h" />
+ <ClInclude Include="include\crypto\dsa.h" />
+ <ClInclude Include="include\crypto\dsaerr.h" />
+ <ClInclude Include="include\crypto\dso_conf.h" />
+ <ClInclude Include="include\crypto\ec.h" />
+ <ClInclude Include="include\crypto\ecerr.h" />
+ <ClInclude Include="include\crypto\ecx.h" />
+ <ClInclude Include="include\crypto\encoder.h" />
+ <ClInclude Include="include\crypto\encodererr.h" />
+ <ClInclude Include="include\crypto\engine.h" />
+ <ClInclude Include="include\crypto\engineerr.h" />
+ <ClInclude Include="include\crypto\err.h" />
+ <ClInclude Include="include\crypto\ess.h" />
+ <ClInclude Include="include\crypto\esserr.h" />
+ <ClInclude Include="include\crypto\evp.h" />
+ <ClInclude Include="include\crypto\evperr.h" />
+ <ClInclude Include="include\crypto\httperr.h" />
+ <ClInclude Include="include\crypto\lhash.h" />
+ <ClInclude Include="include\crypto\md32_common.h" />
+ <ClInclude Include="include\crypto\modes.h" />
+ <ClInclude Include="include\crypto\objects.h" />
+ <ClInclude Include="include\crypto\objectserr.h" />
+ <ClInclude Include="include\crypto\ocsperr.h" />
+ <ClInclude Include="include\crypto\pem.h" />
+ <ClInclude Include="include\crypto\pemerr.h" />
+ <ClInclude Include="include\crypto\pkcs12err.h" />
+ <ClInclude Include="include\crypto\pkcs7.h" />
+ <ClInclude Include="include\crypto\pkcs7err.h" />
+ <ClInclude Include="include\crypto\poly1305.h" />
+ <ClInclude Include="include\crypto\ppc_arch.h" />
+ <ClInclude Include="include\crypto\punycode.h" />
+ <ClInclude Include="include\crypto\rand.h" />
+ <ClInclude Include="include\crypto\randerr.h" />
+ <ClInclude Include="include\crypto\rand_pool.h" />
+ <ClInclude Include="include\crypto\rsa.h" />
+ <ClInclude Include="include\crypto\rsaerr.h" />
+ <ClInclude Include="include\crypto\security_bits.h" />
+ <ClInclude Include="include\crypto\sha.h" />
+ <ClInclude Include="include\crypto\siphash.h" />
+ <ClInclude Include="include\crypto\siv.h" />
+ <ClInclude Include="include\crypto\sm2.h" />
+ <ClInclude Include="include\crypto\sm2err.h" />
+ <ClInclude Include="include\crypto\sm4.h" />
+ <ClInclude Include="include\crypto\sparc_arch.h" />
+ <ClInclude Include="include\crypto\sparse_array.h" />
+ <ClInclude Include="include\crypto\store.h" />
+ <ClInclude Include="include\crypto\storeerr.h" />
+ <ClInclude Include="include\crypto\tserr.h" />
+ <ClInclude Include="include\crypto\types.h" />
+ <ClInclude Include="include\crypto\uierr.h" />
+ <ClInclude Include="include\crypto\x509.h" />
+ <ClInclude Include="include\crypto\x509err.h" />
+ <ClInclude Include="include\crypto\x509v3err.h" />
+ <ClInclude Include="include\crypto\__DECC_INCLUDE_EPILOGUE.H" />
+ <ClInclude Include="include\crypto\__DECC_INCLUDE_PROLOGUE.H" />
+ <ClInclude Include="include\httplib.h" />
+ <ClInclude Include="include\internal\asn1.h" />
+ <ClInclude Include="include\internal\bio.h" />
+ <ClInclude Include="include\internal\comp.h" />
+ <ClInclude Include="include\internal\conf.h" />
+ <ClInclude Include="include\internal\constant_time.h" />
+ <ClInclude Include="include\internal\core.h" />
+ <ClInclude Include="include\internal\cryptlib.h" />
+ <ClInclude Include="include\internal\dane.h" />
+ <ClInclude Include="include\internal\deprecated.h" />
+ <ClInclude Include="include\internal\der.h" />
+ <ClInclude Include="include\internal\dso.h" />
+ <ClInclude Include="include\internal\dsoerr.h" />
+ <ClInclude Include="include\internal\endian.h" />
+ <ClInclude Include="include\internal\err.h" />
+ <ClInclude Include="include\internal\ffc.h" />
+ <ClInclude Include="include\internal\ktls.h" />
+ <ClInclude Include="include\internal\namemap.h" />
+ <ClInclude Include="include\internal\nelem.h" />
+ <ClInclude Include="include\internal\numbers.h" />
+ <ClInclude Include="include\internal\o_dir.h" />
+ <ClInclude Include="include\internal\packet.h" />
+ <ClInclude Include="include\internal\param_build_set.h" />
+ <ClInclude Include="include\internal\passphrase.h" />
+ <ClInclude Include="include\internal\property.h" />
+ <ClInclude Include="include\internal\propertyerr.h" />
+ <ClInclude Include="include\internal\provider.h" />
+ <ClInclude Include="include\internal\refcount.h" />
+ <ClInclude Include="include\internal\sha3.h" />
+ <ClInclude Include="include\internal\sizes.h" />
+ <ClInclude Include="include\internal\sm3.h" />
+ <ClInclude Include="include\internal\sockets.h" />
+ <ClInclude Include="include\internal\sslconf.h" />
+ <ClInclude Include="include\internal\symhacks.h" />
+ <ClInclude Include="include\internal\thread_once.h" />
+ <ClInclude Include="include\internal\tlsgroups.h" />
+ <ClInclude Include="include\internal\tsan_assist.h" />
+ <ClInclude Include="include\internal\unicode.h" />
+ <ClInclude Include="include\internal\__DECC_INCLUDE_EPILOGUE.H" />
+ <ClInclude Include="include\internal\__DECC_INCLUDE_PROLOGUE.H" />
+ <ClInclude Include="include\libcurl\include\curl\curl.h" />
+ <ClInclude Include="include\libcurl\include\curl\curlver.h" />
+ <ClInclude Include="include\libcurl\include\curl\easy.h" />
+ <ClInclude Include="include\libcurl\include\curl\mprintf.h" />
+ <ClInclude Include="include\libcurl\include\curl\multi.h" />
+ <ClInclude Include="include\libcurl\include\curl\options.h" />
+ <ClInclude Include="include\libcurl\include\curl\stdcheaders.h" />
+ <ClInclude Include="include\libcurl\include\curl\system.h" />
+ <ClInclude Include="include\libcurl\include\curl\typecheck-gcc.h" />
+ <ClInclude Include="include\libcurl\include\curl\urlapi.h" />
+ <ClInclude Include="include\MinHook.h" />
+ <ClInclude Include="include\openssl\aes.h" />
+ <ClInclude Include="include\openssl\asn1.h" />
+ <ClInclude Include="include\openssl\asn1err.h" />
+ <ClInclude Include="include\openssl\asn1t.h" />
+ <ClInclude Include="include\openssl\asn1_mac.h" />
+ <ClInclude Include="include\openssl\async.h" />
+ <ClInclude Include="include\openssl\asyncerr.h" />
+ <ClInclude Include="include\openssl\bio.h" />
+ <ClInclude Include="include\openssl\bioerr.h" />
+ <ClInclude Include="include\openssl\blowfish.h" />
+ <ClInclude Include="include\openssl\bn.h" />
+ <ClInclude Include="include\openssl\bnerr.h" />
+ <ClInclude Include="include\openssl\buffer.h" />
+ <ClInclude Include="include\openssl\buffererr.h" />
+ <ClInclude Include="include\openssl\camellia.h" />
+ <ClInclude Include="include\openssl\cast.h" />
+ <ClInclude Include="include\openssl\cmac.h" />
+ <ClInclude Include="include\openssl\cmp.h" />
+ <ClInclude Include="include\openssl\cmperr.h" />
+ <ClInclude Include="include\openssl\cmp_util.h" />
+ <ClInclude Include="include\openssl\cms.h" />
+ <ClInclude Include="include\openssl\cmserr.h" />
+ <ClInclude Include="include\openssl\comp.h" />
+ <ClInclude Include="include\openssl\comperr.h" />
+ <ClInclude Include="include\openssl\conf.h" />
+ <ClInclude Include="include\openssl\conferr.h" />
+ <ClInclude Include="include\openssl\configuration.h" />
+ <ClInclude Include="include\openssl\conftypes.h" />
+ <ClInclude Include="include\openssl\conf_api.h" />
+ <ClInclude Include="include\openssl\core.h" />
+ <ClInclude Include="include\openssl\core_dispatch.h" />
+ <ClInclude Include="include\openssl\core_names.h" />
+ <ClInclude Include="include\openssl\core_object.h" />
+ <ClInclude Include="include\openssl\crmf.h" />
+ <ClInclude Include="include\openssl\crmferr.h" />
+ <ClInclude Include="include\openssl\crypto.h" />
+ <ClInclude Include="include\openssl\cryptoerr.h" />
+ <ClInclude Include="include\openssl\cryptoerr_legacy.h" />
+ <ClInclude Include="include\openssl\ct.h" />
+ <ClInclude Include="include\openssl\cterr.h" />
+ <ClInclude Include="include\openssl\decoder.h" />
+ <ClInclude Include="include\openssl\decodererr.h" />
+ <ClInclude Include="include\openssl\des.h" />
+ <ClInclude Include="include\openssl\dh.h" />
+ <ClInclude Include="include\openssl\dherr.h" />
+ <ClInclude Include="include\openssl\dsa.h" />
+ <ClInclude Include="include\openssl\dsaerr.h" />
+ <ClInclude Include="include\openssl\dtls1.h" />
+ <ClInclude Include="include\openssl\ebcdic.h" />
+ <ClInclude Include="include\openssl\ec.h" />
+ <ClInclude Include="include\openssl\ecdh.h" />
+ <ClInclude Include="include\openssl\ecdsa.h" />
+ <ClInclude Include="include\openssl\ecerr.h" />
+ <ClInclude Include="include\openssl\encoder.h" />
+ <ClInclude Include="include\openssl\encodererr.h" />
+ <ClInclude Include="include\openssl\engine.h" />
+ <ClInclude Include="include\openssl\engineerr.h" />
+ <ClInclude Include="include\openssl\err.h" />
+ <ClInclude Include="include\openssl\ess.h" />
+ <ClInclude Include="include\openssl\esserr.h" />
+ <ClInclude Include="include\openssl\evp.h" />
+ <ClInclude Include="include\openssl\evperr.h" />
+ <ClInclude Include="include\openssl\e_os2.h" />
+ <ClInclude Include="include\openssl\fipskey.h" />
+ <ClInclude Include="include\openssl\fips_names.h" />
+ <ClInclude Include="include\openssl\hmac.h" />
+ <ClInclude Include="include\openssl\http.h" />
+ <ClInclude Include="include\openssl\httperr.h" />
+ <ClInclude Include="include\openssl\idea.h" />
+ <ClInclude Include="include\openssl\kdf.h" />
+ <ClInclude Include="include\openssl\kdferr.h" />
+ <ClInclude Include="include\openssl\lhash.h" />
+ <ClInclude Include="include\openssl\macros.h" />
+ <ClInclude Include="include\openssl\md2.h" />
+ <ClInclude Include="include\openssl\md4.h" />
+ <ClInclude Include="include\openssl\md5.h" />
+ <ClInclude Include="include\openssl\mdc2.h" />
+ <ClInclude Include="include\openssl\modes.h" />
+ <ClInclude Include="include\openssl\objects.h" />
+ <ClInclude Include="include\openssl\objectserr.h" />
+ <ClInclude Include="include\openssl\obj_mac.h" />
+ <ClInclude Include="include\openssl\ocsp.h" />
+ <ClInclude Include="include\openssl\ocsperr.h" />
+ <ClInclude Include="include\openssl\opensslconf.h" />
+ <ClInclude Include="include\openssl\opensslv.h" />
+ <ClInclude Include="include\openssl\ossl_typ.h" />
+ <ClInclude Include="include\openssl\params.h" />
+ <ClInclude Include="include\openssl\param_build.h" />
+ <ClInclude Include="include\openssl\pem.h" />
+ <ClInclude Include="include\openssl\pem2.h" />
+ <ClInclude Include="include\openssl\pemerr.h" />
+ <ClInclude Include="include\openssl\pkcs12.h" />
+ <ClInclude Include="include\openssl\pkcs12err.h" />
+ <ClInclude Include="include\openssl\pkcs7.h" />
+ <ClInclude Include="include\openssl\pkcs7err.h" />
+ <ClInclude Include="include\openssl\proverr.h" />
+ <ClInclude Include="include\openssl\provider.h" />
+ <ClInclude Include="include\openssl\prov_ssl.h" />
+ <ClInclude Include="include\openssl\rand.h" />
+ <ClInclude Include="include\openssl\randerr.h" />
+ <ClInclude Include="include\openssl\rc2.h" />
+ <ClInclude Include="include\openssl\rc4.h" />
+ <ClInclude Include="include\openssl\rc5.h" />
+ <ClInclude Include="include\openssl\ripemd.h" />
+ <ClInclude Include="include\openssl\rsa.h" />
+ <ClInclude Include="include\openssl\rsaerr.h" />
+ <ClInclude Include="include\openssl\safestack.h" />
+ <ClInclude Include="include\openssl\seed.h" />
+ <ClInclude Include="include\openssl\self_test.h" />
+ <ClInclude Include="include\openssl\sha.h" />
+ <ClInclude Include="include\openssl\srp.h" />
+ <ClInclude Include="include\openssl\srtp.h" />
+ <ClInclude Include="include\openssl\ssl.h" />
+ <ClInclude Include="include\openssl\ssl2.h" />
+ <ClInclude Include="include\openssl\ssl3.h" />
+ <ClInclude Include="include\openssl\sslerr.h" />
+ <ClInclude Include="include\openssl\sslerr_legacy.h" />
+ <ClInclude Include="include\openssl\stack.h" />
+ <ClInclude Include="include\openssl\store.h" />
+ <ClInclude Include="include\openssl\storeerr.h" />
+ <ClInclude Include="include\openssl\symhacks.h" />
+ <ClInclude Include="include\openssl\tls1.h" />
+ <ClInclude Include="include\openssl\trace.h" />
+ <ClInclude Include="include\openssl\ts.h" />
+ <ClInclude Include="include\openssl\tserr.h" />
+ <ClInclude Include="include\openssl\txt_db.h" />
+ <ClInclude Include="include\openssl\types.h" />
+ <ClInclude Include="include\openssl\ui.h" />
+ <ClInclude Include="include\openssl\uierr.h" />
+ <ClInclude Include="include\openssl\whrlpool.h" />
+ <ClInclude Include="include\openssl\x509.h" />
+ <ClInclude Include="include\openssl\x509err.h" />
+ <ClInclude Include="include\openssl\x509v3.h" />
+ <ClInclude Include="include\openssl\x509v3err.h" />
+ <ClInclude Include="include\openssl\x509_vfy.h" />
+ <ClInclude Include="include\openssl\__DECC_INCLUDE_EPILOGUE.H" />
+ <ClInclude Include="include\openssl\__DECC_INCLUDE_PROLOGUE.H" />
+ <ClInclude Include="include\rapidjson\allocators.h" />
+ <ClInclude Include="include\rapidjson\document.h" />
+ <ClInclude Include="include\rapidjson\encodedstream.h" />
+ <ClInclude Include="include\rapidjson\encodings.h" />
+ <ClInclude Include="include\rapidjson\error\en.h" />
+ <ClInclude Include="include\rapidjson\error\error.h" />
+ <ClInclude Include="include\rapidjson\filereadstream.h" />
+ <ClInclude Include="include\rapidjson\filewritestream.h" />
+ <ClInclude Include="include\rapidjson\fwd.h" />
+ <ClInclude Include="include\rapidjson\internal\biginteger.h" />
+ <ClInclude Include="include\rapidjson\internal\diyfp.h" />
+ <ClInclude Include="include\rapidjson\internal\dtoa.h" />
+ <ClInclude Include="include\rapidjson\internal\ieee754.h" />
+ <ClInclude Include="include\rapidjson\internal\itoa.h" />
+ <ClInclude Include="include\rapidjson\internal\meta.h" />
+ <ClInclude Include="include\rapidjson\internal\pow10.h" />
+ <ClInclude Include="include\rapidjson\internal\regex.h" />
+ <ClInclude Include="include\rapidjson\internal\stack.h" />
+ <ClInclude Include="include\rapidjson\internal\strfunc.h" />
+ <ClInclude Include="include\rapidjson\internal\strtod.h" />
+ <ClInclude Include="include\rapidjson\internal\swap.h" />
+ <ClInclude Include="include\rapidjson\istreamwrapper.h" />
+ <ClInclude Include="include\rapidjson\memorybuffer.h" />
+ <ClInclude Include="include\rapidjson\memorystream.h" />
+ <ClInclude Include="include\rapidjson\msinttypes\inttypes.h" />
+ <ClInclude Include="include\rapidjson\msinttypes\stdint.h" />
+ <ClInclude Include="include\rapidjson\ostreamwrapper.h" />
+ <ClInclude Include="include\rapidjson\pointer.h" />
+ <ClInclude Include="include\rapidjson\prettywriter.h" />
+ <ClInclude Include="include\rapidjson\rapidjson.h" />
+ <ClInclude Include="include\rapidjson\reader.h" />
+ <ClInclude Include="include\rapidjson\schema.h" />
+ <ClInclude Include="include\rapidjson\stream.h" />
+ <ClInclude Include="include\rapidjson\stringbuffer.h" />
+ <ClInclude Include="include\rapidjson\writer.h" />
+ <ClInclude Include="include\spdlog\async.h" />
+ <ClInclude Include="include\spdlog\async_logger-inl.h" />
+ <ClInclude Include="include\spdlog\async_logger.h" />
+ <ClInclude Include="include\spdlog\cfg\argv.h" />
+ <ClInclude Include="include\spdlog\cfg\env.h" />
+ <ClInclude Include="include\spdlog\cfg\helpers-inl.h" />
+ <ClInclude Include="include\spdlog\cfg\helpers.h" />
+ <ClInclude Include="include\spdlog\common-inl.h" />
+ <ClInclude Include="include\spdlog\common.h" />
+ <ClInclude Include="include\spdlog\details\backtracer-inl.h" />
+ <ClInclude Include="include\spdlog\details\backtracer.h" />
+ <ClInclude Include="include\spdlog\details\circular_q.h" />
+ <ClInclude Include="include\spdlog\details\console_globals.h" />
+ <ClInclude Include="include\spdlog\details\file_helper-inl.h" />
+ <ClInclude Include="include\spdlog\details\file_helper.h" />
+ <ClInclude Include="include\spdlog\details\fmt_helper.h" />
+ <ClInclude Include="include\spdlog\details\log_msg-inl.h" />
+ <ClInclude Include="include\spdlog\details\log_msg.h" />
+ <ClInclude Include="include\spdlog\details\log_msg_buffer-inl.h" />
+ <ClInclude Include="include\spdlog\details\log_msg_buffer.h" />
+ <ClInclude Include="include\spdlog\details\mpmc_blocking_q.h" />
+ <ClInclude Include="include\spdlog\details\null_mutex.h" />
+ <ClInclude Include="include\spdlog\details\os-inl.h" />
+ <ClInclude Include="include\spdlog\details\os.h" />
+ <ClInclude Include="include\spdlog\details\periodic_worker-inl.h" />
+ <ClInclude Include="include\spdlog\details\periodic_worker.h" />
+ <ClInclude Include="include\spdlog\details\registry-inl.h" />
+ <ClInclude Include="include\spdlog\details\registry.h" />
+ <ClInclude Include="include\spdlog\details\synchronous_factory.h" />
+ <ClInclude Include="include\spdlog\details\tcp_client-windows.h" />
+ <ClInclude Include="include\spdlog\details\tcp_client.h" />
+ <ClInclude Include="include\spdlog\details\thread_pool-inl.h" />
+ <ClInclude Include="include\spdlog\details\thread_pool.h" />
+ <ClInclude Include="include\spdlog\details\windows_include.h" />
+ <ClInclude Include="include\spdlog\fmt\bin_to_hex.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\chrono.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\color.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\compile.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\core.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\format-inl.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\format.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\locale.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\os.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\ostream.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\posix.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\printf.h" />
+ <ClInclude Include="include\spdlog\fmt\bundled\ranges.h" />
+ <ClInclude Include="include\spdlog\fmt\chrono.h" />
+ <ClInclude Include="include\spdlog\fmt\fmt.h" />
+ <ClInclude Include="include\spdlog\fmt\ostr.h" />
+ <ClInclude Include="include\spdlog\formatter.h" />
+ <ClInclude Include="include\spdlog\fwd.h" />
+ <ClInclude Include="include\spdlog\logger-inl.h" />
+ <ClInclude Include="include\spdlog\logger.h" />
+ <ClInclude Include="include\spdlog\pattern_formatter-inl.h" />
+ <ClInclude Include="include\spdlog\pattern_formatter.h" />
+ <ClInclude Include="include\spdlog\sinks\android_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\ansicolor_sink-inl.h" />
+ <ClInclude Include="include\spdlog\sinks\ansicolor_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\base_sink-inl.h" />
+ <ClInclude Include="include\spdlog\sinks\base_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\basic_file_sink-inl.h" />
+ <ClInclude Include="include\spdlog\sinks\basic_file_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\daily_file_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\dist_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\dup_filter_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\hourly_file_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\msvc_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\null_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\ostream_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\ringbuffer_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\rotating_file_sink-inl.h" />
+ <ClInclude Include="include\spdlog\sinks\rotating_file_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\sink-inl.h" />
+ <ClInclude Include="include\spdlog\sinks\sink.h" />
+ <ClInclude Include="include\spdlog\sinks\stdout_color_sinks-inl.h" />
+ <ClInclude Include="include\spdlog\sinks\stdout_color_sinks.h" />
+ <ClInclude Include="include\spdlog\sinks\stdout_sinks-inl.h" />
+ <ClInclude Include="include\spdlog\sinks\stdout_sinks.h" />
+ <ClInclude Include="include\spdlog\sinks\syslog_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\systemd_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\tcp_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\wincolor_sink-inl.h" />
+ <ClInclude Include="include\spdlog\sinks\wincolor_sink.h" />
+ <ClInclude Include="include\spdlog\sinks\win_eventlog_sink.h" />
+ <ClInclude Include="include\spdlog\spdlog-inl.h" />
+ <ClInclude Include="include\spdlog\spdlog.h" />
+ <ClInclude Include="include\spdlog\stopwatch.h" />
+ <ClInclude Include="include\spdlog\tweakme.h" />
+ <ClInclude Include="include\spdlog\version.h" />
+ <ClInclude Include="logging.h" />
+ <ClInclude Include="main.h" />
+ <ClInclude Include="masterserver.h" />
+ <ClInclude Include="memalloc.h" />
+ <ClInclude Include="misccommands.h" />
+ <ClInclude Include="modmanager.h" />
+ <ClInclude Include="pch.h" />
+ <ClInclude Include="pdef.h" />
+ <ClInclude Include="playlist.h" />
+ <ClInclude Include="rpakfilesystem.h" />
+ <ClInclude Include="scriptsrson.h" />
+ <ClInclude Include="serverauthentication.h" />
+ <ClInclude Include="serverpresence.h" />
+ <ClInclude Include="sourceconsole.h" />
+ <ClInclude Include="sourceinterface.h" />
+ <ClInclude Include="squirrel.h" />
+ <ClInclude Include="exploitfixes_utf8parser.cpp" />
+ <ClInclude Include="tier0.h" />
+ <ClInclude Include="vector.h" />
+ <ClInclude Include="version.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="audio.cpp" />
+ <ClCompile Include="bansystem.cpp" />
+ <ClCompile Include="bits.cpp" />
+ <ClCompile Include="buildainfile.cpp" />
+ <ClCompile Include="chatcommand.cpp" />
+ <ClCompile Include="clientauthhooks.cpp" />
+ <ClCompile Include="clientchathooks.cpp" />
+ <ClCompile Include="clientruihooks.cpp" />
+ <ClCompile Include="clientvideooverrides.cpp" />
+ <ClCompile Include="concommand.cpp" />
+ <ClCompile Include="exploitfixes_lzss.cpp" />
+ <ClCompile Include="limits.cpp" />
+ <ClCompile Include="memory.cpp" />
+ <ClCompile Include="nsprefix.cpp" />
+ <ClCompile Include="convar.cpp" />
+ <ClCompile Include="crashhandler.cpp" />
+ <ClCompile Include="cvar.cpp" />
+ <ClCompile Include="debugoverlay.cpp" />
+ <ClCompile Include="dedicated.cpp" />
+ <ClCompile Include="dedicatedmaterialsystem.cpp" />
+ <ClCompile Include="demofixes.cpp" />
+ <ClCompile Include="dllmain.cpp" />
+ <ClCompile Include="filesystem.cpp" />
+ <ClCompile Include="hooks.cpp" />
+ <ClCompile Include="host.cpp" />
+ <ClCompile Include="hoststate.cpp" />
+ <ClCompile Include="keyvalues.cpp" />
+ <ClCompile Include="latencyflex.cpp" />
+ <ClCompile Include="localchatwriter.cpp" />
+ <ClCompile Include="printmaps.cpp" />
+ <ClCompile Include="maxplayers.cpp" />
+ <ClCompile Include="languagehooks.cpp" />
+ <ClCompile Include="memalloc.cpp" />
+ <ClCompile Include="misccommands.cpp" />
+ <ClCompile Include="miscserverfixes.cpp" />
+ <ClCompile Include="modlocalisation.cpp" />
+ <ClCompile Include="logging.cpp" />
+ <ClCompile Include="masterserver.cpp" />
+ <ClCompile Include="modmanager.cpp" />
+ <ClCompile Include="pch.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="pdef.cpp" />
+ <ClCompile Include="playlist.cpp" />
+ <ClCompile Include="plugins.cpp" />
+ <ClCompile Include="printcommands.cpp" />
+ <ClCompile Include="r2client.cpp" />
+ <ClCompile Include="r2engine.cpp" />
+ <ClCompile Include="r2server.cpp" />
+ <ClCompile Include="rpakfilesystem.cpp" />
+ <ClCompile Include="runframe.cpp" />
+ <ClCompile Include="scriptbrowserhooks.cpp" />
+ <ClCompile Include="scriptjson.cpp" />
+ <ClCompile Include="scriptdatatables.cpp" />
+ <ClCompile Include="scriptmainmenupromos.cpp" />
+ <ClCompile Include="scriptmodmenu.cpp" />
+ <ClCompile Include="scriptserverbrowser.cpp" />
+ <ClCompile Include="scriptsrson.cpp" />
+ <ClCompile Include="scriptutility.cpp" />
+ <ClCompile Include="serverauthentication.cpp" />
+ <ClCompile Include="miscserverscript.cpp" />
+ <ClCompile Include="serverchathooks.cpp" />
+ <ClCompile Include="scriptservertoclientstringcommand.cpp" />
+ <ClCompile Include="serverpresence.cpp" />
+ <ClCompile Include="sourceconsole.cpp" />
+ <ClCompile Include="sourceinterface.cpp" />
+ <ClCompile Include="squirrel.cpp" />
+ <ClCompile Include="exploitfixes.cpp" />
+ <ClCompile Include="tier0.cpp" />
+ <ClCompile Include="version.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="include\crypto\bn_conf.h.in" />
+ <None Include="include\crypto\dso_conf.h.in" />
+ <None Include="include\openssl\asn1.h.in" />
+ <None Include="include\openssl\asn1t.h.in" />
+ <None Include="include\openssl\bio.h.in" />
+ <None Include="include\openssl\cmp.h.in" />
+ <None Include="include\openssl\cms.h.in" />
+ <None Include="include\openssl\conf.h.in" />
+ <None Include="include\openssl\configuration.h.in" />
+ <None Include="include\openssl\crmf.h.in" />
+ <None Include="include\openssl\crypto.h.in" />
+ <None Include="include\openssl\ct.h.in" />
+ <None Include="include\openssl\err.h.in" />
+ <None Include="include\openssl\ess.h.in" />
+ <None Include="include\openssl\fipskey.h.in" />
+ <None Include="include\openssl\lhash.h.in" />
+ <None Include="include\openssl\ocsp.h.in" />
+ <None Include="include\openssl\opensslv.h.in" />
+ <None Include="include\openssl\pkcs12.h.in" />
+ <None Include="include\openssl\pkcs7.h.in" />
+ <None Include="include\openssl\safestack.h.in" />
+ <None Include="include\openssl\srp.h.in" />
+ <None Include="include\openssl\ssl.h.in" />
+ <None Include="include\openssl\ui.h.in" />
+ <None Include="include\openssl\x509.h.in" />
+ <None Include="include\openssl\x509v3.h.in" />
+ <None Include="include\openssl\x509_vfy.h.in" />
+ <None Include="include\spdlog\fmt\bundled\LICENSE.rst" />
+ </ItemGroup>
+ <ItemGroup>
+ <MASM Include="audio_asm.asm" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
+ </ImportGroup>
</Project> \ No newline at end of file
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters
index 8e429c9f..9b5837d2 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters
@@ -1,1783 +1,1795 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
- <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
- </Filter>
- <Filter Include="Header Files\include">
- <UniqueIdentifier>{d4199e4b-10d2-43ce-af9c-e1fa79e1e64e}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared">
- <UniqueIdentifier>{4d322431-dcaa-4f75-aee0-3b6371cf52a6}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Hooks">
- <UniqueIdentifier>{94259c8c-5411-48bf-af4f-46ca32b7d0bb}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared">
- <UniqueIdentifier>{4f525372-34a8-40b3-8a95-81d77cdfcf7f}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Dedicated">
- <UniqueIdentifier>{947835db-67d6-42c0-870d-62743f85231f}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Dedicated">
- <UniqueIdentifier>{8b8ed12a-9269-4dc3-b932-0daefdf6a388}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Client">
- <UniqueIdentifier>{b6f79919-9735-476d-8798-067a75cbeca0}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Client">
- <UniqueIdentifier>{ca657be5-c2d8-4322-a689-1154aaafe57b}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Convar">
- <UniqueIdentifier>{a18afb37-5fdd-4340-a6b4-a6541593e398}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Convar">
- <UniqueIdentifier>{9751b551-5886-45d4-a039-cbd10445263d}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\spdlog">
- <UniqueIdentifier>{8596cc1c-0492-4467-91e3-1f03b7e19f77}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\spdlog\cfg">
- <UniqueIdentifier>{11eaa578-6336-456e-9c7c-8bd202470945}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\spdlog\fmt">
- <UniqueIdentifier>{7ecd75d2-7eee-41c4-87b6-3b7c2213f34e}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\spdlog\fmt\bundled">
- <UniqueIdentifier>{8afc70f1-639c-49ef-9348-ef6dcece114e}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\spdlog\sinks">
- <UniqueIdentifier>{398efed5-0a92-4d32-b5ba-b4a725b2a70a}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\spdlog\details">
- <UniqueIdentifier>{74567974-c66b-45ef-ab28-97b7154ca224}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Mods">
- <UniqueIdentifier>{3e892d07-2239-44da-9cf3-c288a34cf9a2}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Mods">
- <UniqueIdentifier>{6bbce8a5-38b4-4763-a7cb-4e98012ec245}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\rapidjson">
- <UniqueIdentifier>{4ca5392e-7d3d-4066-833f-f534cd5787c3}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\rapidjson\error">
- <UniqueIdentifier>{94b15898-ef33-41c7-995a-31791fccb7e2}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\rapidjson\internal">
- <UniqueIdentifier>{6495657f-ea55-4552-8aa7-b54eb8e86a99}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\rapidjson\msinttypes">
- <UniqueIdentifier>{85aacdee-0f92-4ec4-b20c-0739c1175055}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Hooks">
- <UniqueIdentifier>{4db0d1e9-9035-457f-87f1-5dc3f13b6b9e}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Mods\Compiled">
- <UniqueIdentifier>{d1f93d1e-0ecb-44fe-a277-d3e75aec2570}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Mods\Compiled">
- <UniqueIdentifier>{14fc0931-acad-46ec-a55e-94f4469d4235}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Server">
- <UniqueIdentifier>{3d41d3fc-8a3b-4358-b3e8-4f06dc96abfe}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Server\Authentication">
- <UniqueIdentifier>{d69760a9-d5ec-4f3e-8f43-f74041654d44}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Server">
- <UniqueIdentifier>{365e5c1f-4b2f-4d8b-a1d8-cdef401ca689}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Server\Authentication">
- <UniqueIdentifier>{24fd0855-9288-4129-93ba-c6cafdc98d1b}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Game Functions">
- <UniqueIdentifier>{2cbddb28-0b17-4881-847d-8773da52b268}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Game Functions">
- <UniqueIdentifier>{0c93d909-e0d6-4c35-a8a4-a13f681a1012}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\openssl">
- <UniqueIdentifier>{4cb0dd89-5f16-4549-a864-34ca3075352a}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\openssl\openssl">
- <UniqueIdentifier>{914d8b8f-6b19-4f23-b746-f40062d72906}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\openssl\internal">
- <UniqueIdentifier>{09516029-fac7-4235-ad61-402977534a0b}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\openssl\crypto">
- <UniqueIdentifier>{8cc1ae44-9dbf-4719-91a2-82e00b8d78e2}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\include\libcurl">
- <UniqueIdentifier>{ea1e17a6-40b7-4e1b-8edb-e9ae704ce604}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Math">
- <UniqueIdentifier>{59b0f68f-daa7-4641-b6fa-8464b56da2bb}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Math">
- <UniqueIdentifier>{44a83740-9d70-480d-9a7a-43b81f8eab9e}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Exploit Fixes">
- <UniqueIdentifier>{4a8a695a-a103-4b1f-b314-0ec19a253119}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Exploit Fixes\UTF8Parser">
- <UniqueIdentifier>{b30e08b1-b962-4264-8cbb-a0a31924b93e}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\ExploitFixes">
- <UniqueIdentifier>{7f609cee-d2c0-46a2-b06e-83b9f0511915}</UniqueIdentifier>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="pch.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="include\MinHook.h">
- <Filter>Header Files\include</Filter>
- </ClInclude>
- <ClInclude Include="hooks.h">
- <Filter>Header Files\Shared\Hooks</Filter>
- </ClInclude>
- <ClInclude Include="hookutils.h">
- <Filter>Header Files\Shared\Hooks</Filter>
- </ClInclude>
- <ClInclude Include="main.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="dedicated.h">
- <Filter>Header Files\Dedicated</Filter>
- </ClInclude>
- <ClInclude Include="sourceconsole.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="squirrel.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="sigscanning.h">
- <Filter>Header Files\Shared\Hooks</Filter>
- </ClInclude>
- <ClInclude Include="logging.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="context.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="sourceinterface.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="concommand.h">
- <Filter>Header Files\Shared\Convar</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\async.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\async_logger.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\async_logger-inl.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\common.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\common-inl.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\formatter.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fwd.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\logger.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\logger-inl.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\pattern_formatter.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\pattern_formatter-inl.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\spdlog.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\spdlog-inl.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\stopwatch.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\tweakme.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\version.h">
- <Filter>Header Files\include\spdlog</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\cfg\argv.h">
- <Filter>Header Files\include\spdlog\cfg</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\cfg\env.h">
- <Filter>Header Files\include\spdlog\cfg</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\cfg\helpers.h">
- <Filter>Header Files\include\spdlog\cfg</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\cfg\helpers-inl.h">
- <Filter>Header Files\include\spdlog\cfg</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bin_to_hex.h">
- <Filter>Header Files\include\spdlog\fmt</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\chrono.h">
- <Filter>Header Files\include\spdlog\fmt</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\fmt.h">
- <Filter>Header Files\include\spdlog\fmt</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\ostr.h">
- <Filter>Header Files\include\spdlog\fmt</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\chrono.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\color.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\compile.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\core.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\format.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\format-inl.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\locale.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\os.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\ostream.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\posix.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\printf.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\fmt\bundled\ranges.h">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\android_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\ansicolor_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\ansicolor_sink-inl.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\base_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\base_sink-inl.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\basic_file_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\basic_file_sink-inl.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\daily_file_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\dist_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\dup_filter_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\hourly_file_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\msvc_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\null_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\ostream_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\ringbuffer_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\rotating_file_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\rotating_file_sink-inl.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\sink-inl.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\stdout_color_sinks.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\stdout_color_sinks-inl.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\stdout_sinks.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\stdout_sinks-inl.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\syslog_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\systemd_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\tcp_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\win_eventlog_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\wincolor_sink.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\sinks\wincolor_sink-inl.h">
- <Filter>Header Files\include\spdlog\sinks</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\backtracer.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\backtracer-inl.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\circular_q.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\console_globals.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\file_helper.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\file_helper-inl.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\fmt_helper.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\log_msg.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\log_msg_buffer.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\log_msg_buffer-inl.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\log_msg-inl.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\mpmc_blocking_q.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\null_mutex.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\os.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\os-inl.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\periodic_worker.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\periodic_worker-inl.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\registry.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\registry-inl.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\synchronous_factory.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\tcp_client.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\tcp_client-windows.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\thread_pool.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\thread_pool-inl.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="include\spdlog\details\windows_include.h">
- <Filter>Header Files\include\spdlog\details</Filter>
- </ClInclude>
- <ClInclude Include="convar.h">
- <Filter>Header Files\Shared\Convar</Filter>
- </ClInclude>
- <ClInclude Include="modmanager.h">
- <Filter>Header Files\Shared\Mods</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\allocators.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\document.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\encodedstream.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\encodings.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\filereadstream.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\filewritestream.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\fwd.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\istreamwrapper.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\memorybuffer.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\memorystream.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\ostreamwrapper.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\pointer.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\prettywriter.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\rapidjson.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\reader.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\schema.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\stream.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\stringbuffer.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\writer.h">
- <Filter>Header Files\include\rapidjson</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\error\en.h">
- <Filter>Header Files\include\rapidjson\error</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\error\error.h">
- <Filter>Header Files\include\rapidjson\error</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\biginteger.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\diyfp.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\dtoa.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\ieee754.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\itoa.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\meta.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\pow10.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\regex.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\stack.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\strfunc.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\strtod.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\internal\swap.h">
- <Filter>Header Files\include\rapidjson\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\msinttypes\inttypes.h">
- <Filter>Header Files\include\rapidjson\msinttypes</Filter>
- </ClInclude>
- <ClInclude Include="include\rapidjson\msinttypes\stdint.h">
- <Filter>Header Files\include\rapidjson\msinttypes</Filter>
- </ClInclude>
- <ClInclude Include="filesystem.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="scriptsrson.h">
- <Filter>Header Files\Shared\Mods\Compiled</Filter>
- </ClInclude>
- <ClInclude Include="serverauthentication.h">
- <Filter>Header Files\Server\Authentication</Filter>
- </ClInclude>
- <ClInclude Include="scriptmodmenu.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="scriptserverbrowser.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="keyvalues.h">
- <Filter>Header Files\Shared\Mods\Compiled</Filter>
- </ClInclude>
- <ClInclude Include="include\httplib.h">
- <Filter>Header Files\include</Filter>
- </ClInclude>
- <ClInclude Include="masterserver.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="chatcommand.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="modlocalisation.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="playlist.h">
- <Filter>Header Files\Server</Filter>
- </ClInclude>
- <ClInclude Include="dedicatedmaterialsystem.h">
- <Filter>Header Files\Dedicated</Filter>
- </ClInclude>
- <ClInclude Include="misccommands.h">
- <Filter>Header Files\Shared\Convar</Filter>
- </ClInclude>
- <ClInclude Include="miscserverscript.h">
- <Filter>Header Files\Server</Filter>
- </ClInclude>
- <ClInclude Include="pdef.h">
- <Filter>Header Files\Shared\Mods\Compiled</Filter>
- </ClInclude>
- <ClInclude Include="clientauthhooks.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="scriptbrowserhooks.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="gameutils.h">
- <Filter>Header Files\Shared\Game Functions</Filter>
- </ClInclude>
- <ClInclude Include="memalloc.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="scriptmainmenupromos.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="miscclientfixes.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\__DECC_INCLUDE_EPILOGUE.H">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\__DECC_INCLUDE_PROLOGUE.H">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\aes.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\asn1.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\asn1_mac.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\asn1err.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\asn1t.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\async.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\asyncerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\bio.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\bioerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\blowfish.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\bn.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\bnerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\buffer.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\buffererr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\camellia.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cast.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cmac.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cmp.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cmp_util.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cmperr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cms.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cmserr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\comp.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\comperr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\conf.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\conf_api.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\conferr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\configuration.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\conftypes.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\core.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\core_dispatch.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\core_names.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\core_object.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\crmf.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\crmferr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\crypto.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cryptoerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cryptoerr_legacy.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ct.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\cterr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\decoder.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\decodererr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\des.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\dh.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\dherr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\dsa.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\dsaerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\dtls1.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\e_os2.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ebcdic.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ec.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ecdh.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ecdsa.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ecerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\encoder.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\encodererr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\engine.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\engineerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\err.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ess.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\esserr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\evp.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\evperr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\fips_names.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\fipskey.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\hmac.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\http.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\httperr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\idea.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\kdf.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\kdferr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\lhash.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\macros.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\md2.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\md4.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\md5.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\mdc2.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\modes.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\obj_mac.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\objects.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\objectserr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ocsp.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ocsperr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\opensslconf.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\opensslv.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ossl_typ.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\param_build.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\params.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\pem.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\pem2.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\pemerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\pkcs7.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\pkcs7err.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\pkcs12.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\pkcs12err.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\prov_ssl.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\proverr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\provider.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\rand.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\randerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\rc2.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\rc4.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\rc5.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ripemd.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\rsa.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\rsaerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\safestack.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\seed.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\self_test.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\sha.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\srp.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\srtp.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ssl.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ssl2.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ssl3.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\sslerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\sslerr_legacy.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\stack.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\store.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\storeerr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\symhacks.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\tls1.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\trace.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ts.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\tserr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\txt_db.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\types.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\ui.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\uierr.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\whrlpool.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\x509.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\x509_vfy.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\x509err.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\x509v3.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\openssl\x509v3err.h">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\__DECC_INCLUDE_EPILOGUE.H">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\__DECC_INCLUDE_PROLOGUE.H">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\aes_platform.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\aria.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\asn1.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\asn1_dsa.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\asn1err.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\async.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\asyncerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\bioerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\bn.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\bn_conf.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\bn_dh.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\bn_srp.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\bnerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\buffererr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\chacha.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\cmll_platform.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\cmperr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\cmserr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\comperr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\conferr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\crmferr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\cryptlib.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\cryptoerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\cterr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\ctype.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\decoder.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\decodererr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\des_platform.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\dh.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\dherr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\dsa.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\dsaerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\dso_conf.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\ec.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\ecerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\ecx.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\encoder.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\encodererr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\engine.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\engineerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\err.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\ess.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\esserr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\evp.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\evperr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\httperr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\lhash.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\md32_common.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\modes.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\objects.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\objectserr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\ocsperr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\pem.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\pemerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\pkcs7.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\pkcs7err.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\pkcs12err.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\poly1305.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\ppc_arch.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\punycode.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\rand.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\rand_pool.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\randerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\rsa.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\rsaerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\security_bits.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\sha.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\siphash.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\siv.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\sm2.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\sm2err.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\sm4.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\sparc_arch.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\sparse_array.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\store.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\storeerr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\tserr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\types.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\uierr.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\x509.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\x509err.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\crypto\x509v3err.h">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\__DECC_INCLUDE_EPILOGUE.H">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\__DECC_INCLUDE_PROLOGUE.H">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\asn1.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\bio.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\comp.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\conf.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\constant_time.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\core.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\cryptlib.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\dane.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\deprecated.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\der.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\dso.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\dsoerr.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\endian.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\err.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\ffc.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\ktls.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\namemap.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\nelem.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\numbers.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\o_dir.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\packet.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\param_build_set.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\passphrase.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\property.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\propertyerr.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\provider.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\refcount.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\sha3.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\sizes.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\sm3.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\sockets.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\sslconf.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\symhacks.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\thread_once.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\tlsgroups.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\tsan_assist.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="include\internal\unicode.h">
- <Filter>Header Files\include\openssl\internal</Filter>
- </ClInclude>
- <ClInclude Include="miscserverfixes.h">
- <Filter>Header Files\Server</Filter>
- </ClInclude>
- <ClInclude Include="maxplayers.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\curl.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\curlver.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\easy.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\mprintf.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\multi.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\options.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\stdcheaders.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\system.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\typecheck-gcc.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="include\libcurl\include\curl\urlapi.h">
- <Filter>Header Files\include\libcurl</Filter>
- </ClInclude>
- <ClInclude Include="rpakfilesystem.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="bansystem.h">
- <Filter>Header Files\Server\Authentication</Filter>
- </ClInclude>
- <ClInclude Include="languagehooks.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="latencyflex.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="audio.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="buildainfile.h">
- <Filter>Header Files\Server</Filter>
- </ClInclude>
- <ClInclude Include="bitbuf.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="configurables.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="cvar.h">
- <Filter>Header Files\Shared\Convar</Filter>
- </ClInclude>
- <ClInclude Include="color.h">
- <Filter>Header Files\Shared\Math</Filter>
- </ClInclude>
- <ClInclude Include="bits.h">
- <Filter>Header Files\Shared\Math</Filter>
- </ClInclude>
- <ClInclude Include="serverchathooks.h">
- <Filter>Header Files\Server</Filter>
- </ClInclude>
- <ClInclude Include="clientchathooks.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="localchatwriter.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="scriptservertoclientstringcommand.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="plugins.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="state.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="plugin_abi.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="debugoverlay.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="clientvideooverrides.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="ExploitFixes_UTF8Parser.h">
- <Filter>Source Files\Shared\Exploit Fixes\UTF8Parser</Filter>
- </ClInclude>
- <ClInclude Include="version.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="clientruihooks.h">
- <Filter>Header Files\Client</Filter>
- </ClInclude>
- <ClInclude Include="ns_version.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="ExploitFixes.h">
- <Filter>Header Files\Shared\ExploitFixes</Filter>
- </ClInclude>
- <ClInclude Include="NSMem.h">
- <Filter>Header Files\Shared\ExploitFixes</Filter>
- </ClInclude>
- <ClInclude Include="emit_blocker.h">
- <Filter>Header Files\Shared\ExploitFixes</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="dllmain.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="pch.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="hooks.cpp">
- <Filter>Source Files\Shared\Hooks</Filter>
- </ClCompile>
- <ClCompile Include="hookutils.cpp">
- <Filter>Source Files\Shared\Hooks</Filter>
- </ClCompile>
- <ClCompile Include="dedicated.cpp">
- <Filter>Source Files\Dedicated</Filter>
- </ClCompile>
- <ClCompile Include="sourceconsole.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="squirrel.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="sigscanning.cpp">
- <Filter>Source Files\Shared\Hooks</Filter>
- </ClCompile>
- <ClCompile Include="logging.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="context.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="sourceinterface.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="convar.cpp">
- <Filter>Source Files\Shared\Convar</Filter>
- </ClCompile>
- <ClCompile Include="concommand.cpp">
- <Filter>Source Files\Shared\Convar</Filter>
- </ClCompile>
- <ClCompile Include="modmanager.cpp">
- <Filter>Source Files\Shared\Mods</Filter>
- </ClCompile>
- <ClCompile Include="filesystem.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="scriptsrson.cpp">
- <Filter>Source Files\Shared\Mods\Compiled</Filter>
- </ClCompile>
- <ClCompile Include="serverauthentication.cpp">
- <Filter>Source Files\Server\Authentication</Filter>
- </ClCompile>
- <ClCompile Include="scriptmodmenu.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="scriptserverbrowser.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="keyvalues.cpp">
- <Filter>Source Files\Shared\Mods\Compiled</Filter>
- </ClCompile>
- <ClCompile Include="masterserver.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="gameutils.cpp">
- <Filter>Source Files\Shared\Game Functions</Filter>
- </ClCompile>
- <ClCompile Include="chatcommand.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="modlocalisation.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="playlist.cpp">
- <Filter>Source Files\Server</Filter>
- </ClCompile>
- <ClCompile Include="dedicatedmaterialsystem.cpp">
- <Filter>Source Files\Dedicated</Filter>
- </ClCompile>
- <ClCompile Include="misccommands.cpp">
- <Filter>Source Files\Shared\Convar</Filter>
- </ClCompile>
- <ClCompile Include="miscserverscript.cpp">
- <Filter>Source Files\Server</Filter>
- </ClCompile>
- <ClCompile Include="pdef.cpp">
- <Filter>Source Files\Shared\Mods\Compiled</Filter>
- </ClCompile>
- <ClCompile Include="clientauthhooks.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="scriptbrowserhooks.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="memalloc.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="scriptmainmenupromos.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="miscclientfixes.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="maxplayers.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="miscserverfixes.cpp">
- <Filter>Source Files\Server</Filter>
- </ClCompile>
- <ClCompile Include="rpakfilesystem.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="bansystem.cpp">
- <Filter>Source Files\Server\Authentication</Filter>
- </ClCompile>
- <ClCompile Include="languagehooks.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="latencyflex.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="audio.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="buildainfile.cpp">
- <Filter>Source Files\Server</Filter>
- </ClCompile>
- <ClCompile Include="configurables.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="cvar.cpp">
- <Filter>Source Files\Shared\Convar</Filter>
- </ClCompile>
- <ClCompile Include="bits.cpp">
- <Filter>Source Files\Shared\Math</Filter>
- </ClCompile>
- <ClCompile Include="serverchathooks.cpp">
- <Filter>Source Files\Server</Filter>
- </ClCompile>
- <ClCompile Include="clientchathooks.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="localchatwriter.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="scriptservertoclientstringcommand.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="plugins.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="debugoverlay.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="clientvideooverrides.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="ExploitFixes.cpp">
- <Filter>Source Files\Shared\Exploit Fixes</Filter>
- </ClCompile>
- <ClCompile Include="version.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="clientruihooks.cpp">
- <Filter>Source Files\Client</Filter>
- </ClCompile>
- <ClCompile Include="emit_blocker.cpp">
- <Filter>Source Files\Shared\Exploit Fixes</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <MASM Include="audio_asm.asm">
- <Filter>Source Files\Client</Filter>
- </MASM>
- </ItemGroup>
- <ItemGroup>
- <None Include="include\spdlog\fmt\bundled\LICENSE.rst">
- <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
- </None>
- <None Include="include\openssl\asn1.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\asn1t.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\bio.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\cmp.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\cms.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\conf.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\configuration.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\crmf.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\crypto.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\ct.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\err.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\ess.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\fipskey.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\lhash.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\ocsp.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\opensslv.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\pkcs7.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\pkcs12.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\safestack.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\srp.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\ssl.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\ui.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\x509.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\x509_vfy.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\openssl\x509v3.h.in">
- <Filter>Header Files\include\openssl\openssl</Filter>
- </None>
- <None Include="include\crypto\bn_conf.h.in">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </None>
- <None Include="include\crypto\dso_conf.h.in">
- <Filter>Header Files\include\openssl\crypto</Filter>
- </None>
- </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Header Files\include">
+ <UniqueIdentifier>{d4199e4b-10d2-43ce-af9c-e1fa79e1e64e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Client">
+ <UniqueIdentifier>{b6f79919-9735-476d-8798-067a75cbeca0}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Client">
+ <UniqueIdentifier>{ca657be5-c2d8-4322-a689-1154aaafe57b}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\spdlog">
+ <UniqueIdentifier>{8596cc1c-0492-4467-91e3-1f03b7e19f77}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\spdlog\cfg">
+ <UniqueIdentifier>{11eaa578-6336-456e-9c7c-8bd202470945}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\spdlog\fmt">
+ <UniqueIdentifier>{7ecd75d2-7eee-41c4-87b6-3b7c2213f34e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\spdlog\fmt\bundled">
+ <UniqueIdentifier>{8afc70f1-639c-49ef-9348-ef6dcece114e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\spdlog\sinks">
+ <UniqueIdentifier>{398efed5-0a92-4d32-b5ba-b4a725b2a70a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\spdlog\details">
+ <UniqueIdentifier>{74567974-c66b-45ef-ab28-97b7154ca224}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\rapidjson">
+ <UniqueIdentifier>{4ca5392e-7d3d-4066-833f-f534cd5787c3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\rapidjson\error">
+ <UniqueIdentifier>{94b15898-ef33-41c7-995a-31791fccb7e2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\rapidjson\internal">
+ <UniqueIdentifier>{6495657f-ea55-4552-8aa7-b54eb8e86a99}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\rapidjson\msinttypes">
+ <UniqueIdentifier>{85aacdee-0f92-4ec4-b20c-0739c1175055}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Server">
+ <UniqueIdentifier>{3d41d3fc-8a3b-4358-b3e8-4f06dc96abfe}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Server\Authentication">
+ <UniqueIdentifier>{d69760a9-d5ec-4f3e-8f43-f74041654d44}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Server">
+ <UniqueIdentifier>{365e5c1f-4b2f-4d8b-a1d8-cdef401ca689}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Server\Authentication">
+ <UniqueIdentifier>{24fd0855-9288-4129-93ba-c6cafdc98d1b}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\openssl">
+ <UniqueIdentifier>{4cb0dd89-5f16-4549-a864-34ca3075352a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\openssl\openssl">
+ <UniqueIdentifier>{914d8b8f-6b19-4f23-b746-f40062d72906}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\openssl\internal">
+ <UniqueIdentifier>{09516029-fac7-4235-ad61-402977534a0b}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\openssl\crypto">
+ <UniqueIdentifier>{8cc1ae44-9dbf-4719-91a2-82e00b8d78e2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\include\libcurl">
+ <UniqueIdentifier>{ea1e17a6-40b7-4e1b-8edb-e9ae704ce604}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Client\Scripted">
+ <UniqueIdentifier>{51910ba0-2ff8-461d-9f67-8d7907b57d22}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Server\Scripted">
+ <UniqueIdentifier>{325e0d7d-6832-496d-8d8e-968fdfa5dd40}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Server\Scripted">
+ <UniqueIdentifier>{802d0771-62f1-4733-89f9-57a4d8864b8d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Console">
+ <UniqueIdentifier>{04fd662a-6e70-494c-b720-c694a5cc2fb1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Convar">
+ <UniqueIdentifier>{a18afb37-5fdd-4340-a6b4-a6541593e398}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Exploit Fixes">
+ <UniqueIdentifier>{4a8a695a-a103-4b1f-b314-0ec19a253119}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Filesystem">
+ <UniqueIdentifier>{d8a83b5e-9a23-4124-824f-eab37880cb08}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Game Functions">
+ <UniqueIdentifier>{2cbddb28-0b17-4881-847d-8773da52b268}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Hooks">
+ <UniqueIdentifier>{4db0d1e9-9035-457f-87f1-5dc3f13b6b9e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Math">
+ <UniqueIdentifier>{59b0f68f-daa7-4641-b6fa-8464b56da2bb}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Mods">
+ <UniqueIdentifier>{3e892d07-2239-44da-9cf3-c288a34cf9a2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Mods\Compiled Assets">
+ <UniqueIdentifier>{14fc0931-acad-46ec-a55e-94f4469d4235}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Dedicated Server">
+ <UniqueIdentifier>{947835db-67d6-42c0-870d-62743f85231f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Console">
+ <UniqueIdentifier>{bf0769d8-40fd-4701-85e9-7ed94aab2283}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Convar">
+ <UniqueIdentifier>{9751b551-5886-45d4-a039-cbd10445263d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Exploit Fixes">
+ <UniqueIdentifier>{96101d42-72af-4fd1-8559-8d1d1ff66240}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Filesystem">
+ <UniqueIdentifier>{ee3ba13a-3061-41d7-981d-328ac2596fd2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Game Functions">
+ <UniqueIdentifier>{0c93d909-e0d6-4c35-a8a4-a13f681a1012}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Hooks">
+ <UniqueIdentifier>{94259c8c-5411-48bf-af4f-46ca32b7d0bb}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Math">
+ <UniqueIdentifier>{44a83740-9d70-480d-9a7a-43b81f8eab9e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Mods">
+ <UniqueIdentifier>{6bbce8a5-38b4-4763-a7cb-4e98012ec245}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Mods\Compiled Assets">
+ <UniqueIdentifier>{826d5193-3ad0-434b-ba7c-dd24ed4bbd0c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Dedicated Server">
+ <UniqueIdentifier>{0f1ba4c4-78ee-4b05-afa5-6f598063f5c1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Squirrel">
+ <UniqueIdentifier>{ca669b16-b8bb-4654-993f-fffa44c914f1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Squirrel">
+ <UniqueIdentifier>{26365f16-ff52-4e80-a01b-2ca020376c93}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Scripted">
+ <UniqueIdentifier>{7263403a-7550-4aa2-a724-f622ab200eed}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="pch.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\MinHook.h">
+ <Filter>Header Files\include</Filter>
+ </ClInclude>
+ <ClInclude Include="main.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="sourceconsole.h">
+ <Filter>Header Files\Client</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\async.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\async_logger.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\async_logger-inl.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\common.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\common-inl.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\formatter.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fwd.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\logger.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\logger-inl.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\pattern_formatter.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\pattern_formatter-inl.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\spdlog.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\spdlog-inl.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\stopwatch.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\tweakme.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\version.h">
+ <Filter>Header Files\include\spdlog</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\cfg\argv.h">
+ <Filter>Header Files\include\spdlog\cfg</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\cfg\env.h">
+ <Filter>Header Files\include\spdlog\cfg</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\cfg\helpers.h">
+ <Filter>Header Files\include\spdlog\cfg</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\cfg\helpers-inl.h">
+ <Filter>Header Files\include\spdlog\cfg</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bin_to_hex.h">
+ <Filter>Header Files\include\spdlog\fmt</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\chrono.h">
+ <Filter>Header Files\include\spdlog\fmt</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\fmt.h">
+ <Filter>Header Files\include\spdlog\fmt</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\ostr.h">
+ <Filter>Header Files\include\spdlog\fmt</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\chrono.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\color.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\compile.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\core.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\format.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\format-inl.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\locale.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\os.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\ostream.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\posix.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\printf.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\fmt\bundled\ranges.h">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\android_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\ansicolor_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\ansicolor_sink-inl.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\base_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\base_sink-inl.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\basic_file_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\basic_file_sink-inl.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\daily_file_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\dist_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\dup_filter_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\hourly_file_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\msvc_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\null_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\ostream_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\ringbuffer_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\rotating_file_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\rotating_file_sink-inl.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\sink-inl.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\stdout_color_sinks.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\stdout_color_sinks-inl.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\stdout_sinks.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\stdout_sinks-inl.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\syslog_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\systemd_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\tcp_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\win_eventlog_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\wincolor_sink.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\sinks\wincolor_sink-inl.h">
+ <Filter>Header Files\include\spdlog\sinks</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\backtracer.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\backtracer-inl.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\circular_q.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\console_globals.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\file_helper.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\file_helper-inl.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\fmt_helper.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\log_msg.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\log_msg_buffer.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\log_msg_buffer-inl.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\log_msg-inl.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\mpmc_blocking_q.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\null_mutex.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\os.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\os-inl.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\periodic_worker.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\periodic_worker-inl.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\registry.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\registry-inl.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\synchronous_factory.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\tcp_client.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\tcp_client-windows.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\thread_pool.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\thread_pool-inl.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\spdlog\details\windows_include.h">
+ <Filter>Header Files\include\spdlog\details</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\allocators.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\document.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\encodedstream.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\encodings.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\filereadstream.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\filewritestream.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\fwd.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\istreamwrapper.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\memorybuffer.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\memorystream.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\ostreamwrapper.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\pointer.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\prettywriter.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\rapidjson.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\reader.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\schema.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\stream.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\stringbuffer.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\writer.h">
+ <Filter>Header Files\include\rapidjson</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\error\en.h">
+ <Filter>Header Files\include\rapidjson\error</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\error\error.h">
+ <Filter>Header Files\include\rapidjson\error</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\biginteger.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\diyfp.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\dtoa.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\ieee754.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\itoa.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\meta.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\pow10.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\regex.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\stack.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\strfunc.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\strtod.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\internal\swap.h">
+ <Filter>Header Files\include\rapidjson\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\msinttypes\inttypes.h">
+ <Filter>Header Files\include\rapidjson\msinttypes</Filter>
+ </ClInclude>
+ <ClInclude Include="include\rapidjson\msinttypes\stdint.h">
+ <Filter>Header Files\include\rapidjson\msinttypes</Filter>
+ </ClInclude>
+ <ClInclude Include="serverauthentication.h">
+ <Filter>Header Files\Server\Authentication</Filter>
+ </ClInclude>
+ <ClInclude Include="include\httplib.h">
+ <Filter>Header Files\include</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\__DECC_INCLUDE_EPILOGUE.H">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\__DECC_INCLUDE_PROLOGUE.H">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\aes.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\asn1.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\asn1_mac.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\asn1err.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\asn1t.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\async.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\asyncerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\bio.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\bioerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\blowfish.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\bn.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\bnerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\buffer.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\buffererr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\camellia.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cast.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cmac.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cmp.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cmp_util.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cmperr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cms.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cmserr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\comp.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\comperr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\conf.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\conf_api.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\conferr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\configuration.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\conftypes.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\core.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\core_dispatch.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\core_names.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\core_object.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\crmf.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\crmferr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\crypto.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cryptoerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cryptoerr_legacy.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ct.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\cterr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\decoder.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\decodererr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\des.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\dh.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\dherr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\dsa.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\dsaerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\dtls1.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\e_os2.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ebcdic.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ec.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ecdh.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ecdsa.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ecerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\encoder.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\encodererr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\engine.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\engineerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\err.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ess.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\esserr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\evp.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\evperr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\fips_names.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\fipskey.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\hmac.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\http.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\httperr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\idea.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\kdf.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\kdferr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\lhash.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\macros.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\md2.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\md4.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\md5.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\mdc2.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\modes.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\obj_mac.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\objects.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\objectserr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ocsp.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ocsperr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\opensslconf.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\opensslv.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ossl_typ.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\param_build.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\params.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\pem.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\pem2.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\pemerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\pkcs7.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\pkcs7err.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\pkcs12.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\pkcs12err.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\prov_ssl.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\proverr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\provider.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\rand.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\randerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\rc2.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\rc4.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\rc5.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ripemd.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\rsa.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\rsaerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\safestack.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\seed.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\self_test.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\sha.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\srp.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\srtp.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ssl.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ssl2.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ssl3.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\sslerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\sslerr_legacy.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\stack.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\store.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\storeerr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\symhacks.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\tls1.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\trace.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ts.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\tserr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\txt_db.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\types.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\ui.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\uierr.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\whrlpool.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\x509.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\x509_vfy.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\x509err.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\x509v3.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\openssl\x509v3err.h">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\__DECC_INCLUDE_EPILOGUE.H">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\__DECC_INCLUDE_PROLOGUE.H">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\aes_platform.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\aria.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\asn1.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\asn1_dsa.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\asn1err.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\async.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\asyncerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\bioerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\bn.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\bn_conf.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\bn_dh.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\bn_srp.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\bnerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\buffererr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\chacha.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\cmll_platform.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\cmperr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\cmserr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\comperr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\conferr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\crmferr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\cryptlib.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\cryptoerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\cterr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\ctype.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\decoder.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\decodererr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\des_platform.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\dh.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\dherr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\dsa.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\dsaerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\dso_conf.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\ec.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\ecerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\ecx.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\encoder.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\encodererr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\engine.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\engineerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\err.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\ess.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\esserr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\evp.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\evperr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\httperr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\lhash.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\md32_common.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\modes.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\objects.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\objectserr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\ocsperr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\pem.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\pemerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\pkcs7.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\pkcs7err.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\pkcs12err.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\poly1305.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\ppc_arch.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\punycode.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\rand.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\rand_pool.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\randerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\rsa.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\rsaerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\security_bits.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\sha.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\siphash.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\siv.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\sm2.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\sm2err.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\sm4.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\sparc_arch.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\sparse_array.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\store.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\storeerr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\tserr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\types.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\uierr.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\x509.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\x509err.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\crypto\x509v3err.h">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\__DECC_INCLUDE_EPILOGUE.H">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\__DECC_INCLUDE_PROLOGUE.H">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\asn1.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\bio.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\comp.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\conf.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\constant_time.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\core.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\cryptlib.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\dane.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\deprecated.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\der.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\dso.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\dsoerr.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\endian.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\err.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\ffc.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\ktls.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\namemap.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\nelem.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\numbers.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\o_dir.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\packet.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\param_build_set.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\passphrase.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\property.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\propertyerr.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\provider.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\refcount.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\sha3.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\sizes.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\sm3.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\sockets.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\sslconf.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\symhacks.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\thread_once.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\tlsgroups.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\tsan_assist.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\internal\unicode.h">
+ <Filter>Header Files\include\openssl\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\curl.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\curlver.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\easy.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\mprintf.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\multi.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\options.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\stdcheaders.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\system.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\typecheck-gcc.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="include\libcurl\include\curl\urlapi.h">
+ <Filter>Header Files\include\libcurl</Filter>
+ </ClInclude>
+ <ClInclude Include="bansystem.h">
+ <Filter>Header Files\Server\Authentication</Filter>
+ </ClInclude>
+ <ClInclude Include="audio.h">
+ <Filter>Header Files\Client</Filter>
+ </ClInclude>
+ <ClInclude Include="localchatwriter.h">
+ <Filter>Header Files\Client</Filter>
+ </ClInclude>
+ <ClInclude Include="plugins.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="plugin_abi.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ns_version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="serverchathooks.h">
+ <Filter>Header Files\Server\Scripted</Filter>
+ </ClInclude>
+ <ClInclude Include="dedicated.h">
+ <Filter>Header Files\Dedicated Server</Filter>
+ </ClInclude>
+ <ClInclude Include="nsprefix.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="exploitfixes_utf8parser.cpp">
+ <Filter>Source Files\Exploit Fixes</Filter>
+ </ClInclude>
+ <ClInclude Include="crashhandler.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="hoststate.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="masterserver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="memalloc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="playlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="sourceinterface.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="bits.h">
+ <Filter>Header Files\Math</Filter>
+ </ClInclude>
+ <ClInclude Include="bitbuf.h">
+ <Filter>Header Files\Math</Filter>
+ </ClInclude>
+ <ClInclude Include="convar.h">
+ <Filter>Header Files\Convar</Filter>
+ </ClInclude>
+ <ClInclude Include="concommand.h">
+ <Filter>Header Files\Convar</Filter>
+ </ClInclude>
+ <ClInclude Include="cvar.h">
+ <Filter>Header Files\Convar</Filter>
+ </ClInclude>
+ <ClInclude Include="filesystem.h">
+ <Filter>Header Files\Filesystem</Filter>
+ </ClInclude>
+ <ClInclude Include="hooks.h">
+ <Filter>Header Files\Hooks</Filter>
+ </ClInclude>
+ <ClInclude Include="limits.h">
+ <Filter>Header Files\Exploit Fixes</Filter>
+ </ClInclude>
+ <ClInclude Include="logging.h">
+ <Filter>Header Files\Console</Filter>
+ </ClInclude>
+ <ClInclude Include="misccommands.h">
+ <Filter>Header Files\Convar</Filter>
+ </ClInclude>
+ <ClInclude Include="modmanager.h">
+ <Filter>Header Files\Mods</Filter>
+ </ClInclude>
+ <ClInclude Include="pdef.h">
+ <Filter>Header Files\Mods\Compiled Assets</Filter>
+ </ClInclude>
+ <ClInclude Include="printcommand.h">
+ <Filter>Header Files\Console</Filter>
+ </ClInclude>
+ <ClInclude Include="printmaps.h">
+ <Filter>Header Files\Console</Filter>
+ </ClInclude>
+ <ClInclude Include="r2client.h">
+ <Filter>Header Files\Game Functions</Filter>
+ </ClInclude>
+ <ClInclude Include="r2engine.h">
+ <Filter>Header Files\Game Functions</Filter>
+ </ClInclude>
+ <ClInclude Include="r2server.h">
+ <Filter>Header Files\Game Functions</Filter>
+ </ClInclude>
+ <ClInclude Include="scriptsrson.h">
+ <Filter>Header Files\Mods\Compiled Assets</Filter>
+ </ClInclude>
+ <ClInclude Include="tier0.h">
+ <Filter>Header Files\Game Functions</Filter>
+ </ClInclude>
+ <ClInclude Include="rpakfilesystem.h">
+ <Filter>Header Files\Filesystem</Filter>
+ </ClInclude>
+ <ClInclude Include="color.h">
+ <Filter>Header Files\Math</Filter>
+ </ClInclude>
+ <ClInclude Include="serverpresence.h">
+ <Filter>Header Files\Server</Filter>
+ </ClInclude>
+ <ClInclude Include="memory.h">
+ <Filter>Header Files\Hooks</Filter>
+ </ClInclude>
+ <ClInclude Include="maxplayers.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="squirrel.h">
+ <Filter>Header Files\Squirrel</Filter>
+ </ClInclude>
+ <ClInclude Include="squirreldatatypes.h">
+ <Filter>Header Files\Squirrel</Filter>
+ </ClInclude>
+ <ClInclude Include="vector.h">
+ <Filter>Header Files\Math</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="pch.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dedicated.cpp">
+ <Filter>Source Files\Dedicated Server</Filter>
+ </ClCompile>
+ <ClCompile Include="sourceconsole.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="modmanager.cpp">
+ <Filter>Source Files\Mods</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptsrson.cpp">
+ <Filter>Source Files\Mods\Compiled Assets</Filter>
+ </ClCompile>
+ <ClCompile Include="serverauthentication.cpp">
+ <Filter>Source Files\Server\Authentication</Filter>
+ </ClCompile>
+ <ClCompile Include="keyvalues.cpp">
+ <Filter>Source Files\Mods\Compiled Assets</Filter>
+ </ClCompile>
+ <ClCompile Include="chatcommand.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="modlocalisation.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="dedicatedmaterialsystem.cpp">
+ <Filter>Source Files\Dedicated Server</Filter>
+ </ClCompile>
+ <ClCompile Include="pdef.cpp">
+ <Filter>Source Files\Mods\Compiled Assets</Filter>
+ </ClCompile>
+ <ClCompile Include="clientauthhooks.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="miscserverfixes.cpp">
+ <Filter>Source Files\Server</Filter>
+ </ClCompile>
+ <ClCompile Include="bansystem.cpp">
+ <Filter>Source Files\Server\Authentication</Filter>
+ </ClCompile>
+ <ClCompile Include="languagehooks.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="latencyflex.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="audio.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="buildainfile.cpp">
+ <Filter>Source Files\Server</Filter>
+ </ClCompile>
+ <ClCompile Include="localchatwriter.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="plugins.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="debugoverlay.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="clientvideooverrides.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="version.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="clientruihooks.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptmainmenupromos.cpp">
+ <Filter>Source Files\Client\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="clientchathooks.cpp">
+ <Filter>Source Files\Client\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptmodmenu.cpp">
+ <Filter>Source Files\Client\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptservertoclientstringcommand.cpp">
+ <Filter>Source Files\Client\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptserverbrowser.cpp">
+ <Filter>Source Files\Client\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptbrowserhooks.cpp">
+ <Filter>Source Files\Client\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="serverchathooks.cpp">
+ <Filter>Source Files\Server\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="miscserverscript.cpp">
+ <Filter>Source Files\Server\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="demofixes.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
+ <ClCompile Include="nsprefix.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllmain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="crashhandler.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="host.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="hoststate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="masterserver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="maxplayers.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="memalloc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="playlist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="sourceinterface.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="r2server.cpp">
+ <Filter>Source Files\Game Functions</Filter>
+ </ClCompile>
+ <ClCompile Include="r2client.cpp">
+ <Filter>Source Files\Game Functions</Filter>
+ </ClCompile>
+ <ClCompile Include="r2engine.cpp">
+ <Filter>Source Files\Game Functions</Filter>
+ </ClCompile>
+ <ClCompile Include="rpakfilesystem.cpp">
+ <Filter>Source Files\Filesystem</Filter>
+ </ClCompile>
+ <ClCompile Include="filesystem.cpp">
+ <Filter>Source Files\Filesystem</Filter>
+ </ClCompile>
+ <ClCompile Include="exploitfixes.cpp">
+ <Filter>Source Files\Exploit Fixes</Filter>
+ </ClCompile>
+ <ClCompile Include="limits.cpp">
+ <Filter>Source Files\Exploit Fixes</Filter>
+ </ClCompile>
+ <ClCompile Include="hooks.cpp">
+ <Filter>Source Files\Hooks</Filter>
+ </ClCompile>
+ <ClCompile Include="bits.cpp">
+ <Filter>Source Files\Math</Filter>
+ </ClCompile>
+ <ClCompile Include="convar.cpp">
+ <Filter>Source Files\Convar</Filter>
+ </ClCompile>
+ <ClCompile Include="concommand.cpp">
+ <Filter>Source Files\Convar</Filter>
+ </ClCompile>
+ <ClCompile Include="printcommands.cpp">
+ <Filter>Source Files\Console</Filter>
+ </ClCompile>
+ <ClCompile Include="printmaps.cpp">
+ <Filter>Source Files\Console</Filter>
+ </ClCompile>
+ <ClCompile Include="cvar.cpp">
+ <Filter>Source Files\Convar</Filter>
+ </ClCompile>
+ <ClCompile Include="misccommands.cpp">
+ <Filter>Source Files\Convar</Filter>
+ </ClCompile>
+ <ClCompile Include="tier0.cpp">
+ <Filter>Source Files\Game Functions</Filter>
+ </ClCompile>
+ <ClCompile Include="logging.cpp">
+ <Filter>Source Files\Console</Filter>
+ </ClCompile>
+ <ClCompile Include="serverpresence.cpp">
+ <Filter>Source Files\Server</Filter>
+ </ClCompile>
+ <ClCompile Include="runframe.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="memory.cpp">
+ <Filter>Source Files\Hooks</Filter>
+ </ClCompile>
+ <ClCompile Include="exploitfixes_lzss.cpp">
+ <Filter>Source Files\Exploit Fixes</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptutility.cpp">
+ <Filter>Source Files\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptjson.cpp">
+ <Filter>Source Files\Scripted</Filter>
+ </ClCompile>
+ <ClCompile Include="squirrel.cpp">
+ <Filter>Source Files\Squirrel</Filter>
+ </ClCompile>
+ <ClCompile Include="scriptdatatables.cpp">
+ <Filter>Source Files\Scripted</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <MASM Include="audio_asm.asm">
+ <Filter>Source Files\Client</Filter>
+ </MASM>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="include\spdlog\fmt\bundled\LICENSE.rst">
+ <Filter>Header Files\include\spdlog\fmt\bundled</Filter>
+ </None>
+ <None Include="include\openssl\asn1.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\asn1t.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\bio.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\cmp.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\cms.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\conf.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\configuration.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\crmf.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\crypto.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\ct.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\err.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\ess.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\fipskey.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\lhash.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\ocsp.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\opensslv.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\pkcs7.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\pkcs12.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\safestack.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\srp.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\ssl.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\ui.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\x509.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\x509_vfy.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\openssl\x509v3.h.in">
+ <Filter>Header Files\include\openssl\openssl</Filter>
+ </None>
+ <None Include="include\crypto\bn_conf.h.in">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </None>
+ <None Include="include\crypto\dso_conf.h.in">
+ <Filter>Header Files\include\openssl\crypto</Filter>
+ </None>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/NorthstarDedicatedTest/audio.cpp b/NorthstarDLL/audio.cpp
index 0b65670f..268175bf 100644
--- a/NorthstarDedicatedTest/audio.cpp
+++ b/NorthstarDLL/audio.cpp
@@ -1,13 +1,15 @@
#include "pch.h"
#include "audio.h"
#include "dedicated.h"
+#include "convar.h"
#include "rapidjson/error/en.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <random>
-#include "convar.h"
+
+AUTOHOOK_INIT()
extern "C"
{
@@ -194,7 +196,7 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
std::string pathString = file.path().string();
// Open the file.
- std::basic_ifstream<uint8_t> wavStream(pathString, std::ios::binary);
+ std::ifstream wavStream(pathString, std::ios::binary);
if (wavStream.fail())
{
@@ -219,7 +221,7 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
[pathString, fileSize, data]
{
std::shared_lock lock(g_CustomAudioManager.m_loadingMutex);
- std::basic_ifstream<uint8_t> wavStream(pathString, std::ios::binary);
+ std::ifstream wavStream(pathString, std::ios::binary);
// would be weird if this got hit, since it would've worked previously
if (wavStream.fail())
@@ -229,10 +231,8 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
}
// read from after the header first to preserve the empty header, then read the header last
- wavStream.seekg(sizeof(EMPTY_WAVE), std::ios::beg);
- wavStream.read(&data[sizeof(EMPTY_WAVE)], fileSize - sizeof(EMPTY_WAVE));
wavStream.seekg(0, std::ios::beg);
- wavStream.read(data, sizeof(EMPTY_WAVE));
+ wavStream.read(reinterpret_cast<char*>(data), fileSize);
wavStream.close();
spdlog::info("Finished async read of audio sample {}", pathString);
@@ -265,7 +265,7 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
{
- if (IsDedicated())
+ if (IsDedicatedServer())
return true; // silently fail
std::ifstream jsonStream(defPath);
@@ -308,13 +308,14 @@ MilesStopAll_Type MilesStopAll;
void CustomAudioManager::ClearAudioOverrides()
{
- if (IsDedicated())
+ if (IsDedicatedServer())
return;
if (m_loadedAudioOverrides.size() > 0 || m_loadedAudioOverridesRegex.size() > 0)
{
// stop all miles sounds beforehand
// miles_stop_all
+
MilesStopAll();
// this is cancer but it works
@@ -329,9 +330,6 @@ void CustomAudioManager::ClearAudioOverrides()
m_loadedAudioOverridesRegex.clear();
}
-typedef bool (*LoadSampleMetadata_Type)(void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType);
-LoadSampleMetadata_Type LoadSampleMetadata_Original;
-
template <typename Iter, typename RandomGenerator> Iter select_randomly(Iter start, Iter end, RandomGenerator& g)
{
std::uniform_int_distribution<> dis(0, std::distance(start, end) - 1);
@@ -368,6 +366,26 @@ bool ShouldPlayAudioEvent(const char* eventName, const std::shared_ptr<EventOver
return true; // good to go
}
+// forward declare
+bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
+ uintptr_t parentEvent, void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType);
+
+// DO NOT TOUCH THIS FUNCTION
+// The actual logic of it in a separate function (forcefully not inlined) to preserve the r12 register, which holds the event pointer.
+// clang-format off
+AUTOHOOK(LoadSampleMetadata, mileswin64.dll + 0xF110,
+bool, __fastcall, (void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType))
+// clang-format on
+{
+ uintptr_t parentEvent = (uintptr_t)Audio_GetParentEvent();
+
+ // Raw source, used for voice data only
+ if (audioType == 0)
+ return LoadSampleMetadata(sample, audioBuffer, audioBufferLength, audioType);
+
+ return LoadSampleMetadata_Internal(parentEvent, sample, audioBuffer, audioBufferLength, audioType);
+}
+
// DO NOT INLINE THIS FUNCTION
// See comment below.
bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
@@ -398,7 +416,7 @@ bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
if (!overrideData)
// not found either
- return LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, audioType);
+ return LoadSampleMetadata(sample, audioBuffer, audioBufferLength, audioType);
else
{
// cache found pattern to improve performance
@@ -412,7 +430,7 @@ bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
overrideData = iter->second;
if (!ShouldPlayAudioEvent(eventName, overrideData))
- return LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, audioType);
+ return LoadSampleMetadata(sample, audioBuffer, audioBufferLength, audioType);
void* data = 0;
unsigned int dataLength = 0;
@@ -454,7 +472,7 @@ bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
if (!data)
{
spdlog::warn("Could not fetch override sample data for event {}! Using original data instead.", eventName);
- return LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, audioType);
+ return LoadSampleMetadata(sample, audioBuffer, audioBufferLength, audioType);
}
audioBuffer = data;
@@ -465,51 +483,25 @@ bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(
*(unsigned int*)((uintptr_t)sample + 0xF0) = audioBufferLength;
// 64 - Auto-detect sample type
- bool res = LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, 64);
+ bool res = LoadSampleMetadata(sample, audioBuffer, audioBufferLength, 64);
if (!res)
spdlog::error("LoadSampleMetadata failed! The game will crash :(");
return res;
}
-// DO NOT TOUCH THIS FUNCTION
-// The actual logic of it in a separate function (forcefully not inlined) to preserve the r12 register, which holds the event pointer.
-bool __fastcall LoadSampleMetadata_Hook(void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType)
-{
- uintptr_t parentEvent = (uintptr_t)Audio_GetParentEvent();
-
- // Raw source, used for voice data only
- if (audioType == 0)
- return LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, audioType);
-
- return LoadSampleMetadata_Internal(parentEvent, sample, audioBuffer, audioBufferLength, audioType);
-}
-
-typedef bool (*MilesLog_Type)(int level, const char* string);
-MilesLog_Type MilesLog_Original;
-
-void __fastcall MilesLog_Hook(int level, const char* string)
+// clang-format off
+AUTOHOOK(MilesLog, client.dll + 0x57DAD0,
+void, __fastcall, (int level, const char* string))
+// clang-format on
{
spdlog::info("[MSS] {} - {}", level, string);
}
-void InitialiseMilesAudioHooks(HMODULE baseAddress)
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", AudioHooks, ConVar, (CModule module))
{
- Cvar_ns_print_played_sounds = new ConVar("ns_print_played_sounds", "0", FCVAR_NONE, "");
-
- if (IsDedicated())
- return;
-
- uintptr_t milesAudioBase = (uintptr_t)GetModuleHandleA("mileswin64.dll");
-
- if (!milesAudioBase)
- return spdlog::error("miles audio not found :terror:");
+ AUTOHOOK_DISPATCH()
- HookEnabler hook;
-
- ENABLER_CREATEHOOK(
- hook, (char*)milesAudioBase + 0xF110, &LoadSampleMetadata_Hook, reinterpret_cast<LPVOID*>(&LoadSampleMetadata_Original));
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x57DAD0, &MilesLog_Hook, reinterpret_cast<LPVOID*>(&MilesLog_Original));
-
- MilesStopAll = (MilesStopAll_Type)((char*)baseAddress + 0x580850);
-} \ No newline at end of file
+ Cvar_ns_print_played_sounds = new ConVar("ns_print_played_sounds", "0", FCVAR_NONE, "");
+ MilesStopAll = module.Offset(0x580850).As<MilesStopAll_Type>();
+}
diff --git a/NorthstarDedicatedTest/audio.h b/NorthstarDLL/audio.h
index 6ed3ce57..26cda205 100644
--- a/NorthstarDedicatedTest/audio.h
+++ b/NorthstarDLL/audio.h
@@ -5,8 +5,6 @@
#include <regex>
#include <shared_mutex>
-namespace fs = std::filesystem;
-
enum class AudioSelectionStrategy
{
INVALID = -1,
@@ -46,5 +44,3 @@ class CustomAudioManager
};
extern CustomAudioManager g_CustomAudioManager;
-
-void InitialiseMilesAudioHooks(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/audio_asm.asm b/NorthstarDLL/audio_asm.asm
index 4c527f9d..1b2d3f8d 100644
--- a/NorthstarDedicatedTest/audio_asm.asm
+++ b/NorthstarDLL/audio_asm.asm
@@ -5,4 +5,4 @@ Audio_GetParentEvent proc
mov rax, r12
ret
Audio_GetParentEvent endp
-end \ No newline at end of file
+end
diff --git a/NorthstarDLL/bansystem.cpp b/NorthstarDLL/bansystem.cpp
new file mode 100644
index 00000000..25c0e6bf
--- /dev/null
+++ b/NorthstarDLL/bansystem.cpp
@@ -0,0 +1,222 @@
+#pragma once
+#include "pch.h"
+#include "bansystem.h"
+#include "serverauthentication.h"
+#include "maxplayers.h"
+#include "concommand.h"
+#include "r2server.h"
+#include "r2engine.h"
+#include "nsprefix.h"
+
+#include <filesystem>
+
+const char* BANLIST_PATH_SUFFIX = "/banlist.txt";
+const char BANLIST_COMMENT_CHAR = '#';
+
+ServerBanSystem* g_pBanSystem;
+
+void ServerBanSystem::OpenBanlist()
+{
+ std::ifstream banlistStream(GetNorthstarPrefix() + "/banlist.txt");
+
+ if (!banlistStream.fail())
+ {
+ std::string line;
+ while (std::getline(banlistStream, line))
+ {
+ // ignore line if first char is # or line is empty
+ if (line == "" || line.front() == BANLIST_COMMENT_CHAR)
+ continue;
+
+ // remove tabs which shouldnt be there but maybe someone did the funny
+ line.erase(std::remove(line.begin(), line.end(), '\t'), line.end());
+ // remove spaces to allow for spaces before uids
+ line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
+
+ // check if line is empty to allow for newlines in the file
+ if (line == "")
+ continue;
+
+ // for inline comments like: 123123123 #banned for unfunny
+ std::string uid = line.substr(0, line.find(BANLIST_COMMENT_CHAR));
+
+ m_vBannedUids.push_back(strtoull(uid.c_str(), nullptr, 10));
+ }
+
+ banlistStream.close();
+ }
+
+ // open write stream for banlist // dont do this to allow for all time access
+ // m_sBanlistStream.open(GetNorthstarPrefix() + "/banlist.txt", std::ofstream::out | std::ofstream::binary | std::ofstream::app);
+}
+
+void ServerBanSystem::ReloadBanlist()
+{
+ std::ifstream fsBanlist(GetNorthstarPrefix() + "/banlist.txt");
+
+ if (!fsBanlist.fail())
+ {
+ std::string line;
+ // since we wanna use this as the reload func we need to clear the list
+ m_vBannedUids.clear();
+ while (std::getline(fsBanlist, line))
+ m_vBannedUids.push_back(strtoull(line.c_str(), nullptr, 10));
+
+ fsBanlist.close();
+ }
+}
+
+void ServerBanSystem::ClearBanlist()
+{
+ m_vBannedUids.clear();
+
+ // reopen the file, don't provide std::ofstream::app so it clears on open
+ m_sBanlistStream.close();
+ m_sBanlistStream.open(GetNorthstarPrefix() + "/banlist.txt", std::ofstream::out | std::ofstream::binary);
+ m_sBanlistStream.close();
+}
+
+void ServerBanSystem::BanUID(uint64_t uid)
+{
+ // checking if last char is \n to make sure uids arent getting fucked
+ std::ifstream fsBanlist(GetNorthstarPrefix() + "/banlist.txt");
+ std::string content((std::istreambuf_iterator<char>(fsBanlist)), (std::istreambuf_iterator<char>()));
+ fsBanlist.close();
+
+ m_sBanlistStream.open(GetNorthstarPrefix() + "/banlist.txt", std::ofstream::out | std::ofstream::binary | std::ofstream::app);
+ if (content.back() != '\n')
+ m_sBanlistStream << std::endl;
+
+ m_vBannedUids.push_back(uid);
+ m_sBanlistStream << std::to_string(uid) << std::endl;
+ m_sBanlistStream.close();
+ spdlog::info("{} was banned", uid);
+}
+
+void ServerBanSystem::UnbanUID(uint64_t uid)
+{
+ auto findResult = std::find(m_vBannedUids.begin(), m_vBannedUids.end(), uid);
+ if (findResult == m_vBannedUids.end())
+ return;
+
+ m_vBannedUids.erase(findResult);
+
+ std::vector<std::string> banlistText;
+ std::ifstream fs_readBanlist(GetNorthstarPrefix() + "/banlist.txt");
+
+ if (!fs_readBanlist.fail())
+ {
+ std::string line;
+ while (std::getline(fs_readBanlist, line))
+ {
+ // support for comments and newlines added in https://github.com/R2Northstar/NorthstarLauncher/pull/227
+
+ std::string modLine = line; // copy the line into a free var that we can fuck with, line will be the original
+
+ // remove tabs which shouldnt be there but maybe someone did the funny
+ modLine.erase(std::remove(modLine.begin(), modLine.end(), '\t'), modLine.end());
+ // remove spaces to allow for spaces before uids
+ modLine.erase(std::remove(modLine.begin(), modLine.end(), ' '), modLine.end());
+
+ // ignore line if first char is # or empty line, just add it
+ if (line.front() == BANLIST_COMMENT_CHAR || modLine == "")
+ {
+ banlistText.push_back(line);
+ continue;
+ }
+
+ // for inline comments like: 123123123 #banned for unfunny
+ std::string lineUid = line.substr(0, line.find(BANLIST_COMMENT_CHAR));
+ // have to erase spaces or else inline comments will fuck up the uid finding
+ lineUid.erase(std::remove(lineUid.begin(), lineUid.end(), '\t'), lineUid.end());
+ lineUid.erase(std::remove(lineUid.begin(), lineUid.end(), ' '), lineUid.end());
+
+ // if the uid in the line is the uid we wanna unban
+ if (std::to_string(uid) == lineUid)
+ {
+ // comment the uid out
+ line.insert(0, "# ");
+
+ // add a comment with unban date
+ // not necessary but i feel like this makes it better
+ std::time_t t = std::time(0);
+ std::tm* now = std::localtime(&t);
+
+ std::ostringstream unbanComment;
+
+ //{y}/{m}/{d} {h}:{m}
+ unbanComment << " # unban date: ";
+ unbanComment << now->tm_year + 1900 << "-"; // this lib is so fucking awful
+ unbanComment << std::setw(2) << std::setfill('0') << now->tm_mon + 1 << "-";
+ unbanComment << std::setw(2) << std::setfill('0') << now->tm_mday << " ";
+ unbanComment << std::setw(2) << std::setfill('0') << now->tm_hour << ":";
+ unbanComment << std::setw(2) << std::setfill('0') << now->tm_min;
+
+ line.append(unbanComment.str());
+ }
+
+ banlistText.push_back(line);
+ }
+
+ fs_readBanlist.close();
+ }
+
+ // open write stream for banlist // without append so we clear the file
+ if (m_sBanlistStream.is_open())
+ m_sBanlistStream.close();
+ m_sBanlistStream.open(GetNorthstarPrefix() + "/banlist.txt", std::ofstream::out | std::ofstream::binary);
+
+ for (std::string updatedLine : banlistText)
+ m_sBanlistStream << updatedLine << std::endl;
+
+ m_sBanlistStream.close();
+ spdlog::info("{} was unbanned", uid);
+}
+
+bool ServerBanSystem::IsUIDAllowed(uint64_t uid)
+{
+ ReloadBanlist(); // Reload to have up to date list on join
+ return std::find(m_vBannedUids.begin(), m_vBannedUids.end(), uid) == m_vBannedUids.end();
+}
+
+void ConCommand_ban(const CCommand& args)
+{
+ if (args.ArgC() < 2)
+ return;
+
+ for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ {
+ R2::CBaseClient* player = &R2::g_pClientArray[i];
+
+ if (!strcmp(player->m_Name, args.Arg(1)) || !strcmp(player->m_UID, args.Arg(1)))
+ {
+ g_pBanSystem->BanUID(strtoull(player->m_UID, nullptr, 10));
+ R2::CBaseClient__Disconnect(player, 1, "Banned from server");
+ break;
+ }
+ }
+}
+
+void ConCommand_unban(const CCommand& args)
+{
+ if (args.ArgC() < 2)
+ return;
+
+ // assumedly the player being unbanned here wasn't already connected, so don't need to iterate over players or anything
+ g_pBanSystem->UnbanUID(strtoull(args.Arg(1), nullptr, 10));
+}
+
+void ConCommand_clearbanlist(const CCommand& args)
+{
+ g_pBanSystem->ClearBanlist();
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", BanSystem, ConCommand, (CModule module))
+{
+ g_pBanSystem = new ServerBanSystem;
+ g_pBanSystem->OpenBanlist();
+
+ RegisterConCommand("ban", ConCommand_ban, "bans a given player by uid or name", FCVAR_GAMEDLL);
+ RegisterConCommand("unban", ConCommand_unban, "unbans a given player by uid", FCVAR_GAMEDLL);
+ RegisterConCommand("clearbanlist", ConCommand_clearbanlist, "clears all uids on the banlist", FCVAR_GAMEDLL);
+}
diff --git a/NorthstarDedicatedTest/bansystem.h b/NorthstarDLL/bansystem.h
index 0f618843..6f180126 100644
--- a/NorthstarDedicatedTest/bansystem.h
+++ b/NorthstarDLL/bansystem.h
@@ -9,12 +9,11 @@ class ServerBanSystem
public:
void OpenBanlist();
+ void ReloadBanlist();
void ClearBanlist();
void BanUID(uint64_t uid);
void UnbanUID(uint64_t uid);
bool IsUIDAllowed(uint64_t uid);
};
-extern ServerBanSystem* g_ServerBanSystem;
-
-void InitialiseBanSystem(HMODULE baseAddress); \ No newline at end of file
+extern ServerBanSystem* g_pBanSystem;
diff --git a/NorthstarDedicatedTest/bitbuf.h b/NorthstarDLL/bitbuf.h
index 520e5d0a..8e8e216f 100644
--- a/NorthstarDedicatedTest/bitbuf.h
+++ b/NorthstarDLL/bitbuf.h
@@ -1145,4 +1145,4 @@ class BFWrite : public BitBufferBase
bool m_Flushed = false; // :flushed:
};
-#undef INLINE \ No newline at end of file
+#undef INLINE
diff --git a/NorthstarDedicatedTest/bits.cpp b/NorthstarDLL/bits.cpp
index 014899f2..014899f2 100644
--- a/NorthstarDedicatedTest/bits.cpp
+++ b/NorthstarDLL/bits.cpp
diff --git a/NorthstarDedicatedTest/bits.h b/NorthstarDLL/bits.h
index 0532a9bd..0532a9bd 100644
--- a/NorthstarDedicatedTest/bits.h
+++ b/NorthstarDLL/bits.h
diff --git a/NorthstarDedicatedTest/buildainfile.cpp b/NorthstarDLL/buildainfile.cpp
index 010f0975..8190adba 100644
--- a/NorthstarDedicatedTest/buildainfile.cpp
+++ b/NorthstarDLL/buildainfile.cpp
@@ -1,19 +1,19 @@
#include "pch.h"
-#include "buildainfile.h"
#include "convar.h"
-#include "hookutils.h"
+#include "hoststate.h"
+#include "r2engine.h"
+
#include <fstream>
#include <filesystem>
-#include "NSMem.h"
-namespace fs = std::filesystem;
+AUTOHOOK_INIT()
const int AINET_VERSION_NUMBER = 57;
const int AINET_SCRIPT_VERSION_NUMBER = 21;
-const int MAP_VERSION_TEMP = 30;
const int PLACEHOLDER_CRC = 0;
const int MAX_HULLS = 5;
+#pragma pack(push, 1)
struct CAI_NodeLink
{
short srcId;
@@ -24,6 +24,7 @@ struct CAI_NodeLink
char unk2[5];
int64_t flags;
};
+#pragma pack(pop)
#pragma pack(push, 1)
struct CAI_NodeLinkDisk
@@ -33,7 +34,9 @@ struct CAI_NodeLinkDisk
char unk0;
bool hulls[MAX_HULLS];
};
+#pragma pack(pop)
+#pragma pack(push, 1)
struct CAI_Node
{
int index; // not present on disk
@@ -62,6 +65,7 @@ struct CAI_Node
char unk9[8]; // padding until next bit
char unk10[8]; // should match up to unk6 on disk
};
+#pragma pack(pop)
// the way CAI_Nodes are represented in on-disk ain files
#pragma pack(push, 1)
@@ -81,7 +85,9 @@ struct CAI_NodeDisk
short unk5;
char unk6[8];
}; // total size of 68 bytes
+#pragma pack(pop)
+#pragma pack(push, 1)
struct UnkNodeStruct0
{
int index;
@@ -106,10 +112,12 @@ struct UnkNodeStruct0
char pad4[132];
char unk5;
};
+#pragma pack(pop)
int* pUnkStruct0Count;
UnkNodeStruct0*** pppUnkNodeStruct0s;
+#pragma pack(push, 1)
struct UnkLinkStruct1
{
short unk0;
@@ -119,10 +127,12 @@ struct UnkLinkStruct1
char unk4;
char unk5;
};
+#pragma pack(pop)
int* pUnkLinkStruct1Count;
UnkLinkStruct1*** pppUnkStruct1s;
+#pragma pack(push, 1)
struct CAI_ScriptNode
{
float x;
@@ -130,7 +140,9 @@ struct CAI_ScriptNode
float z;
uint64_t scriptdata;
};
+#pragma pack(pop)
+#pragma pack(push, 1)
struct CAI_Network
{
// +0
@@ -160,16 +172,16 @@ struct CAI_Network
// +84176
CAI_Node** nodes;
};
+#pragma pack(pop)
char** pUnkServerMapversionGlobal;
-char* pMapName;
ConVar* Cvar_ns_ai_dumpAINfileFromLoad;
void DumpAINInfo(CAI_Network* aiNetwork)
{
- fs::path writePath("r2/maps/graphs");
- writePath /= pMapName;
+ fs::path writePath(fmt::format("{}/maps/graphs", R2::g_pModName));
+ writePath /= R2::g_pHostState->m_levelName;
writePath += ".ain";
// dump from memory
@@ -349,20 +361,20 @@ void DumpAINInfo(CAI_Network* aiNetwork)
writeStream.close();
}
-typedef void (*CAI_NetworkBuilder__BuildType)(void* builder, CAI_Network* aiNetwork, void* unknown);
-CAI_NetworkBuilder__BuildType CAI_NetworkBuilder__Build;
-
-void CAI_NetworkBuilder__BuildHook(void* builder, CAI_Network* aiNetwork, void* unknown)
+// clang-format off
+AUTOHOOK(CAI_NetworkBuilder__Build, server.dll + 0x385E20,
+void, __fastcall, (void* builder, CAI_Network* aiNetwork, void* unknown))
+// clang-format on
{
CAI_NetworkBuilder__Build(builder, aiNetwork, unknown);
DumpAINInfo(aiNetwork);
}
-typedef void (*LoadAINFileType)(void* aimanager, void* buf, const char* filename);
-LoadAINFileType LoadAINFile;
-
-void LoadAINFileHook(void* aimanager, void* buf, const char* filename)
+// clang-format off
+AUTOHOOK(LoadAINFile, server.dll + 0x3933A0,
+void, __fastcall, (void* aimanager, void* buf, const char* filename))
+// clang-format on
{
LoadAINFile(aimanager, buf, filename);
@@ -373,28 +385,16 @@ void LoadAINFileHook(void* aimanager, void* buf, const char* filename)
}
}
-void InitialiseBuildAINFileHooks(HMODULE baseAddress)
+ON_DLL_LOAD("server.dll", BuildAINFile, (CModule module))
{
+ AUTOHOOK_DISPATCH()
+
Cvar_ns_ai_dumpAINfileFromLoad = new ConVar(
"ns_ai_dumpAINfileFromLoad", "0", FCVAR_NONE, "For debugging: whether we should dump ain data for ains loaded from disk");
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x385E20, &CAI_NetworkBuilder__BuildHook, reinterpret_cast<LPVOID*>(&CAI_NetworkBuilder__Build));
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x3933A0, &LoadAINFileHook, reinterpret_cast<LPVOID*>(&LoadAINFile));
-
- pUnkStruct0Count = (int*)((char*)baseAddress + 0x1063BF8);
- pppUnkNodeStruct0s = (UnkNodeStruct0***)((char*)baseAddress + 0x1063BE0);
-
- pUnkLinkStruct1Count = (int*)((char*)baseAddress + 0x1063AA8);
- pppUnkStruct1s = (UnkLinkStruct1***)((char*)baseAddress + 0x1063A90);
- pUnkServerMapversionGlobal = (char**)((char*)baseAddress + 0xBFBE08);
- pMapName = (char*)baseAddress + 0x1053370;
-
- uintptr_t base = (uintptr_t)baseAddress;
-
- // remove a check that prevents a logging function in link generation from working
- // due to the sheer amount of logging this is a massive perf hit to generation, but spewlog_enable 0 exists so whatever
- NSMem::NOP(base + 0x3889B6, 6);
- NSMem::NOP(base + 0x3889BF, 6);
-} \ No newline at end of file
+ pUnkStruct0Count = module.Offset(0x1063BF8).As<int*>();
+ pppUnkNodeStruct0s = module.Offset(0x1063BE0).As<UnkNodeStruct0***>();
+ pUnkLinkStruct1Count = module.Offset(0x1063AA8).As<int*>();
+ pppUnkStruct1s = module.Offset(0x1063A90).As<UnkLinkStruct1***>();
+ pUnkServerMapversionGlobal = module.Offset(0xBFBE08).As<char**>();
+}
diff --git a/NorthstarDedicatedTest/chatcommand.cpp b/NorthstarDLL/chatcommand.cpp
index 2aa51737..37c438f3 100644
--- a/NorthstarDedicatedTest/chatcommand.cpp
+++ b/NorthstarDLL/chatcommand.cpp
@@ -1,13 +1,11 @@
#include "pch.h"
#include "convar.h"
#include "concommand.h"
-#include "chatcommand.h"
#include "localchatwriter.h"
// note: isIngameChat is an int64 because the whole register the arg is stored in needs to be 0'd out to work
// if isIngameChat is false, we use network chat instead
-typedef void(__fastcall* ClientSayTextType)(void* a1, const char* message, __int64 isIngameChat, bool isTeamChat);
-ClientSayTextType ClientSayText;
+void(__fastcall* ClientSayText)(void* a1, const char* message, uint64_t isIngameChat, bool isTeamChat);
void ConCommand_say(const CCommand& args)
{
@@ -29,9 +27,9 @@ void ConCommand_log(const CCommand& args)
}
}
-void InitialiseChatCommands(HMODULE baseAddress)
+ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", ClientChatCommand, ConCommand, (CModule module))
{
- ClientSayText = (ClientSayTextType)((char*)baseAddress + 0x54780);
+ ClientSayText = module.Offset(0x54780).As<void(__fastcall*)(void* a1, const char* message, uint64_t isIngameChat, bool isTeamChat)>();
RegisterConCommand("say", ConCommand_say, "Enters a message in public chat", FCVAR_CLIENTDLL);
RegisterConCommand("say_team", ConCommand_say_team, "Enters a message in team chat", FCVAR_CLIENTDLL);
RegisterConCommand("log", ConCommand_log, "Log a message to the local chat window", FCVAR_CLIENTDLL);
diff --git a/NorthstarDedicatedTest/clientauthhooks.cpp b/NorthstarDLL/clientauthhooks.cpp
index 5c1c4510..ccd7432e 100644
--- a/NorthstarDedicatedTest/clientauthhooks.cpp
+++ b/NorthstarDLL/clientauthhooks.cpp
@@ -1,12 +1,9 @@
#include "pch.h"
-#include "clientauthhooks.h"
-#include "hookutils.h"
-#include "gameutils.h"
#include "masterserver.h"
#include "convar.h"
+#include "r2client.h"
-typedef void (*AuthWithStryderType)(void* a1);
-AuthWithStryderType AuthWithStryder;
+AUTOHOOK_INIT()
ConVar* Cvar_ns_has_agreed_to_send_token;
@@ -15,33 +12,35 @@ const int NOT_DECIDED_TO_SEND_TOKEN = 0;
const int AGREED_TO_SEND_TOKEN = 1;
const int DISAGREED_TO_SEND_TOKEN = 2;
-void AuthWithStryderHook(void* a1)
+// clang-format off
+AUTOHOOK(AuthWithStryder, engine.dll + 0x1843A0,
+void, __fastcall, (void* a1))
+// clang-format on
{
// game will call this forever, until it gets a valid auth key
// so, we need to manually invalidate our key until we're authed with northstar, then we'll allow game to auth with stryder
- if (!g_MasterServerManager->m_bOriginAuthWithMasterServerDone && Cvar_ns_has_agreed_to_send_token->GetInt() != DISAGREED_TO_SEND_TOKEN)
+ if (!g_pMasterServerManager->m_bOriginAuthWithMasterServerDone && Cvar_ns_has_agreed_to_send_token->GetInt() != DISAGREED_TO_SEND_TOKEN)
{
// if player has agreed to send token and we aren't already authing, try to auth
if (Cvar_ns_has_agreed_to_send_token->GetInt() == AGREED_TO_SEND_TOKEN &&
- !g_MasterServerManager->m_bOriginAuthWithMasterServerInProgress)
- g_MasterServerManager->AuthenticateOriginWithMasterServer(g_LocalPlayerUserID, g_LocalPlayerOriginToken);
+ !g_pMasterServerManager->m_bOriginAuthWithMasterServerInProgress)
+ g_pMasterServerManager->AuthenticateOriginWithMasterServer(R2::g_pLocalPlayerUserID, R2::g_pLocalPlayerOriginToken);
// invalidate key so auth will fail
- *g_LocalPlayerOriginToken = 0;
+ *R2::g_pLocalPlayerOriginToken = 0;
}
AuthWithStryder(a1);
}
-void InitialiseClientAuthHooks(HMODULE baseAddress)
+ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", ClientAuthHooks, ConVar, (CModule module))
{
+ AUTOHOOK_DISPATCH()
+
// this cvar will save to cfg once initially agreed with
Cvar_ns_has_agreed_to_send_token = new ConVar(
"ns_has_agreed_to_send_token",
"0",
FCVAR_ARCHIVE_PLAYERPROFILE,
"whether the user has agreed to send their origin token to the northstar masterserver");
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1843A0, &AuthWithStryderHook, reinterpret_cast<LPVOID*>(&AuthWithStryder));
-} \ No newline at end of file
+}
diff --git a/NorthstarDLL/clientchathooks.cpp b/NorthstarDLL/clientchathooks.cpp
new file mode 100644
index 00000000..a7a42689
--- /dev/null
+++ b/NorthstarDLL/clientchathooks.cpp
@@ -0,0 +1,83 @@
+#include "pch.h"
+#include "squirrel.h"
+#include "serverchathooks.h"
+#include "localchatwriter.h"
+
+#include <rapidjson/document.h>
+
+AUTOHOOK_INIT()
+
+// clang-format off
+AUTOHOOK(CHudChat__AddGameLine, client.dll + 0x22E580,
+void, __fastcall, (void* self, const char* message, int inboxId, bool isTeam, bool isDead))
+// clang-format on
+{
+ // This hook is called for each HUD, but we only want our logic to run once.
+ if (self != *CHudChat::allHuds)
+ return;
+
+ if (g_pSquirrel<ScriptContext::CLIENT>->setupfunc("CHudChat_ProcessMessageStartThread") != SQRESULT_ERROR)
+ {
+ int senderId = inboxId & CUSTOM_MESSAGE_INDEX_MASK;
+ bool isAnonymous = senderId == 0;
+ bool isCustom = isAnonymous || (inboxId & CUSTOM_MESSAGE_INDEX_BIT);
+
+ // Type is set to 0 for non-custom messages, custom messages have a type encoded as the first byte
+ int type = 0;
+ const char* payload = message;
+ if (isCustom)
+ {
+ type = message[0];
+ payload = message + 1;
+ }
+
+ g_pSquirrel<ScriptContext::CLIENT>->pushinteger(g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm, (int)senderId - 1);
+ g_pSquirrel<ScriptContext::CLIENT>->pushstring(g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm, payload);
+ g_pSquirrel<ScriptContext::CLIENT>->pushbool(g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm, isTeam);
+ g_pSquirrel<ScriptContext::CLIENT>->pushbool(g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm, isDead);
+ g_pSquirrel<ScriptContext::CLIENT>->pushinteger(g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm, type);
+ g_pSquirrel<ScriptContext::CLIENT>->call(g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm, 5);
+ }
+ else
+ for (CHudChat* hud = *CHudChat::allHuds; hud != NULL; hud = hud->next)
+ CHudChat__AddGameLine(hud, message, inboxId, isTeam, isDead);
+}
+
+// void NSChatWrite( int context, string str )
+SQRESULT SQ_ChatWrite(HSquirrelVM* sqvm)
+{
+ int context = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
+ const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
+
+ LocalChatWriter((LocalChatWriter::Context)context).Write(str);
+ return SQRESULT_NULL;
+}
+
+// void NSChatWriteRaw( int context, string str )
+SQRESULT SQ_ChatWriteRaw(HSquirrelVM* sqvm)
+{
+ int context = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
+ const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
+
+ LocalChatWriter((LocalChatWriter::Context)context).InsertText(str);
+ return SQRESULT_NULL;
+}
+
+// void NSChatWriteLine( int context, string str )
+SQRESULT SQ_ChatWriteLine(HSquirrelVM* sqvm)
+{
+ int context = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
+ const char* str = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
+
+ LocalChatWriter((LocalChatWriter::Context)context).WriteLine(str);
+ return SQRESULT_NULL;
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientChatHooks, ClientSquirrel, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration("void", "NSChatWrite", "int context, string text", "", SQ_ChatWrite);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration("void", "NSChatWriteRaw", "int context, string text", "", SQ_ChatWriteRaw);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration("void", "NSChatWriteLine", "int context, string text", "", SQ_ChatWriteLine);
+}
diff --git a/NorthstarDLL/clientruihooks.cpp b/NorthstarDLL/clientruihooks.cpp
new file mode 100644
index 00000000..3cb08368
--- /dev/null
+++ b/NorthstarDLL/clientruihooks.cpp
@@ -0,0 +1,24 @@
+#include "pch.h"
+#include "convar.h"
+
+AUTOHOOK_INIT()
+
+ConVar* Cvar_rui_drawEnable;
+
+// clang-format off
+AUTOHOOK(DrawRUIFunc, engine.dll + 0xFC500,
+bool, __fastcall, (void* a1, float* a2))
+// clang-format on
+{
+ if (!Cvar_rui_drawEnable->GetBool())
+ return 0;
+
+ return DrawRUIFunc(a1, a2);
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", RUI, ConVar, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ Cvar_rui_drawEnable = new ConVar("rui_drawEnable", "1", FCVAR_CLIENTDLL, "Controls whether RUI should be drawn");
+}
diff --git a/NorthstarDLL/clientvideooverrides.cpp b/NorthstarDLL/clientvideooverrides.cpp
new file mode 100644
index 00000000..b9954bf2
--- /dev/null
+++ b/NorthstarDLL/clientvideooverrides.cpp
@@ -0,0 +1,42 @@
+#include "pch.h"
+#include "modmanager.h"
+
+AUTOHOOK_INIT()
+
+// clang-format off
+AUTOHOOK_PROCADDRESS(BinkOpen, bink2w64.dll, BinkOpen,
+void*, __fastcall, (const char* path, uint32_t flags))
+// clang-format on
+{
+ std::string filename(fs::path(path).filename().string());
+ spdlog::info("BinkOpen {}", filename);
+
+ // figure out which mod is handling the bink
+ Mod* fileOwner = nullptr;
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.m_bEnabled)
+ continue;
+
+ if (std::find(mod.BinkVideos.begin(), mod.BinkVideos.end(), filename) != mod.BinkVideos.end())
+ fileOwner = &mod;
+ }
+
+ if (fileOwner)
+ {
+ // create new path
+ fs::path binkPath(fileOwner->m_ModDirectory / "media" / filename);
+ return BinkOpen(binkPath.string().c_str(), flags);
+ }
+ else
+ return BinkOpen(path, flags);
+}
+
+ON_DLL_LOAD_CLIENT("client.dll", BinkVideo, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ // remove engine check for whether the bik we're trying to load exists in r2/media, as this will fail for biks in mods
+ // note: the check in engine is actually unnecessary, so it's just useless in practice and we lose nothing by removing it
+ module.Offset(0x459AD).NOP(6);
+}
diff --git a/NorthstarDedicatedTest/color.h b/NorthstarDLL/color.h
index e2c1ebba..e2c1ebba 100644
--- a/NorthstarDedicatedTest/color.h
+++ b/NorthstarDLL/color.h
diff --git a/NorthstarDedicatedTest/concommand.cpp b/NorthstarDLL/concommand.cpp
index 1bdda91b..6d77e137 100644
--- a/NorthstarDedicatedTest/concommand.cpp
+++ b/NorthstarDLL/concommand.cpp
@@ -1,27 +1,8 @@
#include "pch.h"
#include "concommand.h"
-#include "gameutils.h"
#include "misccommands.h"
-#include <iostream>
-
-typedef void (*ConCommandConstructorType)(
- ConCommand* newCommand, const char* name, void (*callback)(const CCommand&), const char* helpString, int flags, void* parent);
-ConCommandConstructorType conCommandConstructor;
-
-void RegisterConCommand(const char* name, void (*callback)(const CCommand&), const char* helpString, int flags)
-{
- spdlog::info("Registering ConCommand {}", name);
-
- // no need to free this ever really, it should exist as long as game does
- ConCommand* newCommand = new ConCommand;
- conCommandConstructor(newCommand, name, callback, helpString, flags, nullptr);
-}
-void InitialiseConCommands(HMODULE baseAddress)
-{
- conCommandConstructor = (ConCommandConstructorType)((char*)baseAddress + 0x415F60);
- AddMiscConCommands();
-}
+#include <iostream>
//-----------------------------------------------------------------------------
// Purpose: Returns true if this is a command
@@ -57,7 +38,7 @@ bool ConCommandBase::IsRegistered(void) const
//-----------------------------------------------------------------------------
bool ConCommandBase::IsFlagSet(int nFlags) const
{
- return false; // !TODO: Returning false on every query? (original implementation in Northstar before ConCommandBase refactor)
+ return m_nFlags & nFlags;
}
//-----------------------------------------------------------------------------
@@ -138,3 +119,33 @@ char* ConCommandBase::CopyString(const char* szFrom) const
}
return szTo;
}
+
+typedef void (*ConCommandConstructorType)(
+ ConCommand* newCommand, const char* name, FnCommandCallback_t callback, const char* helpString, int flags, void* parent);
+ConCommandConstructorType ConCommandConstructor;
+
+void RegisterConCommand(const char* name, FnCommandCallback_t callback, const char* helpString, int flags)
+{
+ spdlog::info("Registering ConCommand {}", name);
+
+ // no need to free this ever really, it should exist as long as game does
+ ConCommand* newCommand = new ConCommand;
+ ConCommandConstructor(newCommand, name, callback, helpString, flags, nullptr);
+}
+
+void RegisterConCommand(
+ const char* name, FnCommandCallback_t callback, const char* helpString, int flags, FnCommandCompletionCallback completionCallback)
+{
+ spdlog::info("Registering ConCommand {}", name);
+
+ // no need to free this ever really, it should exist as long as game does
+ ConCommand* newCommand = new ConCommand;
+ ConCommandConstructor(newCommand, name, callback, helpString, flags, nullptr);
+ newCommand->m_pCompletionCallback = completionCallback;
+}
+
+ON_DLL_LOAD("engine.dll", ConCommand, (CModule module))
+{
+ ConCommandConstructor = module.Offset(0x415F60).As<ConCommandConstructorType>();
+ AddMiscConCommands();
+}
diff --git a/NorthstarDedicatedTest/concommand.h b/NorthstarDLL/concommand.h
index ea35ec1f..89363bc7 100644
--- a/NorthstarDedicatedTest/concommand.h
+++ b/NorthstarDLL/concommand.h
@@ -72,6 +72,20 @@ inline const char* CCommand::operator[](int nIndex) const
return Arg(nIndex);
}
+//-----------------------------------------------------------------------------
+// Called when a ConCommand needs to execute
+//-----------------------------------------------------------------------------
+typedef void (*FnCommandCallback_t)(const CCommand& command);
+
+#define COMMAND_COMPLETION_MAXITEMS 64
+#define COMMAND_COMPLETION_ITEM_LENGTH 128
+
+//-----------------------------------------------------------------------------
+// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
+//-----------------------------------------------------------------------------
+typedef int (*__fastcall FnCommandCompletionCallback)(
+ const char* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
+
// From r5reloaded
class ConCommandBase
{
@@ -113,8 +127,8 @@ class ConCommand : public ConCommandBase
void Init(void);
bool IsCommand(void) const;
- void* m_pCommandCallback {}; // 0x0040 <- starts from 0x40 since we inherit ConCommandBase.
- void* m_pCompletionCallback {}; // 0x0048 <- defaults to sub_180417410 ('xor eax, eax').
+ FnCommandCallback_t m_pCommandCallback {}; // 0x0040 <- starts from 0x40 since we inherit ConCommandBase.
+ FnCommandCompletionCallback m_pCompletionCallback {}; // 0x0048 <- defaults to sub_180417410 ('xor eax, eax').
int m_nCallbackFlags {}; // 0x0050
char pad_0054[4]; // 0x0054
int unk0; // 0x0058
@@ -122,6 +136,5 @@ class ConCommand : public ConCommandBase
}; // Size: 0x0060
void RegisterConCommand(const char* name, void (*callback)(const CCommand&), const char* helpString, int flags);
-void InitialiseConCommands(HMODULE baseAddress);
-
-#define MAKE_CONCMD(name, helpStr, flags, fn) RegisterConCommand(name, fn, helpStr, flags); \ No newline at end of file
+void RegisterConCommand(
+ const char* name, void (*callback)(const CCommand&), const char* helpString, int flags, FnCommandCompletionCallback completionCallback);
diff --git a/NorthstarDedicatedTest/convar.cpp b/NorthstarDLL/convar.cpp
index 346e7b69..c8f63922 100644
--- a/NorthstarDedicatedTest/convar.cpp
+++ b/NorthstarDLL/convar.cpp
@@ -2,10 +2,10 @@
#include "bits.h"
#include "cvar.h"
#include "convar.h"
-#include "hookutils.h"
-#include "gameutils.h"
#include "sourceinterface.h"
+#include <float.h>
+
typedef void (*ConVarRegisterType)(
ConVar* pConVar,
const char* pszName,
@@ -25,25 +25,19 @@ ConVarMallocType conVarMalloc;
void* g_pConVar_Vtable = nullptr;
void* g_pIConVar_Vtable = nullptr;
-typedef bool (*CvarIsFlagSetType)(ConVar* self, int flags);
-CvarIsFlagSetType CvarIsFlagSet;
-
//-----------------------------------------------------------------------------
// Purpose: ConVar interface initialization
//-----------------------------------------------------------------------------
-void InitialiseConVars(HMODULE baseAddress)
+ON_DLL_LOAD("engine.dll", ConVar, (CModule module))
{
- conVarMalloc = (ConVarMallocType)((char*)baseAddress + 0x415C20);
- conVarRegister = (ConVarRegisterType)((char*)baseAddress + 0x417230);
+ conVarMalloc = module.Offset(0x415C20).As<ConVarMallocType>();
+ conVarRegister = module.Offset(0x417230).As<ConVarRegisterType>();
- g_pConVar_Vtable = (char*)baseAddress + 0x67FD28;
- g_pIConVar_Vtable = (char*)baseAddress + 0x67FDC8;
+ g_pConVar_Vtable = module.Offset(0x67FD28);
+ g_pIConVar_Vtable = module.Offset(0x67FDC8);
- g_pCVarInterface = new SourceInterface<CCvar>("vstdlib.dll", "VEngineCvar007");
- g_pCVar = *g_pCVarInterface;
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x417FA0, &ConVar::IsFlagSet, reinterpret_cast<LPVOID*>(&CvarIsFlagSet));
+ R2::g_pCVarInterface = new SourceInterface<CCvar>("vstdlib.dll", "VEngineCvar007");
+ R2::g_pCVar = *R2::g_pCVarInterface;
}
//-----------------------------------------------------------------------------
@@ -72,7 +66,7 @@ ConVar::ConVar(
float fMin,
bool bMax,
float fMax,
- void* pCallback)
+ FnChangeCallback_t pCallback)
{
spdlog::info("Registering Convar {}", pszName);
@@ -474,16 +468,12 @@ bool ConVar::IsCommand(void) const
//-----------------------------------------------------------------------------
// Purpose: Test each ConVar query before setting the value.
-// Input : *pConVar - nFlags
+// Input : nFlags
// Output : False if change is permitted, true if not.
//-----------------------------------------------------------------------------
-bool ConVar::IsFlagSet(ConVar* pConVar, int nFlags)
+bool ConVar::IsFlagSet(int nFlags) const
{
- // unrestrict FCVAR_DEVELOPMENTONLY and FCVAR_HIDDEN
- if (pConVar && (nFlags == FCVAR_DEVELOPMENTONLY || nFlags == FCVAR_HIDDEN))
- return false;
-
- return CvarIsFlagSet(pConVar, nFlags);
+ return m_ConCommandBase.m_nFlags & nFlags;
}
//-----------------------------------------------------------------------------
diff --git a/NorthstarDedicatedTest/convar.h b/NorthstarDLL/convar.h
index b1424fb7..176d0d72 100644
--- a/NorthstarDedicatedTest/convar.h
+++ b/NorthstarDLL/convar.h
@@ -58,15 +58,58 @@
// ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd.
#define FCVAR_SERVER_CANNOT_QUERY \
(1 << 29) // If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
+
+// !!!NOTE!!! : this is likely incorrect, there are multiple concommands that the vanilla game registers with this flag that 100% should not
+// be remotely executable i.e. multiple commands that only exist on client (screenshot, joystick_initialize) we now use
+// FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS in all places this flag was previously used
#define FCVAR_CLIENTCMD_CAN_EXECUTE \
(1 << 30) // IVEngineClient::ClientCmd is allowed to execute this command.
// Note: IVEngineClient::ClientCmd_Unrestricted can run any client command.
#define FCVAR_ACCESSIBLE_FROM_THREADS (1 << 25) // used as a debugging tool necessary to check material system thread convars
+
+// TODO: could be cool to repurpose these for northstar use somehow?
// #define FCVAR_AVAILABLE (1<<26)
// #define FCVAR_AVAILABLE (1<<27)
// #define FCVAR_AVAILABLE (1<<31)
+// flag => string stuff
+const std::multimap<int, const char*> g_PrintCommandFlags = {
+ {FCVAR_UNREGISTERED, "UNREGISTERED"},
+ {FCVAR_DEVELOPMENTONLY, "DEVELOPMENTONLY"},
+ {FCVAR_GAMEDLL, "GAMEDLL"},
+ {FCVAR_CLIENTDLL, "CLIENTDLL"},
+ {FCVAR_HIDDEN, "HIDDEN"},
+ {FCVAR_PROTECTED, "PROTECTED"},
+ {FCVAR_SPONLY, "SPONLY"},
+ {FCVAR_ARCHIVE, "ARCHIVE"},
+ {FCVAR_NOTIFY, "NOTIFY"},
+ {FCVAR_USERINFO, "USERINFO"},
+
+ // TODO: PRINTABLEONLY and GAMEDLL_FOR_REMOTE_CLIENTS are both 1<<10, one is for vars and one is for commands
+ // this fucking sucks i think
+ {FCVAR_PRINTABLEONLY, "PRINTABLEONLY"},
+ {FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS, "GAMEDLL_FOR_REMOTE_CLIENTS"},
+
+ {FCVAR_UNLOGGED, "UNLOGGED"},
+ {FCVAR_NEVER_AS_STRING, "NEVER_AS_STRING"},
+ {FCVAR_REPLICATED, "REPLICATED"},
+ {FCVAR_CHEAT, "CHEAT"},
+ {FCVAR_SS, "SS"},
+ {FCVAR_DEMO, "DEMO"},
+ {FCVAR_DONTRECORD, "DONTRECORD"},
+ {FCVAR_SS_ADDED, "SS_ADDED"},
+ {FCVAR_RELEASE, "RELEASE"},
+ {FCVAR_RELOAD_MATERIALS, "RELOAD_MATERIALS"},
+ {FCVAR_RELOAD_TEXTURES, "RELOAD_TEXTURES"},
+ {FCVAR_NOT_CONNECTED, "NOT_CONNECTED"},
+ {FCVAR_MATERIAL_SYSTEM_THREAD, "MATERIAL_SYSTEM_THREAD"},
+ {FCVAR_ARCHIVE_PLAYERPROFILE, "ARCHIVE_PLAYERPROFILE"},
+ {FCVAR_SERVER_CAN_EXECUTE, "SERVER_CAN_EXECUTE"},
+ {FCVAR_SERVER_CANNOT_QUERY, "SERVER_CANNOT_QUERY"},
+ {FCVAR_CLIENTCMD_CAN_EXECUTE, "UNKNOWN"},
+ {FCVAR_ACCESSIBLE_FROM_THREADS, "ACCESSIBLE_FROM_THREADS"}};
+
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
@@ -74,6 +117,8 @@ class ConCommandBase;
class ConCommand;
class ConVar;
+typedef void (*FnChangeCallback_t)(ConVar* var, const char* pOldValue, float flOldValue);
+
//-----------------------------------------------------------------------------
// Purpose: A console variable
//-----------------------------------------------------------------------------
@@ -91,7 +136,7 @@ class ConVar
float fMin,
bool bMax,
float fMax,
- void* pCallback);
+ FnChangeCallback_t pCallback);
~ConVar(void);
const char* GetBaseName(void) const;
@@ -125,7 +170,7 @@ class ConVar
bool IsRegistered(void) const;
bool IsCommand(void) const;
- static bool IsFlagSet(ConVar* pConVar, int nFlags);
+ bool IsFlagSet(int nFlags) const;
struct CVValue_t
{
@@ -145,5 +190,3 @@ class ConVar
void* m_pMalloc {}; // 0x0070
char m_pPad80[10] {}; // 0x0080
}; // Size: 0x0080
-
-void InitialiseConVars(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/logging.cpp b/NorthstarDLL/crashhandler.cpp
index 5936007f..8e083078 100644
--- a/NorthstarDedicatedTest/logging.cpp
+++ b/NorthstarDLL/crashhandler.cpp
@@ -1,35 +1,11 @@
#include "pch.h"
-#include "logging.h"
-#include "sourceconsole.h"
-#include "spdlog/sinks/basic_file_sink.h"
-#include "hookutils.h"
+#include "crashhandler.h"
#include "dedicated.h"
-#include "convar.h"
-#include <iomanip>
-#include <sstream>
-#include <Psapi.h>
-#include <minidumpapiset.h>
-#include "configurables.h"
+#include "nsprefix.h"
-// This needs to be called after hooks are loaded so we can access the command line args
-void CreateLogFiles()
-{
- if (strstr(GetCommandLineA(), "-disablelogs"))
- {
- spdlog::default_logger()->set_level(spdlog::level::off);
- }
- else
- {
- // todo: might be good to delete logs that are too old
- time_t time = std::time(nullptr);
- tm currentTime = *std::localtime(&time);
- std::stringstream stream;
+#include <minidumpapiset.h>
- stream << std::put_time(&currentTime, (GetNorthstarPrefix() + "/logs/nslog%Y-%m-%d %H-%M-%S.txt").c_str());
- spdlog::default_logger()->sinks().push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(stream.str(), false));
- spdlog::flush_on(spdlog::level::info);
- }
-}
+HANDLE hExceptionFilter;
long __stdcall ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo)
{
@@ -204,7 +180,7 @@ long __stdcall ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo)
else
spdlog::error("Failed to write minidump file {}!", stream.str());
- if (!IsDedicated())
+ if (!IsDedicatedServer())
MessageBoxA(
0, "Northstar has crashed! Crash info can be found in R2Northstar/logs", "Northstar has crashed!", MB_ICONERROR | MB_OK);
}
@@ -213,8 +189,6 @@ long __stdcall ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo)
return EXCEPTION_EXECUTE_HANDLER;
}
-HANDLE hExceptionFilter;
-
BOOL WINAPI ConsoleHandlerRoutine(DWORD eventCode)
{
switch (eventCode)
@@ -222,7 +196,7 @@ BOOL WINAPI ConsoleHandlerRoutine(DWORD eventCode)
case CTRL_CLOSE_EVENT:
// User closed console, shut everything down
spdlog::info("Exiting due to console close...");
- RemoveVectoredExceptionHandler(hExceptionFilter);
+ RemoveCrashHandler();
exit(EXIT_SUCCESS);
return FALSE;
}
@@ -230,258 +204,13 @@ BOOL WINAPI ConsoleHandlerRoutine(DWORD eventCode)
return TRUE;
}
-void InitialiseLogging()
+void InitialiseCrashHandler()
{
hExceptionFilter = AddVectoredExceptionHandler(TRUE, ExceptionFilter);
-
- AllocConsole();
- freopen("CONOUT$", "w", stdout);
- freopen("CONOUT$", "w", stderr);
- spdlog::default_logger()->set_pattern("[%H:%M:%S] [%l] %v");
-
SetConsoleCtrlHandler(ConsoleHandlerRoutine, true);
}
-ConVar* Cvar_spewlog_enable;
-
-enum SpewType_t
-{
- SPEW_MESSAGE = 0,
-
- SPEW_WARNING,
- SPEW_ASSERT,
- SPEW_ERROR,
- SPEW_LOG,
-
- SPEW_TYPE_COUNT
-};
-
-typedef void (*EngineSpewFuncType)();
-EngineSpewFuncType EngineSpewFunc;
-
-void EngineSpewFuncHook(void* engineServer, SpewType_t type, const char* format, va_list args)
+void RemoveCrashHandler()
{
- if (!Cvar_spewlog_enable->GetBool())
- return;
-
- const char* typeStr;
- switch (type)
- {
- case SPEW_MESSAGE:
- {
- typeStr = "SPEW_MESSAGE";
- break;
- }
-
- case SPEW_WARNING:
- {
- typeStr = "SPEW_WARNING";
- break;
- }
-
- case SPEW_ASSERT:
- {
- typeStr = "SPEW_ASSERT";
- break;
- }
-
- case SPEW_ERROR:
- {
- typeStr = "SPEW_ERROR";
- break;
- }
-
- case SPEW_LOG:
- {
- typeStr = "SPEW_LOG";
- break;
- }
-
- default:
- {
- typeStr = "SPEW_UNKNOWN";
- break;
- }
- }
-
- char formatted[2048] = {0};
- bool shouldFormat = true;
-
- // because titanfall 2 is quite possibly the worst thing to yet exist, it sometimes gives invalid specifiers which will crash
- // ttf2sdk had a way to prevent them from crashing but it doesnt work in debug builds
- // so we use this instead
- for (int i = 0; format[i]; i++)
- {
- if (format[i] == '%')
- {
- switch (format[i + 1])
- {
- // this is fucking awful lol
- case 'd':
- case 'i':
- case 'u':
- case 'x':
- case 'X':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- case 'a':
- case 'A':
- case 'c':
- case 's':
- case 'p':
- case 'n':
- case '%':
- case '-':
- case '+':
- case ' ':
- case '#':
- case '*':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break;
-
- default:
- {
- shouldFormat = false;
- break;
- }
- }
- }
- }
-
- if (shouldFormat)
- vsnprintf(formatted, sizeof(formatted), format, args);
- else
- {
- spdlog::warn("Failed to format {} \"{}\"", typeStr, format);
- }
-
- auto endpos = strlen(formatted);
- if (formatted[endpos - 1] == '\n')
- formatted[endpos - 1] = '\0'; // cut off repeated newline
-
- spdlog::info("[SERVER {}] {}", typeStr, formatted);
-}
-
-typedef void (*Status_ConMsg_Type)(const char* text, ...);
-Status_ConMsg_Type Status_ConMsg_Original;
-
-void Status_ConMsg_Hook(const char* text, ...)
-{
- char formatted[2048];
- va_list list;
-
- va_start(list, text);
- vsprintf_s(formatted, text, list);
- va_end(list);
-
- auto endpos = strlen(formatted);
- if (formatted[endpos - 1] == '\n')
- formatted[endpos - 1] = '\0'; // cut off repeated newline
-
- spdlog::info(formatted);
-}
-
-typedef bool (*CClientState_ProcessPrint_Type)(__int64 thisptr, __int64 msg);
-CClientState_ProcessPrint_Type CClientState_ProcessPrint_Original;
-
-bool CClientState_ProcessPrint_Hook(__int64 thisptr, __int64 msg)
-{
- char* text = *(char**)(msg + 0x20);
-
- auto endpos = strlen(text);
- if (text[endpos - 1] == '\n')
- text[endpos - 1] = '\0'; // cut off repeated newline
-
- spdlog::info(text);
- return true;
-}
-
-void InitialiseEngineSpewFuncHooks(HMODULE baseAddress)
-{
- HookEnabler hook;
-
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x11CA80, EngineSpewFuncHook, reinterpret_cast<LPVOID*>(&EngineSpewFunc));
-
- // Hook print function that status concmd uses to actually print data
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x15ABD0, Status_ConMsg_Hook, reinterpret_cast<LPVOID*>(&Status_ConMsg_Original));
-
- // Hook CClientState::ProcessPrint
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x1A1530,
- CClientState_ProcessPrint_Hook,
- reinterpret_cast<LPVOID*>(&CClientState_ProcessPrint_Original));
-
- Cvar_spewlog_enable = new ConVar("spewlog_enable", "1", FCVAR_NONE, "Enables/disables whether the engine spewfunc should be logged");
+ RemoveVectoredExceptionHandler(hExceptionFilter);
}
-
-#include "bitbuf.h"
-
-ConVar* Cvar_cl_showtextmsg;
-
-typedef void (*TextMsg_Type)(__int64);
-TextMsg_Type TextMsg_Original;
-
-class ICenterPrint
-{
- public:
- virtual void ctor() = 0;
- virtual void Clear(void) = 0;
- virtual void ColorPrint(int r, int g, int b, int a, wchar_t* text) = 0;
- virtual void ColorPrint(int r, int g, int b, int a, char* text) = 0;
- virtual void Print(wchar_t* text) = 0;
- virtual void Print(char* text) = 0;
- virtual void SetTextColor(int r, int g, int b, int a) = 0;
-};
-
-ICenterPrint* internalCenterPrint = NULL;
-
-void TextMsgHook(BFRead* msg)
-{
- int msg_dest = msg->ReadByte();
-
- char text[256];
- msg->ReadString(text, sizeof(text));
-
- if (!Cvar_cl_showtextmsg->GetBool())
- return;
-
- switch (msg_dest)
- {
- case 4: // HUD_PRINTCENTER
- internalCenterPrint->Print(text);
- break;
- default:
- spdlog::warn("Unimplemented TextMsg type {}! printing to console", msg_dest);
- [[fallthrough]];
- case 2: // HUD_PRINTCONSOLE
- auto endpos = strlen(text);
- if (text[endpos - 1] == '\n')
- text[endpos - 1] = '\0'; // cut off repeated newline
- spdlog::info(text);
- break;
- }
-}
-
-void InitialiseClientPrintHooks(HMODULE baseAddress)
-{
- HookEnabler hook;
-
- internalCenterPrint = (ICenterPrint*)((char*)baseAddress + 0x216E940);
-
- // "TextMsg" usermessage
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x198710, TextMsgHook, reinterpret_cast<LPVOID*>(&TextMsg_Original));
-
- Cvar_cl_showtextmsg = new ConVar("cl_showtextmsg", "1", FCVAR_NONE, "Enable/disable text messages printing on the screen.");
-} \ No newline at end of file
diff --git a/NorthstarDLL/crashhandler.h b/NorthstarDLL/crashhandler.h
new file mode 100644
index 00000000..e0dc6906
--- /dev/null
+++ b/NorthstarDLL/crashhandler.h
@@ -0,0 +1,4 @@
+#pragma once
+
+void InitialiseCrashHandler();
+void RemoveCrashHandler();
diff --git a/NorthstarDedicatedTest/cvar.cpp b/NorthstarDLL/cvar.cpp
index 23d767fd..787790be 100644
--- a/NorthstarDedicatedTest/cvar.cpp
+++ b/NorthstarDLL/cvar.cpp
@@ -23,5 +23,9 @@ std::unordered_map<std::string, ConCommandBase*> CCvar::DumpToMap()
return allConVars;
}
-SourceInterface<CCvar>* g_pCVarInterface;
-CCvar* g_pCVar; \ No newline at end of file
+// use the R2 namespace for game funcs
+namespace R2
+{
+ SourceInterface<CCvar>* g_pCVarInterface;
+ CCvar* g_pCVar;
+} // namespace R2
diff --git a/NorthstarDedicatedTest/cvar.h b/NorthstarDLL/cvar.h
index c4525cef..e65e5145 100644
--- a/NorthstarDedicatedTest/cvar.h
+++ b/NorthstarDLL/cvar.h
@@ -35,5 +35,9 @@ class CCvar
std::unordered_map<std::string, ConCommandBase*> DumpToMap();
};
-extern SourceInterface<CCvar>* g_pCVarInterface;
-extern CCvar* g_pCVar; \ No newline at end of file
+// use the R2 namespace for game funcs
+namespace R2
+{
+ extern SourceInterface<CCvar>* g_pCVarInterface;
+ extern CCvar* g_pCVar;
+} // namespace R2
diff --git a/NorthstarDedicatedTest/debugoverlay.cpp b/NorthstarDLL/debugoverlay.cpp
index e29da96b..ef456867 100644
--- a/NorthstarDedicatedTest/debugoverlay.cpp
+++ b/NorthstarDLL/debugoverlay.cpp
@@ -1,17 +1,9 @@
#include "pch.h"
-#include "debugoverlay.h"
#include "dedicated.h"
#include "cvar.h"
+#include "vector.h"
-struct Vector3
-{
- float x, y, z;
-};
-
-struct QAngle
-{
- float x, y, z, w;
-};
+AUTOHOOK_INIT()
enum OverlayType_t
{
@@ -40,7 +32,7 @@ struct OverlayBase_t
int m_nServerCount; // Latch server count, too
float m_flEndTime; // When does this box go away
OverlayBase_t* m_pNextOverlay;
- __int64 m_pUnk;
+ void* m_pUnk;
};
struct OverlayLine_t : public OverlayBase_t
@@ -76,37 +68,18 @@ struct OverlayBox_t : public OverlayBase_t
int a;
};
-// this is in cvar.h, don't need it here
-/*class Color
-{
- public:
- Color(int r, int g, int b, int a)
- {
- _color[0] = (unsigned char)r;
- _color[1] = (unsigned char)g;
- _color[2] = (unsigned char)b;
- _color[3] = (unsigned char)a;
- }
-
- private:
- unsigned char _color[4];
-};*/
-
static HMODULE sEngineModule;
-typedef void (*DrawOverlayType)(OverlayBase_t* a1);
-DrawOverlayType DrawOverlay;
-
typedef void (*RenderLineType)(Vector3 v1, Vector3 v2, Color c, bool bZBuffer);
static RenderLineType RenderLine;
-
typedef void (*RenderBoxType)(Vector3 vOrigin, QAngle angles, Vector3 vMins, Vector3 vMaxs, Color c, bool bZBuffer, bool bInsideOut);
static RenderBoxType RenderBox;
-
static RenderBoxType RenderWireframeBox;
-// engine.dll+0xABCB0
-void __fastcall DrawOverlayHook(OverlayBase_t* pOverlay)
+// clang-format off
+AUTOHOOK(DrawOverlay, engine.dll + 0xABCB0,
+void, __fastcall, (OverlayBase_t * pOverlay))
+// clang-format on
{
EnterCriticalSection((LPCRITICAL_SECTION)((char*)sEngineModule + 0x10DB0A38)); // s_OverlayMutex
@@ -151,25 +124,18 @@ void __fastcall DrawOverlayHook(OverlayBase_t* pOverlay)
LeaveCriticalSection((LPCRITICAL_SECTION)((char*)sEngineModule + 0x10DB0A38));
}
-void InitialiseDebugOverlay(HMODULE baseAddress)
+ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", DebugOverlay, ConVar, (CModule module))
{
- if (IsDedicated())
- return;
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0xABCB0, &DrawOverlayHook, reinterpret_cast<LPVOID*>(&DrawOverlay));
+ AUTOHOOK_DISPATCH()
- RenderLine = reinterpret_cast<RenderLineType>((char*)baseAddress + 0x192A70);
-
- RenderBox = reinterpret_cast<RenderBoxType>((char*)baseAddress + 0x192520);
-
- RenderWireframeBox = reinterpret_cast<RenderBoxType>((char*)baseAddress + 0x193DA0);
-
- sEngineModule = baseAddress;
+ RenderLine = module.Offset(0x192A70).As<RenderLineType>();
+ RenderBox = module.Offset(0x192520).As<RenderBoxType>();
+ RenderWireframeBox = module.Offset(0x193DA0).As<RenderBoxType>();
+ sEngineModule = reinterpret_cast<HMODULE>(module.m_nAddress);
// not in g_pCVar->FindVar by this point for whatever reason, so have to get from memory
- ConVar* Cvar_enable_debug_overlays = (ConVar*)((char*)baseAddress + 0x10DB0990);
+ ConVar* Cvar_enable_debug_overlays = module.Offset(0x10DB0990).As<ConVar*>();
Cvar_enable_debug_overlays->SetValue(false);
Cvar_enable_debug_overlays->m_pszDefaultValue = (char*)"0";
Cvar_enable_debug_overlays->AddFlags(FCVAR_CHEAT);
-} \ No newline at end of file
+}
diff --git a/NorthstarDLL/dedicated.cpp b/NorthstarDLL/dedicated.cpp
new file mode 100644
index 00000000..251e2437
--- /dev/null
+++ b/NorthstarDLL/dedicated.cpp
@@ -0,0 +1,293 @@
+#include "pch.h"
+#include "dedicated.h"
+#include "tier0.h"
+#include "playlist.h"
+#include "r2engine.h"
+#include "hoststate.h"
+#include "serverauthentication.h"
+#include "masterserver.h"
+#include "printcommand.h"
+
+AUTOHOOK_INIT()
+
+using namespace R2;
+
+bool IsDedicatedServer()
+{
+ static bool result = strstr(GetCommandLineA(), "-dedicated");
+ return result;
+}
+
+// CDedidcatedExports defs
+struct CDedicatedExports; // forward declare
+
+typedef void (*DedicatedSys_PrintfType)(CDedicatedExports* dedicated, const char* msg);
+typedef void (*DedicatedRunServerType)(CDedicatedExports* dedicated);
+
+// would've liked to just do this as a class but have not been able to get it to work
+struct CDedicatedExports
+{
+ void* vtable; // because it's easier, we just set this to &this, since CDedicatedExports has no props we care about other than funcs
+
+ char unused[56];
+
+ DedicatedSys_PrintfType Sys_Printf;
+ DedicatedRunServerType RunServer;
+};
+
+void Sys_Printf(CDedicatedExports* dedicated, const char* msg)
+{
+ spdlog::info("[DEDICATED SERVER] {}", msg);
+}
+
+void RunServer(CDedicatedExports* dedicated)
+{
+ spdlog::info("CDedicatedExports::RunServer(): starting");
+ spdlog::info(Tier0::CommandLine()->GetCmdLine());
+
+ // initialise engine
+ g_pEngine->Frame();
+
+ // add +map if not present
+ // don't manually execute this from cbuf as users may have it in their startup args anyway, easier just to run from stuffcmds if present
+ if (!Tier0::CommandLine()->CheckParm("+map"))
+ Tier0::CommandLine()->AppendParm("+map", g_pCVar->FindVar("match_defaultMap")->GetString());
+
+ // re-run commandline
+ Cbuf_AddText(Cbuf_GetCurrentPlayer(), "stuffcmds", cmd_source_t::kCommandSrcCode);
+ Cbuf_Execute();
+
+ // get tickinterval
+ ConVar* Cvar_base_tickinterval_mp = g_pCVar->FindVar("base_tickinterval_mp");
+
+ // main loop
+ double frameTitle = 0;
+ while (g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING)
+ {
+ double frameStart = Tier0::Plat_FloatTime();
+ g_pEngine->Frame();
+
+ std::this_thread::sleep_for(std::chrono::duration<double, std::ratio<1>>(
+ Cvar_base_tickinterval_mp->GetFloat() - fmin(Tier0::Plat_FloatTime() - frameStart, 0.25)));
+ }
+}
+
+// use server presence to update window title
+class DedicatedConsoleServerPresence : public ServerPresenceReporter
+{
+ void ReportPresence(const ServerPresence* pServerPresence) override
+ {
+ SetConsoleTitleA(fmt::format(
+ "{} - {} {}/{} players ({})",
+ pServerPresence->m_sServerName,
+ pServerPresence->m_MapName,
+ pServerPresence->m_iPlayerCount,
+ pServerPresence->m_iMaxPlayers,
+ pServerPresence->m_PlaylistName)
+ .c_str());
+ }
+};
+
+HANDLE consoleInputThreadHandle = NULL;
+DWORD WINAPI ConsoleInputThread(PVOID pThreadParameter)
+{
+ while (!g_pEngine || !g_pHostState || g_pHostState->m_iCurrentState != HostState_t::HS_RUN)
+ Sleep(1000);
+
+ // Bind stdin to receive console input.
+ FILE* fp = nullptr;
+ freopen_s(&fp, "CONIN$", "r", stdin);
+
+ spdlog::info("Ready to receive console commands.");
+
+ {
+ // Process console input
+ std::string input;
+ while (g_pEngine && g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING && std::getline(std::cin, input))
+ {
+ input += "\n";
+ Cbuf_AddText(Cbuf_GetCurrentPlayer(), input.c_str(), cmd_source_t::kCommandSrcCode);
+ TryPrintCvarHelpForCommand(input.c_str()); // this needs to be done on main thread, unstable in this one
+ }
+ }
+
+ return 0;
+}
+
+// clang-format off
+AUTOHOOK(IsGameActiveWindow, engine.dll + 0x1CDC80,
+bool,, ())
+// clang-format on
+{
+ return true;
+}
+
+ON_DLL_LOAD_DEDI_RELIESON("engine.dll", DedicatedServer, ServerPresence, (CModule module))
+{
+ spdlog::info("InitialiseDedicated");
+
+ AUTOHOOK_DISPATCH_MODULE("engine.dll")
+
+ // Host_Init
+ // prevent a particle init that relies on client dll
+ module.Offset(0x156799).NOP(5);
+
+ // Host_Init
+ // don't call Key_Init to avoid loading some extra rsons from rpak (will be necessary to boot if we ever wanna disable rpaks entirely on
+ // dedi)
+ module.Offset(0x1565B0).NOP(5);
+
+ {
+ // CModAppSystemGroup::Create
+ // force the engine into dedicated mode by changing the first comparison to IsServerOnly to an assignment
+ MemoryAddress base = module.Offset(0x1C4EBD);
+
+ // cmp => mov
+ base.Offset(1).Patch("C6 87");
+
+ // 00 => 01
+ base.Offset(7).Patch("01");
+ }
+
+ // Some init that i'm not sure of that crashes
+ // nop the call to it
+ module.Offset(0x156A63).NOP(5);
+
+ // runframeserver
+ // nop some access violations
+ module.Offset(0x159819).NOP(17);
+
+ module.Offset(0x156B4C).NOP(7);
+
+ // previously patched these, took me a couple weeks to figure out they were the issue
+ // removing these will mess up register state when this function is over, so we'll write HS_RUN to the wrong address
+ // so uhh, don't do that
+ // NSMem::NOP(ea + 0x156B4C + 7, 8);
+ module.Offset(0x156B4C).Offset(15).NOP(9);
+
+ // HostState_State_NewGame
+ // nop an access violation
+ module.Offset(0xB934C).NOP(9);
+
+ // CEngineAPI::Connect
+ // remove call to Shader_Connect
+ module.Offset(0x1C4D7D).NOP(5);
+
+ // Host_Init
+ // remove call to ui loading stuff
+ module.Offset(0x156595).NOP(5);
+
+ // some function that gets called from RunFrameServer
+ // nop a function that makes requests to stryder, this will eventually access violation if left alone and isn't necessary anyway
+ module.Offset(0x15A0BB).NOP(5);
+
+ // RunFrameServer
+ // nop a function that access violations
+ module.Offset(0x159BF3).NOP(5);
+
+ // func that checks if origin is inited
+ // always return 1
+ module.Offset(0x183B70).Patch("B0 01 C3"); // mov al,01 ret
+
+ // HostState_State_ChangeLevel
+ // nop clientinterface call
+ module.Offset(0x1552ED).NOP(16);
+
+ // HostState_State_ChangeLevel
+ // nop clientinterface call
+ module.Offset(0x155363).NOP(16);
+
+ // IVideoMode::CreateGameWindow
+ // nop call to ShowWindow
+ module.Offset(0x1CD146).NOP(5);
+
+ CDedicatedExports* dedicatedExports = new CDedicatedExports;
+ dedicatedExports->vtable = dedicatedExports;
+ dedicatedExports->Sys_Printf = Sys_Printf;
+ dedicatedExports->RunServer = RunServer;
+
+ *module.Offset(0x13F0B668).As<CDedicatedExports**>() = dedicatedExports;
+
+ // extra potential patches:
+ // nop engine.dll+1c67d1 and +1c67d8 to skip videomode creategamewindow
+ // also look into launcher.dll+d381, seems to cause renderthread to get made
+ // this crashes HARD if no window which makes sense tbh
+ // also look into materialsystem + 5B344 since it seems to be the base of all the renderthread stuff
+
+ // big note: datatable gets registered in window creation
+ // make sure it still gets registered
+
+ // add cmdline args that are good for dedi
+ Tier0::CommandLine()->AppendParm("-nomenuvid", 0);
+ Tier0::CommandLine()->AppendParm("-nosound", 0);
+ Tier0::CommandLine()->AppendParm("-windowed", 0);
+ Tier0::CommandLine()->AppendParm("-nomessagebox", 0);
+ Tier0::CommandLine()->AppendParm("+host_preload_shaders", "0");
+ Tier0::CommandLine()->AppendParm("+net_usesocketsforloopback", "1");
+
+ // use presence reporter for console title
+ DedicatedConsoleServerPresence* presenceReporter = new DedicatedConsoleServerPresence;
+ g_pServerPresence->AddPresenceReporter(presenceReporter);
+
+ // Disable Quick Edit mode to reduce chance of user unintentionally hanging their server by selecting something.
+ if (!Tier0::CommandLine()->CheckParm("-bringbackquickedit"))
+ {
+ HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD mode = 0;
+
+ if (GetConsoleMode(stdIn, &mode))
+ {
+ if (mode & ENABLE_QUICK_EDIT_MODE)
+ {
+ mode &= ~ENABLE_QUICK_EDIT_MODE;
+ mode &= ~ENABLE_MOUSE_INPUT;
+
+ mode |= ENABLE_PROCESSED_INPUT;
+
+ SetConsoleMode(stdIn, mode);
+ }
+ }
+ }
+ else
+ spdlog::info("Quick Edit enabled by user request");
+
+ // create console input thread
+ if (!Tier0::CommandLine()->CheckParm("-noconsoleinput"))
+ consoleInputThreadHandle = CreateThread(0, 0, ConsoleInputThread, 0, 0, NULL);
+ else
+ spdlog::info("Console input disabled by user request");
+}
+
+ON_DLL_LOAD_DEDI("tier0.dll", DedicatedServerOrigin, (CModule module))
+{
+ // disable origin on dedicated
+ // for any big ea lawyers, this can't be used to play the game without origin, game will throw a fit if you try to do anything without
+ // an origin id as a client for dedi it's fine though, game doesn't care if origin is disabled as long as there's only a server
+ module.GetExport("Tier0_InitOrigin").Patch("C3");
+}
+
+// clang-format off
+AUTOHOOK(PrintSquirrelError, server.dll + 0x794D0,
+void, __fastcall, (void* sqvm))
+// clang-format on
+{
+ PrintSquirrelError(sqvm);
+
+ // close dedicated server if a fatal error is hit
+ static ConVar* Cvar_fatal_script_errors = g_pCVar->FindVar("fatal_script_errors");
+ if (Cvar_fatal_script_errors->GetBool())
+ abort();
+}
+
+ON_DLL_LOAD_DEDI("server.dll", DedicatedServerGameDLL, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(server.dll)
+
+ if (Tier0::CommandLine()->CheckParm("-nopakdedi"))
+ {
+ module.Offset(0x6BA350).Patch("C3"); // dont load skins.rson from rpak if we don't have rpaks, as loading it will cause a crash
+ module.Offset(0x6BA300).Patch(
+ "B8 C8 00 00 00 C3"); // return 200 as the number of skins from server.dll + 6BA300, this is the normal value read from
+ // skins.rson and should be updated when we need it more modular
+ }
+}
diff --git a/NorthstarDLL/dedicated.h b/NorthstarDLL/dedicated.h
new file mode 100644
index 00000000..82806763
--- /dev/null
+++ b/NorthstarDLL/dedicated.h
@@ -0,0 +1,3 @@
+#pragma once
+
+bool IsDedicatedServer();
diff --git a/NorthstarDLL/dedicatedmaterialsystem.cpp b/NorthstarDLL/dedicatedmaterialsystem.cpp
new file mode 100644
index 00000000..28ee9b76
--- /dev/null
+++ b/NorthstarDLL/dedicatedmaterialsystem.cpp
@@ -0,0 +1,41 @@
+#include "pch.h"
+#include "dedicated.h"
+#include "tier0.h"
+
+AUTOHOOK_INIT()
+
+// clang-format off
+AUTOHOOK(D3D11CreateDevice, materialsystem_dx11.dll + 0xD9A0E,
+HRESULT, __stdcall, (
+ void* pAdapter,
+ int DriverType,
+ HMODULE Software,
+ UINT Flags,
+ int* pFeatureLevels,
+ UINT FeatureLevels,
+ UINT SDKVersion,
+ void** ppDevice,
+ int* pFeatureLevel,
+ void** ppImmediateContext))
+// clang-format on
+{
+ // note: this is super duper temp pretty much just messing around with it
+ // does run surprisingly well on dedi for a software driver tho if you ignore the +1gb ram usage at times, seems like dedi doesn't
+ // really call gpu much even with renderthread still being a thing will be using this hook for actual d3d stubbing and stuff later
+
+ // note: this has been succeeded by the d3d11 and gfsdk stubs, and is only being kept around for posterity and as a fallback option
+ if (Tier0::CommandLine()->CheckParm("-softwared3d11"))
+ DriverType = 5; // D3D_DRIVER_TYPE_WARP
+
+ return D3D11CreateDevice(
+ pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext);
+}
+
+ON_DLL_LOAD_DEDI("materialsystem_dx11.dll", DedicatedServerMaterialSystem, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ // CMaterialSystem::FindMaterial
+ // make the game always use the error material
+ module.Offset(0x5F0F1).Patch("E9 34 03 00");
+}
diff --git a/NorthstarDLL/demofixes.cpp b/NorthstarDLL/demofixes.cpp
new file mode 100644
index 00000000..ab092484
--- /dev/null
+++ b/NorthstarDLL/demofixes.cpp
@@ -0,0 +1,26 @@
+#include "pch.h"
+#include "convar.h"
+
+ON_DLL_LOAD_CLIENT("engine.dll", EngineDemoFixes, (CModule module))
+{
+ // allow demo recording on loopback
+ module.Offset(0x8E1B1).NOP(2);
+ module.Offset(0x56CC3).NOP(2);
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientDemoFixes, ConVar, (CModule module))
+{
+ // change default values of demo cvars to enable them by default, but not autorecord
+ // this is before Host_Init, the setvalue calls here will get overwritten by custom cfgs/launch options
+ ConVar* Cvar_demo_enableDemos = R2::g_pCVar->FindVar("demo_enabledemos");
+ Cvar_demo_enableDemos->m_pszDefaultValue = "1";
+ Cvar_demo_enableDemos->SetValue(true);
+
+ ConVar* Cvar_demo_writeLocalFile = R2::g_pCVar->FindVar("demo_writeLocalFile");
+ Cvar_demo_writeLocalFile->m_pszDefaultValue = "1";
+ Cvar_demo_writeLocalFile->SetValue(true);
+
+ ConVar* Cvar_demo_autoRecord = R2::g_pCVar->FindVar("demo_autoRecord");
+ Cvar_demo_autoRecord->m_pszDefaultValue = "0";
+ Cvar_demo_autoRecord->SetValue(false);
+}
diff --git a/NorthstarDLL/dllmain.cpp b/NorthstarDLL/dllmain.cpp
new file mode 100644
index 00000000..8d78ee2c
--- /dev/null
+++ b/NorthstarDLL/dllmain.cpp
@@ -0,0 +1,168 @@
+#include "pch.h"
+#include "main.h"
+#include "logging.h"
+#include "crashhandler.h"
+#include "memalloc.h"
+#include "nsprefix.h"
+#include "plugin_abi.h"
+#include "plugins.h"
+#include "version.h"
+#include "pch.h"
+
+#include "rapidjson/document.h"
+#include "rapidjson/stringbuffer.h"
+#include "rapidjson/writer.h"
+#include "rapidjson/error/en.h"
+
+#include <string.h>
+#include <filesystem>
+
+typedef void (*initPluginFuncPtr)(void* (*getPluginObject)(PluginObject));
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+void freeLibrary(HMODULE hLib)
+{
+ if (!FreeLibrary(hLib))
+ {
+ spdlog::error("There was an error while trying to free library");
+ }
+}
+
+bool LoadPlugins()
+{
+
+ std::vector<fs::path> paths;
+
+ std::string pluginPath = GetNorthstarPrefix() + "/plugins";
+ if (!fs::exists(pluginPath))
+ {
+ spdlog::warn("Could not find a plugins directory. Skipped loading plugins");
+ return false;
+ }
+ // ensure dirs exist
+ fs::recursive_directory_iterator iterator(pluginPath);
+ if (std::filesystem::begin(iterator) == std::filesystem::end(iterator))
+ {
+ spdlog::warn("Could not find any plugins. Skipped loading plugins");
+ return false;
+ }
+ for (auto const& entry : iterator)
+ {
+ if (fs::is_regular_file(entry) && entry.path().extension() == ".dll")
+ paths.emplace_back(entry.path().filename());
+ }
+ initGameState();
+ for (fs::path path : paths)
+ {
+ std::string pathstring = (pluginPath / path).string();
+ std::wstring wpath = (pluginPath / path).wstring();
+
+ LPCWSTR wpptr = wpath.c_str();
+ HMODULE datafile =
+ LoadLibraryExW(wpptr, 0, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); // Load the DLL as a data file
+ if (datafile == NULL)
+ {
+ spdlog::info("Failed to load library {}: ", std::system_category().message(GetLastError()));
+ continue;
+ }
+ HRSRC manifestResource = FindResourceW(datafile, MAKEINTRESOURCEW(101), MAKEINTRESOURCEW(RT_RCDATA));
+
+ if (manifestResource == NULL)
+ {
+ spdlog::info("Could not find manifest for library {}", pathstring);
+ freeLibrary(datafile);
+ continue;
+ }
+ spdlog::info("Loading resource from library");
+ HGLOBAL myResourceData = LoadResource(datafile, manifestResource);
+ if (myResourceData == NULL)
+ {
+ spdlog::error("Failed to load resource from library");
+ freeLibrary(datafile);
+ continue;
+ }
+ int manifestSize = SizeofResource(datafile, manifestResource);
+ std::string manifest = std::string((const char*)LockResource(myResourceData), 0, manifestSize);
+ freeLibrary(datafile);
+
+ rapidjson_document manifestJSON;
+ manifestJSON.Parse(manifest.c_str());
+
+ if (manifestJSON.HasParseError())
+ {
+ spdlog::error("Manifest for {} was invalid", pathstring);
+ continue;
+ }
+ if (!manifestJSON.HasMember("api_version"))
+ {
+ spdlog::error("{} does not have a version number in its manifest", pathstring);
+ continue;
+ // spdlog::info(manifestJSON["version"].GetString());
+ }
+ if (strcmp(manifestJSON["api_version"].GetString(), std::to_string(ABI_VERSION).c_str()))
+ {
+ spdlog::error("{} has an incompatible API version number in its manifest", pathstring);
+ continue;
+ }
+ // Passed all checks, going to actually load it now
+
+ HMODULE pluginLib = LoadLibraryW(wpptr); // Load the DLL as a data file
+ if (pluginLib == NULL)
+ {
+ spdlog::info("Failed to load library {}: ", std::system_category().message(GetLastError()));
+ continue;
+ }
+ initPluginFuncPtr initPlugin = (initPluginFuncPtr)GetProcAddress(pluginLib, "initializePlugin");
+ if (initPlugin == NULL)
+ {
+ spdlog::info("Library {} has no function initializePlugin", pathstring);
+ continue;
+ }
+ spdlog::info("Succesfully loaded {}", pathstring);
+ initPlugin(&getPluginObject);
+ }
+ return true;
+}
+
+bool InitialiseNorthstar()
+{
+ static bool bInitialised = false;
+ if (bInitialised)
+ return false;
+
+ bInitialised = true;
+
+ InitialiseNorthstarPrefix();
+ InitialiseVersion();
+
+ // Fix some users' failure to connect to respawn datacenters
+ SetEnvironmentVariableA("OPENSSL_ia32cap", "~0x200000200000000");
+
+ curl_global_init_mem(CURL_GLOBAL_DEFAULT, _malloc_base, _free_base, _realloc_base, _strdup_base, _calloc_base);
+
+ InitialiseCrashHandler();
+ InitialiseLogging();
+ InstallInitialHooks();
+ CreateLogFiles();
+
+ // Write launcher version to log
+ spdlog::info("NorthstarLauncher version: {}", version);
+
+ // run callbacks for any libraries that are already loaded by now
+ CallAllPendingDLLLoadCallbacks();
+
+ return true;
+}
diff --git a/NorthstarDLL/exploitfixes.cpp b/NorthstarDLL/exploitfixes.cpp
new file mode 100644
index 00000000..de60a854
--- /dev/null
+++ b/NorthstarDLL/exploitfixes.cpp
@@ -0,0 +1,449 @@
+#include "pch.h"
+#include "cvar.h"
+#include "limits.h"
+#include "dedicated.h"
+#include "tier0.h"
+#include "r2engine.h"
+#include "r2client.h"
+#include "vector.h"
+
+AUTOHOOK_INIT()
+
+ConVar* Cvar_ns_exploitfixes_log;
+ConVar* Cvar_ns_should_log_all_clientcommands;
+
+ConVar* Cvar_sv_cheats;
+
+#define BLOCKED_INFO(s) \
+ ( \
+ [=]() -> bool \
+ { \
+ if (Cvar_ns_exploitfixes_log->GetBool()) \
+ { \
+ std::stringstream stream; \
+ stream << "ExploitFixes.cpp: " << BLOCK_PREFIX << s; \
+ spdlog::error(stream.str()); \
+ } \
+ return false; \
+ }())
+
+// block bad netmessages
+// Servers can literally request a screenshot from any client, yeah no
+// clang-format off
+AUTOHOOK(CLC_Screenshot_WriteToBuffer, engine.dll + 0x22AF20,
+bool, __fastcall, (void* thisptr, void* buffer)) // 48 89 5C 24 ? 57 48 83 EC 20 8B 42 10
+// clang-format on
+{
+ return false;
+}
+
+// clang-format off
+AUTOHOOK(CLC_Screenshot_ReadFromBuffer, engine.dll + 0x221F00,
+bool, __fastcall, (void* thisptr, void* buffer)) // 48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B DA 48 8B 52 38
+// clang-format on
+{
+ return false;
+}
+
+// This is unused ingame and a big client=>server=>client exploit vector
+// clang-format off
+AUTOHOOK(Base_CmdKeyValues_ReadFromBuffer, engine.dll + 0x220040,
+bool, __fastcall, (void* thisptr, void* buffer)) // 40 55 48 81 EC ? ? ? ? 48 8D 6C 24 ? 48 89 5D 70
+// clang-format on
+{
+ return false;
+}
+
+// clang-format off
+AUTOHOOK(CClient_ProcessSetConVar, engine.dll + 0x75CF0,
+bool, __fastcall, (void* pMsg)) // 48 8B D1 48 8B 49 18 48 8B 01 48 FF 60 10
+// clang-format on
+{
+
+ constexpr int ENTRY_STR_LEN = 260;
+ struct SetConVarEntry
+ {
+ char name[ENTRY_STR_LEN];
+ char val[ENTRY_STR_LEN];
+ };
+
+ struct NET_SetConVar
+ {
+ void* vtable;
+ void* unk1;
+ void* unk2;
+ void* m_pMessageHandler;
+ SetConVarEntry* m_ConVars; // convar entry array
+ void* unk5; // these 2 unks are just vector capacity or whatever
+ void* unk6;
+ int m_ConVars_count; // amount of cvar entries in array (this will not be out of bounds)
+ };
+
+ auto msg = (NET_SetConVar*)pMsg;
+ bool bIsServerFrame = Tier0::ThreadInServerFrameThread();
+
+ std::string BLOCK_PREFIX =
+ std::string {"NET_SetConVar ("} + (bIsServerFrame ? "server" : "client") + "): Blocked dangerous/invalid msg: ";
+
+ if (bIsServerFrame)
+ {
+ constexpr int SETCONVAR_SANITY_AMOUNT_LIMIT = 69;
+ if (msg->m_ConVars_count < 1 || msg->m_ConVars_count > SETCONVAR_SANITY_AMOUNT_LIMIT)
+ {
+ return BLOCKED_INFO("Invalid m_ConVars_count (" << msg->m_ConVars_count << ")");
+ }
+ }
+
+ for (int i = 0; i < msg->m_ConVars_count; i++)
+ {
+ auto entry = msg->m_ConVars + i;
+
+ // Safety check for memory access
+ if (MemoryAddress(entry).IsMemoryReadable(sizeof(*entry)))
+ {
+ // Find null terminators
+ bool nameValid = false, valValid = false;
+ for (int i = 0; i < ENTRY_STR_LEN; i++)
+ {
+ if (!entry->name[i])
+ nameValid = true;
+ if (!entry->val[i])
+ valValid = true;
+ }
+
+ if (!nameValid || !valValid)
+ return BLOCKED_INFO("Missing null terminators");
+
+ auto realVar = R2::g_pCVar->FindVar(entry->name);
+
+ if (realVar)
+ memcpy(
+ entry->name,
+ realVar->m_ConCommandBase.m_pszName,
+ strlen(realVar->m_ConCommandBase.m_pszName) + 1); // Force name to match case
+
+ bool isValidFlags = true;
+ if (bIsServerFrame)
+ {
+ if (realVar)
+ isValidFlags = realVar->IsFlagSet(FCVAR_USERINFO); // ConVar MUST be userinfo var
+ }
+ else
+ {
+ // TODO: Should probably have some sanity checks, but can't find any that are consistent
+ }
+
+ if (!isValidFlags)
+ {
+ if (!realVar)
+ {
+ return BLOCKED_INFO("Invalid flags on nonexistant cvar (how tho???)");
+ }
+ else
+ {
+ return BLOCKED_INFO(
+ "Invalid flags (" << std::hex << "0x" << realVar->m_ConCommandBase.m_nFlags << "), var is " << entry->name);
+ }
+ }
+ }
+ else
+ {
+ return BLOCKED_INFO("Unreadable memory at " << (void*)entry); // Not risking that one, they all gotta be readable
+ }
+ }
+
+ return CClient_ProcessSetConVar(msg);
+}
+
+// prevent invalid user CMDs
+// clang-format off
+AUTOHOOK(CClient_ProcessUsercmds, engine.dll + 0x1040F0,
+bool, __fastcall, (void* thisptr, void* pMsg)) // 40 55 56 48 83 EC 58
+// clang-format on
+{
+ struct CLC_Move
+ {
+ BYTE gap0[24];
+ void* m_pMessageHandler;
+ int m_nBackupCommands;
+ int m_nNewCommands;
+ int m_nLength;
+ // bf_read m_DataIn;
+ // bf_write m_DataOut;
+ };
+
+ auto msg = (CLC_Move*)pMsg;
+
+ const char* BLOCK_PREFIX = "ProcessUserCmds: ";
+
+ if (msg->m_nBackupCommands < 0)
+ {
+ return BLOCKED_INFO("Invalid m_nBackupCommands (" << msg->m_nBackupCommands << ")");
+ }
+
+ if (msg->m_nNewCommands < 0)
+ {
+ return BLOCKED_INFO("Invalid m_nNewCommands (" << msg->m_nNewCommands << ")");
+ }
+
+ if (msg->m_nLength <= 0)
+ return BLOCKED_INFO("Invalid message length (" << msg->m_nLength << ")");
+
+ return CClient_ProcessUsercmds(thisptr, pMsg);
+}
+
+// clang-format off
+AUTOHOOK(ReadUsercmd, server.dll + 0x2603F0,
+void, __fastcall, (void* buf, void* pCmd_move, void* pCmd_from)) // 4C 89 44 24 ? 53 55 56 57
+// clang-format on
+{
+ // Let normal usercmd read happen first, it's safe
+ ReadUsercmd(buf, pCmd_move, pCmd_from);
+
+ // Now let's make sure the CMD we read isnt messed up to prevent numerous exploits (including server crashing)
+ struct alignas(4) SV_CUserCmd
+ {
+ DWORD command_number;
+ DWORD tick_count;
+ float command_time;
+ Vector3 worldViewAngles;
+ BYTE gap18[4];
+ Vector3 localViewAngles;
+ Vector3 attackangles;
+ Vector3 move;
+ DWORD buttons;
+ BYTE impulse;
+ short weaponselect;
+ DWORD meleetarget;
+ BYTE gap4C[24];
+ char headoffset;
+ BYTE gap65[11];
+ Vector3 cameraPos;
+ Vector3 cameraAngles;
+ BYTE gap88[4];
+ int tickSomething;
+ DWORD dword90;
+ DWORD predictedServerEventAck;
+ DWORD dword98;
+ float frameTime;
+ };
+
+ auto cmd = (SV_CUserCmd*)pCmd_move;
+ auto fromCmd = (SV_CUserCmd*)pCmd_from;
+
+ std::string BLOCK_PREFIX =
+ "ReadUsercmd (command_number delta: " + std::to_string(cmd->command_number - fromCmd->command_number) + "): ";
+
+ // fix invalid player angles
+ cmd->worldViewAngles.MakeValid();
+ cmd->attackangles.MakeValid();
+ cmd->localViewAngles.MakeValid();
+
+ // Fix invalid camera angles
+ cmd->cameraPos.MakeValid();
+ cmd->cameraAngles.MakeValid();
+
+ // Fix invaid movement vector
+ cmd->move.MakeValid();
+
+ if (cmd->frameTime <= 0 || cmd->tick_count == 0 || cmd->command_time <= 0)
+ {
+ BLOCKED_INFO(
+ "Bogus cmd timing (tick_count: " << cmd->tick_count << ", frameTime: " << cmd->frameTime
+ << ", commandTime : " << cmd->command_time << ")");
+ goto INVALID_CMD; // No simulation of bogus-timed cmds
+ }
+
+ return;
+
+INVALID_CMD:
+
+ // Fix any gameplay-affecting cmd properties
+ // NOTE: Currently tickcount/frametime is set to 0, this ~shouldn't~ cause any problems
+ cmd->worldViewAngles = cmd->localViewAngles = cmd->attackangles = cmd->cameraAngles = {0, 0, 0};
+ cmd->tick_count = cmd->frameTime = 0;
+ cmd->move = cmd->cameraPos = {0, 0, 0};
+ cmd->buttons = 0;
+ cmd->meleetarget = 0;
+}
+
+// ensure that GetLocalBaseClient().m_bRestrictServerCommands is set correctly, which the return value of this function controls
+// this is IsValveMod in source, but we're making it IsRespawnMod now since valve didn't make this one
+// clang-format off
+AUTOHOOK(IsRespawnMod, engine.dll + 0x1C6360,
+bool, __fastcall, (const char* pModName)) // 48 83 EC 28 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? E8 ? ? ? ? 85 C0 74 63
+// clang-format on
+{
+ // somewhat temp, store the modname here, since we don't have a proper ptr in engine to it rn
+ int iSize = strlen(pModName);
+ R2::g_pModName = new char[iSize + 1];
+ strcpy(R2::g_pModName, pModName);
+
+ return (!strcmp("r2", pModName) || !strcmp("r1", pModName)) && !Tier0::CommandLine()->CheckParm("-norestrictservercommands");
+}
+
+// ratelimit stringcmds, and prevent remote clients from calling commands that they shouldn't
+bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
+
+// clang-format off
+AUTOHOOK(CGameClient__ExecuteStringCommand, engine.dll + 0x1022E0,
+bool, __fastcall, (R2::CBaseClient* self, uint32_t unknown, const char* pCommandString))
+// clang-format on
+{
+ if (Cvar_ns_should_log_all_clientcommands->GetBool())
+ spdlog::info("player {} (UID: {}) sent command: \"{}\"", self->m_Name, self->m_UID, pCommandString);
+
+ if (!g_pServerLimits->CheckStringCommandLimits(self))
+ {
+ R2::CBaseClient__Disconnect(self, 1, "Sent too many stringcmd commands");
+ return false;
+ }
+
+ // verify the command we're trying to execute is FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS, if it's a concommand
+ char* commandBuf[1040]; // assumedly this is the size of CCommand since we don't have an actual constructor
+ memset(commandBuf, 0, sizeof(commandBuf));
+ CCommand tempCommand = *(CCommand*)&commandBuf;
+
+ if (!CCommand__Tokenize(tempCommand, pCommandString, R2::cmd_source_t::kCommandSrcCode) || !tempCommand.ArgC())
+ return false;
+
+ ConCommand* command = R2::g_pCVar->FindCommand(tempCommand.Arg(0));
+
+ // if the command doesn't exist pass it on to ExecuteStringCommand for script clientcommands and stuff
+ if (command && !command->IsFlagSet(FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS))
+ {
+ // ensure FCVAR_GAMEDLL concommands without FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS can't be executed by remote clients
+ if (IsDedicatedServer())
+ return false;
+
+ if (strcmp(self->m_UID, R2::g_pLocalPlayerUserID))
+ return false;
+ }
+
+ // check for and block abusable legacy portal 2 commands
+ // these aren't actually concommands weirdly enough, they seem to just be hardcoded
+ if (!Cvar_sv_cheats->GetBool())
+ {
+ constexpr const char* blockedCommands[] = {
+ "emit", // Sound-playing exploit (likely for Portal 2 coop devs testing splitscreen sound or something)
+
+ // These both execute a command for every single entity for some reason, nice one valve
+ "pre_go_to_hub",
+ "pre_go_to_calibration",
+
+ "end_movie", // Calls "__MovieFinished" script function, not sure exactly what this does but it certainly isn't needed
+ "load_recent_checkpoint" // This is the instant-respawn exploit, literally just calls RespawnPlayer()
+ };
+
+ int iCmdLength = strlen(tempCommand.Arg(0));
+
+ bool bIsBadCommand = false;
+ for (auto& blockedCommand : blockedCommands)
+ {
+ if (iCmdLength != strlen(blockedCommand))
+ continue;
+
+ for (int i = 0; tempCommand.Arg(0)[i]; i++)
+ if (tolower(tempCommand.Arg(0)[i]) != blockedCommand[i])
+ goto NEXT_COMMAND; // break out of this loop, then go to next command
+
+ // this is a command we need to block
+ return false;
+ NEXT_COMMAND:;
+ }
+ }
+
+ return CGameClient__ExecuteStringCommand(self, unknown, pCommandString);
+}
+
+// prevent clients from crashing servers through overflowing CNetworkStringTableContainer::WriteBaselines
+bool bWasWritingStringTableSuccessful;
+
+// clang-format off
+AUTOHOOK(CBaseClient__SendServerInfo, engine.dll + 0x104FB0,
+void, __fastcall, (void* self))
+// clang-format on
+{
+ bWasWritingStringTableSuccessful = true;
+ CBaseClient__SendServerInfo(self);
+ if (!bWasWritingStringTableSuccessful)
+ R2::CBaseClient__Disconnect(
+ self, 1, "Overflowed CNetworkStringTableContainer::WriteBaselines, try restarting your client and reconnecting");
+}
+
+// return null when GetEntByIndex is passed an index >= 0x4000
+// this is called from exactly 1 script clientcommand that can be given an arbitrary index, and going above 0x4000 crashes
+// clang-format off
+AUTOHOOK(GetEntByIndex, server.dll + 0x2A8A50,
+void*, __fastcall, (int i))
+// clang-format on
+{
+ const int MAX_ENT_IDX = 0x4000;
+
+ if (i >= MAX_ENT_IDX)
+ {
+ spdlog::warn("GetEntByIndex {} is out of bounds (max {})", i, MAX_ENT_IDX);
+ return nullptr;
+ }
+
+ return GetEntByIndex(i);
+}
+
+ON_DLL_LOAD("engine.dll", EngineExploitFixes, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(engine.dll)
+
+ CCommand__Tokenize = module.Offset(0x418380).As<bool (*)(CCommand&, const char*, R2::cmd_source_t)>();
+
+ // allow client/ui to run clientcommands despite restricting servercommands
+ module.Offset(0x4FB65).Patch("EB 11");
+ module.Offset(0x4FBAC).Patch("EB 16");
+
+ // patch to set bWasWritingStringTableSuccessful in CNetworkStringTableContainer::WriteBaselines if it fails
+ {
+ MemoryAddress writeAddress(&bWasWritingStringTableSuccessful - module.Offset(0x234EDC).m_nAddress);
+
+ MemoryAddress addr = module.Offset(0x234ED2);
+ addr.Patch("C7 05");
+ addr.Offset(2).Patch((BYTE*)&writeAddress, sizeof(writeAddress));
+
+ addr.Offset(6).Patch("00 00 00 00");
+
+ addr.Offset(10).NOP(5);
+ }
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerExploitFixes, ConVar, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(server.dll)
+
+ // ret at the start of CServerGameClients::ClientCommandKeyValues as it has no benefit and is forwarded to client (i.e. security issue)
+ // this prevents the attack vector of client=>server=>client, however server=>client also has clientside patches
+ module.Offset(0x153920).Patch("C3");
+
+ // Dumb ANTITAMPER patches (they negatively impact performance and security)
+ constexpr const char* ANTITAMPER_EXPORTS[] = {
+ "ANTITAMPER_SPOTCHECK_CODEMARKER",
+ "ANTITAMPER_TESTVALUE_CODEMARKER",
+ "ANTITAMPER_TRIGGER_CODEMARKER",
+ };
+
+ // Prevent these from actually doing anything
+ for (auto exportName : ANTITAMPER_EXPORTS)
+ {
+ MemoryAddress exportAddr = module.GetExport(exportName);
+ if (exportAddr)
+ {
+ // Just return, none of them have any args or are userpurge
+ exportAddr.Patch("C3");
+ spdlog::info("Patched AntiTamper function export \"{}\"", exportName);
+ }
+ }
+
+ Cvar_ns_exploitfixes_log =
+ new ConVar("ns_exploitfixes_log", "1", FCVAR_GAMEDLL, "Whether to log whenever ExploitFixes.cpp blocks/corrects something");
+ Cvar_ns_should_log_all_clientcommands =
+ new ConVar("ns_should_log_all_clientcommands", "0", FCVAR_NONE, "Whether to log all clientcommands");
+
+ Cvar_sv_cheats = R2::g_pCVar->FindVar("sv_cheats");
+}
diff --git a/NorthstarDLL/exploitfixes_lzss.cpp b/NorthstarDLL/exploitfixes_lzss.cpp
new file mode 100644
index 00000000..4205133a
--- /dev/null
+++ b/NorthstarDLL/exploitfixes_lzss.cpp
@@ -0,0 +1,79 @@
+#include "pch.h"
+
+AUTOHOOK_INIT()
+
+static constexpr int LZSS_LOOKSHIFT = 4;
+
+struct lzss_header_t
+{
+ unsigned int id;
+ unsigned int actualSize;
+};
+
+// Rewrite of CLZSS::SafeUncompress to fix a vulnerability where malicious compressed payloads could cause the decompressor to try to read
+// out of the bounds of the output buffer.
+// clang-format off
+AUTOHOOK(CLZSS__SafeDecompress, engine.dll + 0x432A10,
+unsigned int, __fastcall, (void* self, const unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize))
+// clang-format on
+{
+ unsigned int totalBytes = 0;
+ int getCmdByte = 0;
+ int cmdByte = 0;
+
+ lzss_header_t header = *(lzss_header_t*)pInput;
+
+ if (!pInput || !header.actualSize || header.id != 0x53535A4C || header.actualSize > unBufSize)
+ return 0;
+
+ pInput += sizeof(lzss_header_t);
+
+ for (;;)
+ {
+ if (!getCmdByte)
+ cmdByte = *pInput++;
+
+ getCmdByte = (getCmdByte + 1) & 0x07;
+
+ if (cmdByte & 0x01)
+ {
+ int position = *pInput++ << LZSS_LOOKSHIFT;
+ position |= (*pInput >> LZSS_LOOKSHIFT);
+ position += 1;
+ int count = (*pInput++ & 0x0F) + 1;
+ if (count == 1)
+ break;
+
+ // Ensure reference chunk exists entirely within our buffer
+ if (position > totalBytes)
+ return 0;
+
+ totalBytes += count;
+ if (totalBytes > unBufSize)
+ return 0;
+
+ unsigned char* pSource = pOutput - position;
+ for (int i = 0; i < count; i++)
+ *pOutput++ = *pSource++;
+ }
+ else
+ {
+ totalBytes++;
+ if (totalBytes > unBufSize)
+ return 0;
+
+ *pOutput++ = *pInput++;
+ }
+ cmdByte = cmdByte >> 1;
+ }
+
+ if (totalBytes != header.actualSize)
+ return 0;
+
+ return totalBytes;
+}
+
+ON_DLL_LOAD("engine.dll", ExploitFixes_LZSS, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+}
diff --git a/NorthstarDLL/exploitfixes_utf8parser.cpp b/NorthstarDLL/exploitfixes_utf8parser.cpp
new file mode 100644
index 00000000..e2510765
--- /dev/null
+++ b/NorthstarDLL/exploitfixes_utf8parser.cpp
@@ -0,0 +1,200 @@
+#include "pch.h"
+
+AUTOHOOK_INIT()
+
+INT64(__fastcall* sub_F1320)(DWORD a1, char* a2);
+
+// Reimplementation of an exploitable UTF decoding function in titanfall
+bool __fastcall CheckUTF8Valid(INT64* a1, DWORD* a2, char* strData)
+{
+ DWORD v3; // eax
+ char* v4; // rbx
+ char v5; // si
+ char* _strData; // rdi
+ char* v7; // rbp
+ char v11; // al
+ DWORD v12; // er9
+ DWORD v13; // ecx
+ DWORD v14; // edx
+ DWORD v15; // er8
+ int v16; // eax
+ DWORD v17; // er9
+ int v18; // eax
+ DWORD v19; // er9
+ DWORD v20; // ecx
+ int v21; // eax
+ int v22; // er9
+ DWORD v23; // edx
+ int v24; // eax
+ int v25; // er9
+ DWORD v26; // er9
+ DWORD v27; // er10
+ DWORD v28; // ecx
+ DWORD v29; // edx
+ DWORD v30; // er8
+ int v31; // eax
+ DWORD v32; // er10
+ int v33; // eax
+ DWORD v34; // er10
+ DWORD v35; // ecx
+ int v36; // eax
+ int v37; // er10
+ DWORD v38; // edx
+ int v39; // eax
+ int v40; // er10
+ DWORD v41; // er10
+ INT64 v43; // r8
+ INT64 v44; // rdx
+ INT64 v45; // rcx
+ INT64 v46; // rax
+ INT64 v47; // rax
+ char v48; // al
+ INT64 v49; // r8
+ INT64 v50; // rdx
+ INT64 v51; // rcx
+ INT64 v52; // rax
+ INT64 v53; // rax
+
+ v3 = a2[2];
+ v4 = (char*)(a1[1] + *a2);
+ v5 = 0;
+ _strData = strData;
+ v7 = &v4[*((UINT16*)a2 + 2)];
+ if (v3 >= 2)
+ {
+ ++v4;
+ --v7;
+ if (v3 != 2)
+ {
+ while (1)
+ {
+ if (!MemoryAddress(v4).IsMemoryReadable(1))
+ return false; // INVALID
+
+ v11 = *v4++; // crash potential
+ if (v11 != 92)
+ goto LABEL_6;
+ v11 = *v4++;
+ if (v11 == 110)
+ break;
+ switch (v11)
+ {
+ case 't':
+ v11 = 9;
+ goto LABEL_6;
+ case 'r':
+ v11 = 13;
+ goto LABEL_6;
+ case 'b':
+ v11 = 8;
+ goto LABEL_6;
+ case 'f':
+ v11 = 12;
+ goto LABEL_6;
+ }
+ if (v11 != 117)
+ goto LABEL_6;
+ v12 = *v4 | 0x20;
+ v13 = v4[1] | 0x20;
+ v14 = v4[2] | 0x20;
+ v15 = v4[3] | 0x20;
+ v16 = 87;
+ if (v12 <= 0x39)
+ v16 = 48;
+ v17 = v12 - v16;
+ v18 = 87;
+ v19 = v17 << 12;
+ if (v13 <= 0x39)
+ v18 = 48;
+ v20 = v13 - v18;
+ v21 = 87;
+ v22 = (v20 << 8) | v19;
+ if (v14 <= 0x39)
+ v21 = 48;
+ v23 = v14 - v21;
+ v24 = 87;
+ v25 = (16 * v23) | v22;
+ if (v15 <= 0x39)
+ v24 = 48;
+ v4 += 4;
+ v26 = (v15 - v24) | v25;
+ if (v26 - 55296 <= 0x7FF)
+ {
+ if (v26 >= 0xDC00)
+ return true;
+ if (*v4 != 92 || v4[1] != 117)
+ return true;
+
+ v27 = v4[2] | 0x20;
+ v28 = v4[3] | 0x20;
+ v29 = v4[4] | 0x20;
+ v30 = v4[5] | 0x20;
+ v31 = 87;
+ if (v27 <= 0x39)
+ v31 = 48;
+ v32 = v27 - v31;
+ v33 = 87;
+ v34 = v32 << 12;
+ if (v28 <= 0x39)
+ v33 = 48;
+ v35 = v28 - v33;
+ v36 = 87;
+ v37 = (v35 << 8) | v34;
+ if (v29 <= 0x39)
+ v36 = 48;
+ v38 = v29 - v36;
+ v39 = 87;
+ v40 = (16 * v38) | v37;
+ if (v30 <= 0x39)
+ v39 = 48;
+ v4 += 6;
+ v41 = ((v30 - v39) | v40) - 56320;
+ if (v41 > 0x3FF)
+ return true;
+ v26 = v41 | ((v26 - 55296) << 10);
+ }
+ _strData += (DWORD)sub_F1320(v26, _strData);
+ LABEL_7:
+ if (v4 == v7)
+ goto LABEL_48;
+ }
+ v11 = 10;
+ LABEL_6:
+ v5 |= v11;
+ *_strData++ = v11;
+ goto LABEL_7;
+ }
+ }
+LABEL_48:
+ return true;
+}
+
+// prevent utf8 parser from crashing when provided bad data, which can be sent through user-controlled openinvites
+// clang-format off
+AUTOHOOK(Rson_ParseUTF8, engine.dll + 0xEF670,
+bool, __fastcall, (INT64* a1, DWORD* a2, char* strData)) // 48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 54 41 55 41 56 41 57 48 83 EC 20 8B 1A
+// clang-format on
+{
+ static void* targetRetAddr = CModule("engine.dll").FindPattern("84 C0 75 2C 49 8B 16");
+
+ // only call if we're parsing utf8 data from the network (i.e. communities), otherwise we get perf issues
+ void* pReturnAddress =
+#ifdef _MSC_VER
+ _ReturnAddress()
+#else
+ __builtin_return_address(0)
+#endif
+ ;
+
+ if (pReturnAddress == targetRetAddr && !CheckUTF8Valid(a1, a2, strData))
+ return false;
+
+ return Rson_ParseUTF8(a1, a2, strData);
+}
+
+ON_DLL_LOAD("engine.dll", EngineExploitFixes_UTF8Parser, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ sub_F1320 = module.FindPattern("83 F9 7F 77 08 88 0A").As<INT64(__fastcall*)(DWORD, char*)>();
+}
diff --git a/NorthstarDLL/filesystem.cpp b/NorthstarDLL/filesystem.cpp
new file mode 100644
index 00000000..e6c6f49a
--- /dev/null
+++ b/NorthstarDLL/filesystem.cpp
@@ -0,0 +1,186 @@
+#include "pch.h"
+#include "filesystem.h"
+#include "sourceinterface.h"
+#include "modmanager.h"
+
+#include <iostream>
+#include <sstream>
+
+AUTOHOOK_INIT()
+
+using namespace R2;
+
+bool bReadingOriginalFile = false;
+std::string sCurrentModPath;
+
+ConVar* Cvar_ns_fs_log_reads;
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ SourceInterface<IFileSystem>* g_pFilesystem;
+
+ std::string ReadVPKFile(const char* path)
+ {
+ // read scripts.rson file, todo: check if this can be overwritten
+ FileHandle_t fileHandle = (*g_pFilesystem)->m_vtable2->Open(&(*g_pFilesystem)->m_vtable2, path, "rb", "GAME", 0);
+
+ std::stringstream fileStream;
+ int bytesRead = 0;
+ char data[4096];
+ do
+ {
+ bytesRead = (*g_pFilesystem)->m_vtable2->Read(&(*g_pFilesystem)->m_vtable2, data, (int)std::size(data), fileHandle);
+ fileStream.write(data, bytesRead);
+ } while (bytesRead == std::size(data));
+
+ (*g_pFilesystem)->m_vtable2->Close(*g_pFilesystem, fileHandle);
+
+ return fileStream.str();
+ }
+
+ std::string ReadVPKOriginalFile(const char* path)
+ {
+ // todo: should probably set search path to be g_pModName here also
+
+ bReadingOriginalFile = true;
+ std::string ret = ReadVPKFile(path);
+ bReadingOriginalFile = false;
+
+ return ret;
+ }
+} // namespace R2
+
+// clang-format off
+HOOK(AddSearchPathHook, AddSearchPath,
+void, __fastcall, (IFileSystem * fileSystem, const char* pPath, const char* pathID, SearchPathAdd_t addType))
+// clang-format on
+{
+ AddSearchPath(fileSystem, pPath, pathID, addType);
+
+ // make sure current mod paths are at head
+ if (!strcmp(pathID, "GAME") && sCurrentModPath.compare(pPath) && addType == PATH_ADD_TO_HEAD)
+ {
+ AddSearchPath(fileSystem, sCurrentModPath.c_str(), "GAME", PATH_ADD_TO_HEAD);
+ AddSearchPath(fileSystem, GetCompiledAssetsPath().string().c_str(), "GAME", PATH_ADD_TO_HEAD);
+ }
+}
+
+void SetNewModSearchPaths(Mod* mod)
+{
+ // put our new path to the head if we need to read from a different mod path
+ // in the future we could also determine whether the file we're setting paths for needs a mod dir, or compiled assets
+ if (mod != nullptr)
+ {
+ if ((fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string().compare(sCurrentModPath))
+ {
+ spdlog::info("changing mod search path from {} to {}", sCurrentModPath, mod->m_ModDirectory.string());
+
+ AddSearchPath(
+ &*(*g_pFilesystem), (fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string().c_str(), "GAME", PATH_ADD_TO_HEAD);
+ sCurrentModPath = (fs::absolute(mod->m_ModDirectory) / MOD_OVERRIDE_DIR).string();
+ }
+ }
+ else // push compiled to head
+ AddSearchPath(&*(*g_pFilesystem), fs::absolute(GetCompiledAssetsPath()).string().c_str(), "GAME", PATH_ADD_TO_HEAD);
+}
+
+bool TryReplaceFile(const char* pPath, bool shouldCompile)
+{
+ if (bReadingOriginalFile)
+ return false;
+
+ if (shouldCompile)
+ g_pModManager->CompileAssetsForFile(pPath);
+
+ // idk how efficient the lexically normal check is
+ // can't just set all /s in path to \, since some paths aren't in writeable memory
+ auto file = g_pModManager->m_ModFiles.find(g_pModManager->NormaliseModFilePath(fs::path(pPath)));
+ if (file != g_pModManager->m_ModFiles.end())
+ {
+ SetNewModSearchPaths(file->second.m_pOwningMod);
+ return true;
+ }
+
+ return false;
+}
+
+// force modded files to be read from mods, not cache
+// clang-format off
+HOOK(ReadFromCacheHook, ReadFromCache,
+bool, __fastcall, (IFileSystem * filesystem, char* pPath, void* result))
+// clang-format off
+{
+ if (TryReplaceFile(pPath, true))
+ return false;
+
+ return ReadFromCache(filesystem, pPath, result);
+}
+
+// force modded files to be read from mods, not vpk
+// clang-format off
+AUTOHOOK(ReadFileFromVPK, filesystem_stdio.dll + 0x5CBA0,
+FileHandle_t, __fastcall, (VPKData* vpkInfo, uint64_t* b, char* filename))
+// clang-format on
+{
+ // don't compile here because this is only ever called from OpenEx, which already compiles
+ if (TryReplaceFile(filename, false))
+ {
+ *b = -1;
+ return b;
+ }
+
+ return ReadFileFromVPK(vpkInfo, b, filename);
+}
+
+// clang-format off
+AUTOHOOK(CBaseFileSystem__OpenEx, filesystem_stdio.dll + 0x15F50,
+FileHandle_t, __fastcall, (IFileSystem* filesystem, const char* pPath, const char* pOptions, uint32_t flags, const char* pPathID, char **ppszResolvedFilename))
+// clang-format on
+{
+ TryReplaceFile(pPath, true);
+ return CBaseFileSystem__OpenEx(filesystem, pPath, pOptions, flags, pPathID, ppszResolvedFilename);
+}
+
+HOOK(MountVPKHook, MountVPK, VPKData*, , (IFileSystem * fileSystem, const char* pVpkPath))
+{
+ spdlog::info("MountVPK {}", pVpkPath);
+ VPKData* ret = MountVPK(fileSystem, pVpkPath);
+
+ for (Mod mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.m_bEnabled)
+ continue;
+
+ for (ModVPKEntry& vpkEntry : mod.Vpks)
+ {
+ // if we're autoloading, just load no matter what
+ if (!vpkEntry.m_bAutoLoad)
+ {
+ // resolve vpk name and try to load one with the same name
+ // todo: we should be unloading these on map unload manually
+ std::string mapName(fs::path(pVpkPath).filename().string());
+ std::string modMapName(fs::path(vpkEntry.m_sVpkPath.c_str()).filename().string());
+ if (mapName.compare(modMapName))
+ continue;
+ }
+
+ VPKData* loaded = MountVPK(fileSystem, vpkEntry.m_sVpkPath.c_str());
+ if (!ret) // this is primarily for map vpks and stuff, so the map's vpk is what gets returned from here
+ ret = loaded;
+ }
+ }
+
+ return ret;
+}
+
+ON_DLL_LOAD("filesystem_stdio.dll", Filesystem, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ R2::g_pFilesystem = new SourceInterface<IFileSystem>("filesystem_stdio.dll", "VFileSystem017");
+
+ AddSearchPathHook.Dispatch((*g_pFilesystem)->m_vtable->AddSearchPath);
+ ReadFromCacheHook.Dispatch((*g_pFilesystem)->m_vtable->ReadFromCache);
+ MountVPKHook.Dispatch((*g_pFilesystem)->m_vtable->MountVPK);
+}
diff --git a/NorthstarDedicatedTest/filesystem.h b/NorthstarDLL/filesystem.h
index 960c2836..c326b419 100644
--- a/NorthstarDedicatedTest/filesystem.h
+++ b/NorthstarDLL/filesystem.h
@@ -59,7 +59,8 @@ class IFileSystem
FileHandle_t (*Open)(
IFileSystem::VTable2** fileSystem, const char* pFileName, const char* pOptions, const char* pathID, int64_t unknown);
void (*Close)(IFileSystem* fileSystem, FileHandle_t file);
- void* unknown2[6];
+ long long (*Seek)(IFileSystem::VTable2** fileSystem, FileHandle_t file, long long offset, long long whence);
+ void* unknown2[5];
bool (*FileExists)(IFileSystem::VTable2** fileSystem, const char* pFileName, const char* pPathID);
};
@@ -67,8 +68,11 @@ class IFileSystem
VTable2* m_vtable2;
};
-std::string ReadVPKFile(const char* path);
-std::string ReadVPKOriginalFile(const char* path);
+// use the R2 namespace for game funcs
+namespace R2
+{
+ extern SourceInterface<IFileSystem>* g_pFilesystem;
-void InitialiseFilesystem(HMODULE baseAddress);
-extern SourceInterface<IFileSystem>* g_Filesystem; \ No newline at end of file
+ std::string ReadVPKFile(const char* path);
+ std::string ReadVPKOriginalFile(const char* path);
+} // namespace R2
diff --git a/NorthstarDLL/hooks.cpp b/NorthstarDLL/hooks.cpp
new file mode 100644
index 00000000..4c068fe8
--- /dev/null
+++ b/NorthstarDLL/hooks.cpp
@@ -0,0 +1,398 @@
+#include "pch.h"
+#include "dedicated.h"
+
+#include <iostream>
+#include <wchar.h>
+#include <iostream>
+#include <vector>
+#include <fstream>
+#include <sstream>
+#include <filesystem>
+#include <Psapi.h>
+
+AUTOHOOK_INIT()
+
+// called from the ON_DLL_LOAD macros
+__dllLoadCallback::__dllLoadCallback(
+ eDllLoadCallbackSide side, const std::string dllName, DllLoadCallbackFuncType callback, std::string uniqueStr, std::string reliesOn)
+{
+ // parse reliesOn array from string
+ std::vector<std::string> reliesOnArray;
+
+ if (reliesOn.length() && reliesOn[0] != '(')
+ {
+ reliesOnArray.push_back(reliesOn);
+ }
+ else
+ {
+ // follows the format (tag, tag, tag)
+ std::string sCurrentTag;
+ for (int i = 1; i < reliesOn.length(); i++)
+ {
+ if (!isspace(reliesOn[i]))
+ {
+ if (reliesOn[i] == ',' || reliesOn[i] == ')')
+ {
+ reliesOnArray.push_back(sCurrentTag);
+ sCurrentTag = "";
+ }
+ else
+ sCurrentTag += reliesOn[i];
+ }
+ }
+ }
+
+ switch (side)
+ {
+ case eDllLoadCallbackSide::UNSIDED:
+ {
+ AddDllLoadCallback(dllName, callback, uniqueStr, reliesOnArray);
+ break;
+ }
+
+ case eDllLoadCallbackSide::CLIENT:
+ {
+ AddDllLoadCallbackForClient(dllName, callback, uniqueStr, reliesOnArray);
+ break;
+ }
+
+ case eDllLoadCallbackSide::DEDICATED_SERVER:
+ {
+ AddDllLoadCallbackForDedicatedServer(dllName, callback, uniqueStr, reliesOnArray);
+ break;
+ }
+ }
+}
+
+void __fileAutohook::Dispatch()
+{
+ for (__autohook* hook : hooks)
+ hook->Dispatch();
+}
+
+void __fileAutohook::DispatchForModule(const char* pModuleName)
+{
+ const int iModuleNameLen = strlen(pModuleName);
+
+ for (__autohook* hook : hooks)
+ if ((hook->iAddressResolutionMode == __autohook::OFFSET_STRING && !strncmp(pModuleName, hook->pAddrString, iModuleNameLen)) ||
+ (hook->iAddressResolutionMode == __autohook::PROCADDRESS && !strcmp(pModuleName, hook->pModuleName)))
+ hook->Dispatch();
+}
+
+ManualHook::ManualHook(const char* funcName, LPVOID func) : pHookFunc(func), ppOrigFunc(nullptr)
+{
+ const int iFuncNameStrlen = strlen(funcName);
+ pFuncName = new char[iFuncNameStrlen];
+ memcpy(pFuncName, funcName, iFuncNameStrlen);
+}
+
+ManualHook::ManualHook(const char* funcName, LPVOID* orig, LPVOID func) : pHookFunc(func), ppOrigFunc(orig)
+{
+ const int iFuncNameStrlen = strlen(funcName);
+ pFuncName = new char[iFuncNameStrlen];
+ memcpy(pFuncName, funcName, iFuncNameStrlen);
+}
+
+bool ManualHook::Dispatch(LPVOID addr, LPVOID* orig)
+{
+ if (orig)
+ ppOrigFunc = orig;
+
+ if (MH_CreateHook(addr, pHookFunc, ppOrigFunc) == MH_OK)
+ {
+ if (MH_EnableHook(addr) == MH_OK)
+ {
+ spdlog::info("Enabling hook {}", pFuncName);
+ return true;
+ }
+ else
+ spdlog::error("MH_EnableHook failed for function {}", pFuncName);
+ }
+ else
+ spdlog::error("MH_CreateHook failed for function {}", pFuncName);
+
+ return false;
+}
+
+// dll load callback stuff
+// this allows for code to register callbacks to be run as soon as a dll is loaded, mainly to allow for patches to be made on dll load
+struct DllLoadCallback
+{
+ std::string dll;
+ DllLoadCallbackFuncType callback;
+ std::string tag;
+ std::vector<std::string> reliesOn;
+ bool called;
+};
+
+// HACK: declaring and initialising this vector at file scope crashes on debug builds due to static initialisation order
+// using a static var like this ensures that the vector is initialised lazily when it's used
+std::vector<DllLoadCallback>& GetDllLoadCallbacks()
+{
+ static std::vector<DllLoadCallback> vec = std::vector<DllLoadCallback>();
+ return vec;
+}
+
+void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback, std::string tag, std::vector<std::string> reliesOn)
+{
+ DllLoadCallback& callbackStruct = GetDllLoadCallbacks().emplace_back();
+
+ callbackStruct.dll = dll;
+ callbackStruct.callback = callback;
+ callbackStruct.tag = tag;
+ callbackStruct.reliesOn = reliesOn;
+ callbackStruct.called = false;
+}
+
+void AddDllLoadCallbackForDedicatedServer(
+ std::string dll, DllLoadCallbackFuncType callback, std::string tag, std::vector<std::string> reliesOn)
+{
+ if (!IsDedicatedServer())
+ return;
+
+ AddDllLoadCallback(dll, callback, tag, reliesOn);
+}
+
+void AddDllLoadCallbackForClient(std::string dll, DllLoadCallbackFuncType callback, std::string tag, std::vector<std::string> reliesOn)
+{
+ if (IsDedicatedServer())
+ return;
+
+ AddDllLoadCallback(dll, callback, tag, reliesOn);
+}
+
+void MakeHook(LPVOID pTarget, LPVOID pDetour, void* ppOriginal, const char* pFuncName)
+{
+ char* pStrippedFuncName = (char*)pFuncName;
+ // strip & char from funcname
+ if (*pStrippedFuncName == '&')
+ pStrippedFuncName++;
+
+ if (MH_CreateHook(pTarget, pDetour, (LPVOID*)ppOriginal) == MH_OK)
+ {
+ if (MH_EnableHook(pTarget) == MH_OK)
+ spdlog::info("Enabling hook {}", pStrippedFuncName);
+ else
+ spdlog::error("MH_EnableHook failed for function {}", pStrippedFuncName);
+ }
+ else
+ spdlog::error("MH_CreateHook failed for function {}", pStrippedFuncName);
+}
+
+AUTOHOOK_ABSOLUTEADDR(_GetCommandLineA, GetCommandLineA, LPSTR, WINAPI, ())
+{
+ static char* cmdlineModified;
+ static char* cmdlineOrg;
+
+ if (cmdlineOrg == nullptr || cmdlineModified == nullptr)
+ {
+ cmdlineOrg = _GetCommandLineA();
+ bool isDedi = strstr(cmdlineOrg, "-dedicated"); // well, this one has to be a real argument
+ bool ignoreStartupArgs = strstr(cmdlineOrg, "-nostartupargs");
+
+ std::string args;
+ std::ifstream cmdlineArgFile;
+
+ // it looks like CommandLine() prioritizes parameters apprearing first, so we want the real commandline to take priority
+ // not to mention that cmdlineOrg starts with the EXE path
+ args.append(cmdlineOrg);
+ args.append(" ");
+
+ // append those from the file
+
+ if (!ignoreStartupArgs)
+ {
+
+ cmdlineArgFile = std::ifstream(!isDedi ? "ns_startup_args.txt" : "ns_startup_args_dedi.txt");
+
+ if (cmdlineArgFile)
+ {
+ std::stringstream argBuffer;
+ argBuffer << cmdlineArgFile.rdbuf();
+ cmdlineArgFile.close();
+
+ // if some other command line option includes "-northstar" in the future then you have to refactor this check to check with
+ // both either space after or ending with
+ if (!isDedi && argBuffer.str().find("-northstar") != std::string::npos)
+ MessageBoxA(
+ NULL,
+ "The \"-northstar\" command line option is NOT supposed to go into ns_startup_args.txt file!\n\nThis option is "
+ "supposed to go into Origin/Steam game launch options, and then you are supposed to launch the original "
+ "Titanfall2.exe "
+ "rather than NorthstarLauncher.exe to make use of it.",
+ "Northstar Warning",
+ MB_ICONWARNING);
+
+ args.append(argBuffer.str());
+ }
+ }
+
+ auto len = args.length();
+ cmdlineModified = new char[len + 1];
+ if (!cmdlineModified)
+ {
+ spdlog::error("malloc failed for command line");
+ return cmdlineOrg;
+ }
+ memcpy(cmdlineModified, args.c_str(), len + 1);
+
+ spdlog::info("Command line: {}", cmdlineModified);
+ }
+
+ return cmdlineModified;
+}
+
+std::vector<std::string> calledTags;
+void CallLoadLibraryACallbacks(LPCSTR lpLibFileName, HMODULE moduleAddress)
+{
+ CModule cModule(moduleAddress);
+
+ while (true)
+ {
+ bool bDoneCalling = true;
+
+ for (auto& callbackStruct : GetDllLoadCallbacks())
+ {
+ if (!callbackStruct.called && fs::path(lpLibFileName).filename() == fs::path(callbackStruct.dll).filename())
+ {
+ bool bShouldContinue = false;
+
+ if (!callbackStruct.reliesOn.empty())
+ {
+ for (std::string tag : callbackStruct.reliesOn)
+ {
+ if (std::find(calledTags.begin(), calledTags.end(), tag) == calledTags.end())
+ {
+ bDoneCalling = false;
+ bShouldContinue = true;
+ break;
+ }
+ }
+ }
+
+ if (bShouldContinue)
+ continue;
+
+ callbackStruct.callback(moduleAddress);
+ calledTags.push_back(callbackStruct.tag);
+ callbackStruct.called = true;
+ }
+ }
+
+ if (bDoneCalling)
+ break;
+ }
+}
+
+void CallLoadLibraryWCallbacks(LPCWSTR lpLibFileName, HMODULE moduleAddress)
+{
+ CModule cModule(moduleAddress);
+
+ while (true)
+ {
+ bool bDoneCalling = true;
+
+ for (auto& callbackStruct : GetDllLoadCallbacks())
+ {
+ if (!callbackStruct.called && fs::path(lpLibFileName).filename() == fs::path(callbackStruct.dll).filename())
+ {
+ bool bShouldContinue = false;
+
+ if (!callbackStruct.reliesOn.empty())
+ {
+ for (std::string tag : callbackStruct.reliesOn)
+ {
+ if (std::find(calledTags.begin(), calledTags.end(), tag) == calledTags.end())
+ {
+ bDoneCalling = false;
+ bShouldContinue = true;
+ break;
+ }
+ }
+ }
+
+ if (bShouldContinue)
+ continue;
+
+ callbackStruct.callback(moduleAddress);
+ calledTags.push_back(callbackStruct.tag);
+ callbackStruct.called = true;
+ }
+ }
+
+ if (bDoneCalling)
+ break;
+ }
+}
+
+void CallAllPendingDLLLoadCallbacks()
+{
+ HMODULE hMods[1024];
+ HANDLE hProcess = GetCurrentProcess();
+ DWORD cbNeeded;
+ unsigned int i;
+
+ // Get a list of all the modules in this process.
+ if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
+ {
+ for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
+ {
+ wchar_t szModName[MAX_PATH];
+
+ // Get the full path to the module's file.
+ if (GetModuleFileNameExW(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
+ {
+ CallLoadLibraryWCallbacks(szModName, hMods[i]);
+ }
+ }
+ }
+}
+
+AUTOHOOK_ABSOLUTEADDR(_LoadLibraryExA, LoadLibraryExA, HMODULE, WINAPI, (LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags))
+{
+ HMODULE moduleAddress = _LoadLibraryExA(lpLibFileName, hFile, dwFlags);
+
+ if (moduleAddress)
+ CallLoadLibraryACallbacks(lpLibFileName, moduleAddress);
+
+ return moduleAddress;
+}
+
+AUTOHOOK_ABSOLUTEADDR(_LoadLibraryA, LoadLibraryA, HMODULE, WINAPI, (LPCSTR lpLibFileName))
+{
+ HMODULE moduleAddress = _LoadLibraryA(lpLibFileName);
+
+ if (moduleAddress)
+ CallLoadLibraryACallbacks(lpLibFileName, moduleAddress);
+
+ return moduleAddress;
+}
+
+AUTOHOOK_ABSOLUTEADDR(_LoadLibraryExW, LoadLibraryExW, HMODULE, WINAPI, (LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags))
+{
+ HMODULE moduleAddress = _LoadLibraryExW(lpLibFileName, hFile, dwFlags);
+
+ if (moduleAddress)
+ CallLoadLibraryWCallbacks(lpLibFileName, moduleAddress);
+
+ return moduleAddress;
+}
+
+AUTOHOOK_ABSOLUTEADDR(_LoadLibraryW, LoadLibraryW, HMODULE, WINAPI, (LPCWSTR lpLibFileName))
+{
+ HMODULE moduleAddress = _LoadLibraryW(lpLibFileName);
+
+ if (moduleAddress)
+ CallLoadLibraryWCallbacks(lpLibFileName, moduleAddress);
+
+ return moduleAddress;
+}
+
+void InstallInitialHooks()
+{
+ if (MH_Initialize() != MH_OK)
+ spdlog::error("MH_Initialize (minhook initialization) failed");
+
+ AUTOHOOK_DISPATCH()
+}
diff --git a/NorthstarDLL/hooks.h b/NorthstarDLL/hooks.h
new file mode 100644
index 00000000..f47791fb
--- /dev/null
+++ b/NorthstarDLL/hooks.h
@@ -0,0 +1,311 @@
+#pragma once
+#include "memory.h"
+
+#include <string>
+#include <iostream>
+
+void InstallInitialHooks();
+
+typedef void (*DllLoadCallbackFuncType)(CModule moduleAddress);
+void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback, std::string tag = "", std::vector<std::string> reliesOn = {});
+void AddDllLoadCallbackForDedicatedServer(
+ std::string dll, DllLoadCallbackFuncType callback, std::string tag = "", std::vector<std::string> reliesOn = {});
+void AddDllLoadCallbackForClient(
+ std::string dll, DllLoadCallbackFuncType callback, std::string tag = "", std::vector<std::string> reliesOn = {});
+
+void CallAllPendingDLLLoadCallbacks();
+
+// new dll load callback stuff
+enum class eDllLoadCallbackSide
+{
+ UNSIDED,
+ CLIENT,
+ DEDICATED_SERVER
+};
+
+class __dllLoadCallback
+{
+ public:
+ __dllLoadCallback() = delete;
+ __dllLoadCallback(
+ eDllLoadCallbackSide side,
+ const std::string dllName,
+ DllLoadCallbackFuncType callback,
+ std::string uniqueStr,
+ std::string reliesOn);
+};
+
+#define __CONCAT3(x, y, z) x##y##z
+#define CONCAT3(x, y, z) __CONCAT3(x, y, z)
+#define __CONCAT2(x, y) x##y
+#define CONCAT2(x, y) __CONCAT2(x, y)
+#define __STR(s) #s
+
+// adds a callback to be called when a given dll is loaded, for creating hooks and such
+#define __ON_DLL_LOAD(dllName, side, uniquestr, reliesOn, args) \
+ void CONCAT2(__dllLoadCallback, uniquestr) args; \
+ namespace \
+ { \
+ __dllLoadCallback CONCAT2(__dllLoadCallbackInstance, __LINE__)( \
+ side, dllName, CONCAT2(__dllLoadCallback, uniquestr), __STR(uniquestr), reliesOn); \
+ } \
+ void CONCAT2(__dllLoadCallback, uniquestr) args
+
+#define ON_DLL_LOAD(dllName, uniquestr, args) __ON_DLL_LOAD(dllName, eDllLoadCallbackSide::UNSIDED, uniquestr, "", args)
+#define ON_DLL_LOAD_RELIESON(dllName, uniquestr, reliesOn, args) \
+ __ON_DLL_LOAD(dllName, eDllLoadCallbackSide::UNSIDED, uniquestr, __STR(reliesOn), args)
+#define ON_DLL_LOAD_CLIENT(dllName, uniquestr, args) __ON_DLL_LOAD(dllName, eDllLoadCallbackSide::CLIENT, uniquestr, "", args)
+#define ON_DLL_LOAD_CLIENT_RELIESON(dllName, uniquestr, reliesOn, args) \
+ __ON_DLL_LOAD(dllName, eDllLoadCallbackSide::CLIENT, uniquestr, __STR(reliesOn), args)
+#define ON_DLL_LOAD_DEDI(dllName, uniquestr, args) __ON_DLL_LOAD(dllName, eDllLoadCallbackSide::DEDICATED_SERVER, uniquestr, "", args)
+#define ON_DLL_LOAD_DEDI_RELIESON(dllName, uniquestr, reliesOn, args) \
+ __ON_DLL_LOAD(dllName, eDllLoadCallbackSide::DEDICATED_SERVER, uniquestr, __STR(reliesOn), args)
+
+// new macro hook stuff
+class __autohook;
+
+class __fileAutohook
+{
+ public:
+ std::vector<__autohook*> hooks;
+
+ void Dispatch();
+ void DispatchForModule(const char* pModuleName);
+};
+
+// initialise autohooks for this file
+#define AUTOHOOK_INIT() \
+ namespace \
+ { \
+ __fileAutohook __FILEAUTOHOOK; \
+ }
+
+// dispatch all autohooks in this file
+#define AUTOHOOK_DISPATCH() __FILEAUTOHOOK.Dispatch();
+
+#define AUTOHOOK_DISPATCH_MODULE(moduleName) __FILEAUTOHOOK.DispatchForModule(__STR(moduleName));
+
+class __autohook
+{
+ public:
+ enum AddressResolutionMode
+ {
+ OFFSET_STRING, // we're using a string that of the format dllname.dll + offset
+ ABSOLUTE_ADDR, // we're using an absolute address, we don't need to process it at all
+ PROCADDRESS // resolve using GetModuleHandle and GetProcAddress
+ };
+
+ char* pFuncName;
+
+ LPVOID pHookFunc;
+ LPVOID* ppOrigFunc;
+
+ // address resolution props
+ AddressResolutionMode iAddressResolutionMode;
+ char* pAddrString = nullptr; // for OFFSET_STRING
+ LPVOID iAbsoluteAddress = nullptr; // for ABSOLUTE_ADDR
+ char* pModuleName; // for PROCADDRESS
+ char* pProcName; // for PROCADDRESS
+
+ public:
+ __autohook() = delete;
+
+ __autohook(__fileAutohook* autohook, const char* funcName, LPVOID absoluteAddress, LPVOID* orig, LPVOID func)
+ : pHookFunc(func), ppOrigFunc(orig), iAbsoluteAddress(absoluteAddress)
+ {
+ iAddressResolutionMode = ABSOLUTE_ADDR;
+
+ const int iFuncNameStrlen = strlen(funcName) + 1;
+ pFuncName = new char[iFuncNameStrlen];
+ memcpy(pFuncName, funcName, iFuncNameStrlen);
+
+ autohook->hooks.push_back(this);
+ }
+
+ __autohook(__fileAutohook* autohook, const char* funcName, const char* addrString, LPVOID* orig, LPVOID func)
+ : pHookFunc(func), ppOrigFunc(orig)
+ {
+ iAddressResolutionMode = OFFSET_STRING;
+
+ const int iFuncNameStrlen = strlen(funcName) + 1;
+ pFuncName = new char[iFuncNameStrlen];
+ memcpy(pFuncName, funcName, iFuncNameStrlen);
+
+ const int iAddrStrlen = strlen(addrString) + 1;
+ pAddrString = new char[iAddrStrlen];
+ memcpy(pAddrString, addrString, iAddrStrlen);
+
+ autohook->hooks.push_back(this);
+ }
+
+ __autohook(__fileAutohook* autohook, const char* funcName, const char* moduleName, const char* procName, LPVOID* orig, LPVOID func)
+ : pHookFunc(func), ppOrigFunc(orig)
+ {
+ iAddressResolutionMode = PROCADDRESS;
+
+ const int iFuncNameStrlen = strlen(funcName) + 1;
+ pFuncName = new char[iFuncNameStrlen];
+ memcpy(pFuncName, funcName, iFuncNameStrlen);
+
+ const int iModuleNameStrlen = strlen(moduleName) + 1;
+ pModuleName = new char[iModuleNameStrlen];
+ memcpy(pModuleName, moduleName, iModuleNameStrlen);
+
+ const int iProcNameStrlen = strlen(procName) + 1;
+ pProcName = new char[iProcNameStrlen];
+ memcpy(pProcName, procName, iProcNameStrlen);
+
+ autohook->hooks.push_back(this);
+ }
+
+ ~__autohook()
+ {
+ delete[] pFuncName;
+
+ if (pAddrString)
+ delete[] pAddrString;
+
+ if (pModuleName)
+ delete[] pModuleName;
+
+ if (pProcName)
+ delete[] pProcName;
+ }
+
+ void Dispatch()
+ {
+ LPVOID targetAddr = nullptr;
+
+ // determine the address of the function we're hooking
+ switch (iAddressResolutionMode)
+ {
+ case ABSOLUTE_ADDR:
+ {
+ targetAddr = iAbsoluteAddress;
+ break;
+ }
+
+ case OFFSET_STRING:
+ {
+ // in the format server.dll + 0xDEADBEEF
+ int iDllNameEnd = 0;
+ for (; !isspace(pAddrString[iDllNameEnd]) && pAddrString[iDllNameEnd] != '+'; iDllNameEnd++)
+ ;
+
+ char* pModuleName = new char[iDllNameEnd + 1];
+ memcpy(pModuleName, pAddrString, iDllNameEnd);
+ pModuleName[iDllNameEnd] = '\0';
+
+ // get the module address
+ const HMODULE pModuleAddr = GetModuleHandleA(pModuleName);
+
+ if (!pModuleAddr)
+ break;
+
+ // get the offset string
+ uintptr_t iOffset = 0;
+
+ int iOffsetBegin = iDllNameEnd;
+ int iOffsetEnd = strlen(pAddrString);
+
+ // seek until we hit the start of the number offset
+ for (; !(pAddrString[iOffsetBegin] >= '0' && pAddrString[iOffsetBegin] <= '9') && pAddrString[iOffsetBegin]; iOffsetBegin++)
+ ;
+
+ bool bIsHex =
+ pAddrString[iOffsetBegin] == '0' && (pAddrString[iOffsetBegin + 1] == 'X' || pAddrString[iOffsetBegin + 1] == 'x');
+ if (bIsHex)
+ iOffset = std::stoi(pAddrString + iOffsetBegin + 2, 0, 16);
+ else
+ iOffset = std::stoi(pAddrString + iOffsetBegin);
+
+ targetAddr = (LPVOID)((uintptr_t)pModuleAddr + iOffset);
+ break;
+ }
+
+ case PROCADDRESS:
+ {
+ targetAddr = GetProcAddress(GetModuleHandleA(pModuleName), pProcName);
+ break;
+ }
+ }
+
+ if (MH_CreateHook(targetAddr, pHookFunc, ppOrigFunc) == MH_OK)
+ {
+ if (MH_EnableHook(targetAddr) == MH_OK)
+ spdlog::info("Enabling hook {}", pFuncName);
+ else
+ spdlog::error("MH_EnableHook failed for function {}", pFuncName);
+ }
+ else
+ spdlog::error("MH_CreateHook failed for function {}", pFuncName);
+ }
+};
+
+// hook a function at a given offset from a dll to be dispatched with AUTOHOOK_DISPATCH()
+#define AUTOHOOK(name, addrString, type, callingConvention, args) \
+ type callingConvention CONCAT2(__autohookfunc, name) args; \
+ namespace \
+ { \
+ type(*callingConvention name) args; \
+ __autohook CONCAT2(__autohook, __LINE__)( \
+ &__FILEAUTOHOOK, __STR(name), __STR(addrString), (LPVOID*)&name, (LPVOID)CONCAT2(__autohookfunc, name)); \
+ } \
+ type callingConvention CONCAT2(__autohookfunc, name) args
+
+// hook a function at a given absolute constant address to be dispatched with AUTOHOOK_DISPATCH()
+#define AUTOHOOK_ABSOLUTEADDR(name, addr, type, callingConvention, args) \
+ type callingConvention CONCAT2(__autohookfunc, name) args; \
+ namespace \
+ { \
+ type(*callingConvention name) args; \
+ __autohook \
+ CONCAT2(__autohook, __LINE__)(&__FILEAUTOHOOK, __STR(name), addr, (LPVOID*)&name, (LPVOID)CONCAT2(__autohookfunc, name)); \
+ } \
+ type callingConvention CONCAT2(__autohookfunc, name) args
+
+// hook a function at a given module and exported function to be dispatched with AUTOHOOK_DISPATCH()
+#define AUTOHOOK_PROCADDRESS(name, moduleName, procName, type, callingConvention, args) \
+ type callingConvention CONCAT2(__autohookfunc, name) args; \
+ namespace \
+ { \
+ type(*callingConvention name) args; \
+ __autohook CONCAT2(__autohook, __LINE__)( \
+ &__FILEAUTOHOOK, __STR(name), __STR(moduleName), __STR(procName), (LPVOID*)&name, (LPVOID)CONCAT2(__autohookfunc, name)); \
+ } \
+ type callingConvention CONCAT2(__autohookfunc, name) \
+ args
+
+class ManualHook
+{
+ public:
+ char* pFuncName;
+
+ LPVOID pHookFunc;
+ LPVOID* ppOrigFunc;
+
+ public:
+ ManualHook() = delete;
+ ManualHook(const char* funcName, LPVOID func);
+ ManualHook(const char* funcName, LPVOID* orig, LPVOID func);
+ bool Dispatch(LPVOID addr, LPVOID* orig = nullptr);
+};
+
+// hook a function to be dispatched manually later
+#define HOOK(varName, originalFunc, type, callingConvention, args) \
+ namespace \
+ { \
+ type(*callingConvention originalFunc) args; \
+ } \
+ type callingConvention CONCAT2(__manualhookfunc, varName) args; \
+ ManualHook varName = ManualHook(__STR(varName), (LPVOID*)&originalFunc, (LPVOID)CONCAT2(__manualhookfunc, varName)); \
+ type callingConvention CONCAT2(__manualhookfunc, varName) args
+
+#define HOOK_NOORIG(varName, type, callingConvention, args) \
+ type callingConvention CONCAT2(__manualhookfunc, varName) args; \
+ ManualHook varName = ManualHook(__STR(varName), (LPVOID)CONCAT2(__manualhookfunc, varName)); \
+ type callingConvention CONCAT2(__manualhookfunc, varName) \
+ args
+
+void MakeHook(LPVOID pTarget, LPVOID pDetour, void* ppOriginal, const char* pFuncName = "");
+#define MAKEHOOK(pTarget, pDetour, ppOriginal) MakeHook(pTarget, pDetour, ppOriginal, __STR(pDetour))
diff --git a/NorthstarDLL/host.cpp b/NorthstarDLL/host.cpp
new file mode 100644
index 00000000..e8cb9bdc
--- /dev/null
+++ b/NorthstarDLL/host.cpp
@@ -0,0 +1,73 @@
+#include "pch.h"
+#include "convar.h"
+#include "modmanager.h"
+#include "printcommand.h"
+#include "printmaps.h"
+#include "r2engine.h"
+
+AUTOHOOK_INIT()
+
+// clang-format off
+AUTOHOOK(Host_Init, engine.dll + 0x155EA0,
+void, __fastcall, (bool bDedicated))
+// clang-format on
+{
+ spdlog::info("Host_Init()");
+ Host_Init(bDedicated);
+
+ // get all mod convars
+ std::vector<std::string> vModConvarNames;
+ for (auto& mod : g_pModManager->m_LoadedMods)
+ for (auto& cvar : mod.ConVars)
+ vModConvarNames.push_back(cvar->Name);
+
+ // strip hidden and devonly cvar flags
+ int iNumCvarsAltered = 0;
+ for (auto& pair : R2::g_pCVar->DumpToMap())
+ {
+ // don't remove from mod cvars
+ if (std::find(vModConvarNames.begin(), vModConvarNames.end(), pair.second->m_pszName) != vModConvarNames.end())
+ continue;
+
+ // strip flags
+ int flags = pair.second->GetFlags();
+ if (flags & FCVAR_DEVELOPMENTONLY)
+ {
+ flags &= ~FCVAR_DEVELOPMENTONLY;
+ iNumCvarsAltered++;
+ }
+
+ if (flags & FCVAR_HIDDEN)
+ {
+ flags &= ~FCVAR_HIDDEN;
+ iNumCvarsAltered++;
+ }
+
+ pair.second->m_nFlags = flags;
+ }
+
+ spdlog::info("Removed {} hidden/devonly cvar flags", iNumCvarsAltered);
+
+ // make servers able to run disconnect on clients
+ R2::g_pCVar->FindCommand("disconnect")->m_nFlags |= FCVAR_SERVER_CAN_EXECUTE;
+
+ // make clients able to run status and ping
+ R2::g_pCVar->FindCommand("status")->m_nFlags |= FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS;
+ R2::g_pCVar->FindCommand("ping")->m_nFlags |= FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS;
+
+ // need to initialise these after host_init since they do stuff to preexisting concommands/convars without being client/server specific
+ InitialiseCommandPrint();
+ InitialiseMapsPrint();
+
+ // client/server autoexecs on necessary platforms
+ // dedi needs autoexec_ns_server on boot, while non-dedi will run it on on listen server start
+ if (bDedicated)
+ R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "exec autoexec_ns_server", R2::cmd_source_t::kCommandSrcCode);
+ else
+ R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "exec autoexec_ns_client", R2::cmd_source_t::kCommandSrcCode);
+}
+
+ON_DLL_LOAD("engine.dll", Host_Init, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+}
diff --git a/NorthstarDLL/hoststate.cpp b/NorthstarDLL/hoststate.cpp
new file mode 100644
index 00000000..adbcde3b
--- /dev/null
+++ b/NorthstarDLL/hoststate.cpp
@@ -0,0 +1,116 @@
+#include "pch.h"
+#include "hoststate.h"
+#include "masterserver.h"
+#include "serverauthentication.h"
+#include "serverpresence.h"
+#include "playlist.h"
+#include "tier0.h"
+#include "r2engine.h"
+#include "limits.h"
+
+AUTOHOOK_INIT()
+
+using namespace R2;
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ CHostState* g_pHostState;
+} // namespace R2
+
+ConVar* Cvar_hostport;
+
+void ServerStartingOrChangingMap()
+{
+ // net_data_block_enabled is required for sp, force it if we're on an sp map
+ // sucks for security but just how it be
+ if (!strncmp(g_pHostState->m_levelName, "sp_", 3))
+ g_pCVar->FindVar("net_data_block_enabled")->SetValue(true);
+}
+
+// clang-format off
+AUTOHOOK(CHostState__State_NewGame, engine.dll + 0x16E7D0,
+void, __fastcall, (CHostState* self))
+// clang-format on
+{
+ spdlog::info("HostState: NewGame");
+
+ Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec autoexec_ns_server", cmd_source_t::kCommandSrcCode);
+ Cbuf_Execute();
+
+ // need to do this to ensure we don't go to private match
+ if (g_pServerAuthentication->m_bNeedLocalAuthForNewgame)
+ SetCurrentPlaylist("tdm");
+
+ // don't require authentication on singleplayer startup
+ g_pServerAuthentication->m_bRequireClientAuth = strncmp(g_pHostState->m_levelName, "sp_", 3);
+
+ ServerStartingOrChangingMap();
+
+ double dStartTime = Tier0::Plat_FloatTime();
+ CHostState__State_NewGame(self);
+ spdlog::info("loading took {}s", Tier0::Plat_FloatTime() - dStartTime);
+
+ // setup server presence
+ g_pServerPresence->CreatePresence();
+ g_pServerPresence->SetMap(g_pHostState->m_levelName, true);
+ g_pServerPresence->SetPlaylist(GetCurrentPlaylistName());
+ g_pServerPresence->SetPort(Cvar_hostport->GetInt());
+
+ g_pServerAuthentication->StartPlayerAuthServer();
+ g_pServerAuthentication->m_bNeedLocalAuthForNewgame = false;
+}
+
+// clang-format off
+AUTOHOOK(CHostState__State_ChangeLevelMP, engine.dll + 0x16E520,
+void, __fastcall, (CHostState* self))
+// clang-format on
+{
+ spdlog::info("HostState: ChangeLevelMP");
+
+ ServerStartingOrChangingMap();
+
+ double dStartTime = Tier0::Plat_FloatTime();
+ CHostState__State_ChangeLevelMP(self);
+ spdlog::info("loading took {}s", Tier0::Plat_FloatTime() - dStartTime);
+
+ g_pServerPresence->SetMap(g_pHostState->m_levelName);
+}
+
+// clang-format off
+AUTOHOOK(CHostState__State_GameShutdown, engine.dll + 0x16E640,
+void, __fastcall, (CHostState* self))
+// clang-format on
+{
+ spdlog::info("HostState: GameShutdown");
+
+ g_pServerPresence->DestroyPresence();
+ g_pServerAuthentication->StopPlayerAuthServer();
+
+ CHostState__State_GameShutdown(self);
+}
+
+// clang-format off
+AUTOHOOK(CHostState__FrameUpdate, engine.dll + 0x16DB00,
+void, __fastcall, (CHostState* self, double flCurrentTime, float flFrameTime))
+// clang-format on
+{
+ CHostState__FrameUpdate(self, flCurrentTime, flFrameTime);
+
+ if (*R2::g_pServerState == R2::server_state_t::ss_active)
+ {
+ // update server presence
+ g_pServerPresence->RunFrame(flCurrentTime);
+
+ // update limits for frame
+ g_pServerLimits->RunFrame(flCurrentTime, flFrameTime);
+ }
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", HostState, ConVar, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ g_pHostState = module.Offset(0x7CF180).As<CHostState*>();
+ Cvar_hostport = module.Offset(0x13FA6070).As<ConVar*>();
+}
diff --git a/NorthstarDLL/hoststate.h b/NorthstarDLL/hoststate.h
new file mode 100644
index 00000000..a77385ef
--- /dev/null
+++ b/NorthstarDLL/hoststate.h
@@ -0,0 +1,45 @@
+#pragma once
+
+// use the R2 namespace for game funxcs
+namespace R2
+{
+ enum class HostState_t
+ {
+ HS_NEW_GAME = 0,
+ HS_LOAD_GAME,
+ HS_CHANGE_LEVEL_SP,
+ HS_CHANGE_LEVEL_MP,
+ HS_RUN,
+ HS_GAME_SHUTDOWN,
+ HS_SHUTDOWN,
+ HS_RESTART,
+ };
+
+ struct CHostState
+ {
+ public:
+ HostState_t m_iCurrentState;
+ HostState_t m_iNextState;
+
+ float m_vecLocation[3];
+ float m_angLocation[3];
+
+ char m_levelName[32];
+ char m_mapGroupName[32];
+ char m_landmarkName[32];
+ char m_saveName[32];
+ float m_flShortFrameTime; // run a few one-tick frames to avoid large timesteps while loading assets
+
+ bool m_activeGame;
+ bool m_bRememberLocation;
+ bool m_bBackgroundLevel;
+ bool m_bWaitingForConnection;
+ bool m_bLetToolsOverrideLoadGameEnts; // During a load game, this tells Foundry to override ents that are selected in Hammer.
+ bool m_bSplitScreenConnect;
+ bool m_bGameHasShutDownAndFlushedMemory; // This is false once we load a map into memory, and set to true once the map is unloaded
+ // and all memory flushed
+ bool m_bWorkshopMapDownloadPending;
+ };
+
+ extern CHostState* g_pHostState;
+} // namespace R2
diff --git a/NorthstarDedicatedTest/include/MinHook.h b/NorthstarDLL/include/MinHook.h
index 15c0a875..15c0a875 100644
--- a/NorthstarDedicatedTest/include/MinHook.h
+++ b/NorthstarDLL/include/MinHook.h
diff --git a/NorthstarDedicatedTest/include/MinHook.x64.lib b/NorthstarDLL/include/MinHook.x64.lib
index 213df08f..a346f386 100644
--- a/NorthstarDedicatedTest/include/MinHook.x64.lib
+++ b/NorthstarDLL/include/MinHook.x64.lib
Binary files differ
diff --git a/NorthstarDedicatedTest/include/crypto/__DECC_INCLUDE_EPILOGUE.H b/NorthstarDLL/include/crypto/__DECC_INCLUDE_EPILOGUE.H
index e57c0eab..e57c0eab 100644
--- a/NorthstarDedicatedTest/include/crypto/__DECC_INCLUDE_EPILOGUE.H
+++ b/NorthstarDLL/include/crypto/__DECC_INCLUDE_EPILOGUE.H
diff --git a/NorthstarDedicatedTest/include/crypto/__DECC_INCLUDE_PROLOGUE.H b/NorthstarDLL/include/crypto/__DECC_INCLUDE_PROLOGUE.H
index a0139575..a0139575 100644
--- a/NorthstarDedicatedTest/include/crypto/__DECC_INCLUDE_PROLOGUE.H
+++ b/NorthstarDLL/include/crypto/__DECC_INCLUDE_PROLOGUE.H
diff --git a/NorthstarDedicatedTest/include/crypto/aes_platform.h b/NorthstarDLL/include/crypto/aes_platform.h
index e95ad5aa..e95ad5aa 100644
--- a/NorthstarDedicatedTest/include/crypto/aes_platform.h
+++ b/NorthstarDLL/include/crypto/aes_platform.h
diff --git a/NorthstarDedicatedTest/include/crypto/aria.h b/NorthstarDLL/include/crypto/aria.h
index 21a9932e..21a9932e 100644
--- a/NorthstarDedicatedTest/include/crypto/aria.h
+++ b/NorthstarDLL/include/crypto/aria.h
diff --git a/NorthstarDedicatedTest/include/crypto/asn1.h b/NorthstarDLL/include/crypto/asn1.h
index ec76ae6f..ec76ae6f 100644
--- a/NorthstarDedicatedTest/include/crypto/asn1.h
+++ b/NorthstarDLL/include/crypto/asn1.h
diff --git a/NorthstarDedicatedTest/include/crypto/asn1_dsa.h b/NorthstarDLL/include/crypto/asn1_dsa.h
index 3eadb9ec..3eadb9ec 100644
--- a/NorthstarDedicatedTest/include/crypto/asn1_dsa.h
+++ b/NorthstarDLL/include/crypto/asn1_dsa.h
diff --git a/NorthstarDedicatedTest/include/crypto/asn1err.h b/NorthstarDLL/include/crypto/asn1err.h
index 6441386b..6441386b 100644
--- a/NorthstarDedicatedTest/include/crypto/asn1err.h
+++ b/NorthstarDLL/include/crypto/asn1err.h
diff --git a/NorthstarDedicatedTest/include/crypto/async.h b/NorthstarDLL/include/crypto/async.h
index 7bc0dbb6..7bc0dbb6 100644
--- a/NorthstarDedicatedTest/include/crypto/async.h
+++ b/NorthstarDLL/include/crypto/async.h
diff --git a/NorthstarDedicatedTest/include/crypto/asyncerr.h b/NorthstarDLL/include/crypto/asyncerr.h
index 574e0af7..574e0af7 100644
--- a/NorthstarDedicatedTest/include/crypto/asyncerr.h
+++ b/NorthstarDLL/include/crypto/asyncerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/bioerr.h b/NorthstarDLL/include/crypto/bioerr.h
index a0c06099..a0c06099 100644
--- a/NorthstarDedicatedTest/include/crypto/bioerr.h
+++ b/NorthstarDLL/include/crypto/bioerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/bn.h b/NorthstarDLL/include/crypto/bn.h
index cf69bea8..cf69bea8 100644
--- a/NorthstarDedicatedTest/include/crypto/bn.h
+++ b/NorthstarDLL/include/crypto/bn.h
diff --git a/NorthstarDedicatedTest/include/crypto/bn_conf.h b/NorthstarDLL/include/crypto/bn_conf.h
index a6f73d4a..a6f73d4a 100644
--- a/NorthstarDedicatedTest/include/crypto/bn_conf.h
+++ b/NorthstarDLL/include/crypto/bn_conf.h
diff --git a/NorthstarDedicatedTest/include/crypto/bn_conf.h.in b/NorthstarDLL/include/crypto/bn_conf.h.in
index dbc901b1..dbc901b1 100644
--- a/NorthstarDedicatedTest/include/crypto/bn_conf.h.in
+++ b/NorthstarDLL/include/crypto/bn_conf.h.in
diff --git a/NorthstarDedicatedTest/include/crypto/bn_dh.h b/NorthstarDLL/include/crypto/bn_dh.h
index 6d12c20e..6d12c20e 100644
--- a/NorthstarDedicatedTest/include/crypto/bn_dh.h
+++ b/NorthstarDLL/include/crypto/bn_dh.h
diff --git a/NorthstarDedicatedTest/include/crypto/bn_srp.h b/NorthstarDLL/include/crypto/bn_srp.h
index 00b160aa..00b160aa 100644
--- a/NorthstarDedicatedTest/include/crypto/bn_srp.h
+++ b/NorthstarDLL/include/crypto/bn_srp.h
diff --git a/NorthstarDedicatedTest/include/crypto/bnerr.h b/NorthstarDLL/include/crypto/bnerr.h
index 7282c915..7282c915 100644
--- a/NorthstarDedicatedTest/include/crypto/bnerr.h
+++ b/NorthstarDLL/include/crypto/bnerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/buffererr.h b/NorthstarDLL/include/crypto/buffererr.h
index 54976d95..54976d95 100644
--- a/NorthstarDedicatedTest/include/crypto/buffererr.h
+++ b/NorthstarDLL/include/crypto/buffererr.h
diff --git a/NorthstarDedicatedTest/include/crypto/chacha.h b/NorthstarDLL/include/crypto/chacha.h
index d29998ff..d29998ff 100644
--- a/NorthstarDedicatedTest/include/crypto/chacha.h
+++ b/NorthstarDLL/include/crypto/chacha.h
diff --git a/NorthstarDedicatedTest/include/crypto/cmll_platform.h b/NorthstarDLL/include/crypto/cmll_platform.h
index 8cadadf6..8cadadf6 100644
--- a/NorthstarDedicatedTest/include/crypto/cmll_platform.h
+++ b/NorthstarDLL/include/crypto/cmll_platform.h
diff --git a/NorthstarDedicatedTest/include/crypto/cmperr.h b/NorthstarDLL/include/crypto/cmperr.h
index ac61dd48..ac61dd48 100644
--- a/NorthstarDedicatedTest/include/crypto/cmperr.h
+++ b/NorthstarDLL/include/crypto/cmperr.h
diff --git a/NorthstarDedicatedTest/include/crypto/cmserr.h b/NorthstarDLL/include/crypto/cmserr.h
index 1de2f9c7..1de2f9c7 100644
--- a/NorthstarDedicatedTest/include/crypto/cmserr.h
+++ b/NorthstarDLL/include/crypto/cmserr.h
diff --git a/NorthstarDedicatedTest/include/crypto/comperr.h b/NorthstarDLL/include/crypto/comperr.h
index 0fd9c6de..0fd9c6de 100644
--- a/NorthstarDedicatedTest/include/crypto/comperr.h
+++ b/NorthstarDLL/include/crypto/comperr.h
diff --git a/NorthstarDedicatedTest/include/crypto/conferr.h b/NorthstarDLL/include/crypto/conferr.h
index cb367e4f..cb367e4f 100644
--- a/NorthstarDedicatedTest/include/crypto/conferr.h
+++ b/NorthstarDLL/include/crypto/conferr.h
diff --git a/NorthstarDedicatedTest/include/crypto/crmferr.h b/NorthstarDLL/include/crypto/crmferr.h
index f1a27e04..f1a27e04 100644
--- a/NorthstarDedicatedTest/include/crypto/crmferr.h
+++ b/NorthstarDLL/include/crypto/crmferr.h
diff --git a/NorthstarDedicatedTest/include/crypto/cryptlib.h b/NorthstarDLL/include/crypto/cryptlib.h
index 39a956bf..39a956bf 100644
--- a/NorthstarDedicatedTest/include/crypto/cryptlib.h
+++ b/NorthstarDLL/include/crypto/cryptlib.h
diff --git a/NorthstarDedicatedTest/include/crypto/cryptoerr.h b/NorthstarDLL/include/crypto/cryptoerr.h
index 288b87ac..288b87ac 100644
--- a/NorthstarDedicatedTest/include/crypto/cryptoerr.h
+++ b/NorthstarDLL/include/crypto/cryptoerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/cterr.h b/NorthstarDLL/include/crypto/cterr.h
index 760bc796..760bc796 100644
--- a/NorthstarDedicatedTest/include/crypto/cterr.h
+++ b/NorthstarDLL/include/crypto/cterr.h
diff --git a/NorthstarDedicatedTest/include/crypto/ctype.h b/NorthstarDLL/include/crypto/ctype.h
index a35c137e..a35c137e 100644
--- a/NorthstarDedicatedTest/include/crypto/ctype.h
+++ b/NorthstarDLL/include/crypto/ctype.h
diff --git a/NorthstarDedicatedTest/include/crypto/decoder.h b/NorthstarDLL/include/crypto/decoder.h
index cc06ef29..cc06ef29 100644
--- a/NorthstarDedicatedTest/include/crypto/decoder.h
+++ b/NorthstarDLL/include/crypto/decoder.h
diff --git a/NorthstarDedicatedTest/include/crypto/decodererr.h b/NorthstarDLL/include/crypto/decodererr.h
index d7badc43..d7badc43 100644
--- a/NorthstarDedicatedTest/include/crypto/decodererr.h
+++ b/NorthstarDLL/include/crypto/decodererr.h
diff --git a/NorthstarDedicatedTest/include/crypto/des_platform.h b/NorthstarDLL/include/crypto/des_platform.h
index 07ea1ddd..07ea1ddd 100644
--- a/NorthstarDedicatedTest/include/crypto/des_platform.h
+++ b/NorthstarDLL/include/crypto/des_platform.h
diff --git a/NorthstarDedicatedTest/include/crypto/dh.h b/NorthstarDLL/include/crypto/dh.h
index f6be4ae0..f6be4ae0 100644
--- a/NorthstarDedicatedTest/include/crypto/dh.h
+++ b/NorthstarDLL/include/crypto/dh.h
diff --git a/NorthstarDedicatedTest/include/crypto/dherr.h b/NorthstarDLL/include/crypto/dherr.h
index bb24d131..bb24d131 100644
--- a/NorthstarDedicatedTest/include/crypto/dherr.h
+++ b/NorthstarDLL/include/crypto/dherr.h
diff --git a/NorthstarDedicatedTest/include/crypto/dsa.h b/NorthstarDLL/include/crypto/dsa.h
index eedbd8c7..eedbd8c7 100644
--- a/NorthstarDedicatedTest/include/crypto/dsa.h
+++ b/NorthstarDLL/include/crypto/dsa.h
diff --git a/NorthstarDedicatedTest/include/crypto/dsaerr.h b/NorthstarDLL/include/crypto/dsaerr.h
index 9898097d..9898097d 100644
--- a/NorthstarDedicatedTest/include/crypto/dsaerr.h
+++ b/NorthstarDLL/include/crypto/dsaerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/dso_conf.h b/NorthstarDLL/include/crypto/dso_conf.h
index 99514321..99514321 100644
--- a/NorthstarDedicatedTest/include/crypto/dso_conf.h
+++ b/NorthstarDLL/include/crypto/dso_conf.h
diff --git a/NorthstarDedicatedTest/include/crypto/dso_conf.h.in b/NorthstarDLL/include/crypto/dso_conf.h.in
index 12de11ad..12de11ad 100644
--- a/NorthstarDedicatedTest/include/crypto/dso_conf.h.in
+++ b/NorthstarDLL/include/crypto/dso_conf.h.in
diff --git a/NorthstarDedicatedTest/include/crypto/ec.h b/NorthstarDLL/include/crypto/ec.h
index 62163b31..62163b31 100644
--- a/NorthstarDedicatedTest/include/crypto/ec.h
+++ b/NorthstarDLL/include/crypto/ec.h
diff --git a/NorthstarDedicatedTest/include/crypto/ecerr.h b/NorthstarDLL/include/crypto/ecerr.h
index 07b6c7aa..07b6c7aa 100644
--- a/NorthstarDedicatedTest/include/crypto/ecerr.h
+++ b/NorthstarDLL/include/crypto/ecerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/ecx.h b/NorthstarDLL/include/crypto/ecx.h
index 48b95fa5..48b95fa5 100644
--- a/NorthstarDedicatedTest/include/crypto/ecx.h
+++ b/NorthstarDLL/include/crypto/ecx.h
diff --git a/NorthstarDedicatedTest/include/crypto/encoder.h b/NorthstarDLL/include/crypto/encoder.h
index 09d445d2..09d445d2 100644
--- a/NorthstarDedicatedTest/include/crypto/encoder.h
+++ b/NorthstarDLL/include/crypto/encoder.h
diff --git a/NorthstarDedicatedTest/include/crypto/encodererr.h b/NorthstarDLL/include/crypto/encodererr.h
index 56c45823..56c45823 100644
--- a/NorthstarDedicatedTest/include/crypto/encodererr.h
+++ b/NorthstarDLL/include/crypto/encodererr.h
diff --git a/NorthstarDedicatedTest/include/crypto/engine.h b/NorthstarDLL/include/crypto/engine.h
index fac6ed09..fac6ed09 100644
--- a/NorthstarDedicatedTest/include/crypto/engine.h
+++ b/NorthstarDLL/include/crypto/engine.h
diff --git a/NorthstarDedicatedTest/include/crypto/engineerr.h b/NorthstarDLL/include/crypto/engineerr.h
index 737c841d..737c841d 100644
--- a/NorthstarDedicatedTest/include/crypto/engineerr.h
+++ b/NorthstarDLL/include/crypto/engineerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/err.h b/NorthstarDLL/include/crypto/err.h
index 15ec6fd0..15ec6fd0 100644
--- a/NorthstarDedicatedTest/include/crypto/err.h
+++ b/NorthstarDLL/include/crypto/err.h
diff --git a/NorthstarDedicatedTest/include/crypto/ess.h b/NorthstarDLL/include/crypto/ess.h
index 7acde5f8..7acde5f8 100644
--- a/NorthstarDedicatedTest/include/crypto/ess.h
+++ b/NorthstarDLL/include/crypto/ess.h
diff --git a/NorthstarDedicatedTest/include/crypto/esserr.h b/NorthstarDLL/include/crypto/esserr.h
index 8df2df11..8df2df11 100644
--- a/NorthstarDedicatedTest/include/crypto/esserr.h
+++ b/NorthstarDLL/include/crypto/esserr.h
diff --git a/NorthstarDedicatedTest/include/crypto/evp.h b/NorthstarDLL/include/crypto/evp.h
index c5d3a930..c5d3a930 100644
--- a/NorthstarDedicatedTest/include/crypto/evp.h
+++ b/NorthstarDLL/include/crypto/evp.h
diff --git a/NorthstarDedicatedTest/include/crypto/evperr.h b/NorthstarDLL/include/crypto/evperr.h
index d90ba83f..d90ba83f 100644
--- a/NorthstarDedicatedTest/include/crypto/evperr.h
+++ b/NorthstarDLL/include/crypto/evperr.h
diff --git a/NorthstarDedicatedTest/include/crypto/httperr.h b/NorthstarDLL/include/crypto/httperr.h
index 969df17b..969df17b 100644
--- a/NorthstarDedicatedTest/include/crypto/httperr.h
+++ b/NorthstarDLL/include/crypto/httperr.h
diff --git a/NorthstarDedicatedTest/include/crypto/lhash.h b/NorthstarDLL/include/crypto/lhash.h
index 0f64869f..0f64869f 100644
--- a/NorthstarDedicatedTest/include/crypto/lhash.h
+++ b/NorthstarDLL/include/crypto/lhash.h
diff --git a/NorthstarDedicatedTest/include/crypto/md32_common.h b/NorthstarDLL/include/crypto/md32_common.h
index 3b16f1b7..3b16f1b7 100644
--- a/NorthstarDedicatedTest/include/crypto/md32_common.h
+++ b/NorthstarDLL/include/crypto/md32_common.h
diff --git a/NorthstarDedicatedTest/include/crypto/modes.h b/NorthstarDLL/include/crypto/modes.h
index 19f9d859..19f9d859 100644
--- a/NorthstarDedicatedTest/include/crypto/modes.h
+++ b/NorthstarDLL/include/crypto/modes.h
diff --git a/NorthstarDedicatedTest/include/crypto/objects.h b/NorthstarDLL/include/crypto/objects.h
index f22e9287..f22e9287 100644
--- a/NorthstarDedicatedTest/include/crypto/objects.h
+++ b/NorthstarDLL/include/crypto/objects.h
diff --git a/NorthstarDedicatedTest/include/crypto/objectserr.h b/NorthstarDLL/include/crypto/objectserr.h
index ec994824..ec994824 100644
--- a/NorthstarDedicatedTest/include/crypto/objectserr.h
+++ b/NorthstarDLL/include/crypto/objectserr.h
diff --git a/NorthstarDedicatedTest/include/crypto/ocsperr.h b/NorthstarDLL/include/crypto/ocsperr.h
index f9529b2a..f9529b2a 100644
--- a/NorthstarDedicatedTest/include/crypto/ocsperr.h
+++ b/NorthstarDLL/include/crypto/ocsperr.h
diff --git a/NorthstarDedicatedTest/include/crypto/pem.h b/NorthstarDLL/include/crypto/pem.h
index 840dc18f..840dc18f 100644
--- a/NorthstarDedicatedTest/include/crypto/pem.h
+++ b/NorthstarDLL/include/crypto/pem.h
diff --git a/NorthstarDedicatedTest/include/crypto/pemerr.h b/NorthstarDLL/include/crypto/pemerr.h
index b255ff5c..b255ff5c 100644
--- a/NorthstarDedicatedTest/include/crypto/pemerr.h
+++ b/NorthstarDLL/include/crypto/pemerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/pkcs12err.h b/NorthstarDLL/include/crypto/pkcs12err.h
index 662f412e..662f412e 100644
--- a/NorthstarDedicatedTest/include/crypto/pkcs12err.h
+++ b/NorthstarDLL/include/crypto/pkcs12err.h
diff --git a/NorthstarDedicatedTest/include/crypto/pkcs7.h b/NorthstarDLL/include/crypto/pkcs7.h
index 9caa9af4..9caa9af4 100644
--- a/NorthstarDedicatedTest/include/crypto/pkcs7.h
+++ b/NorthstarDLL/include/crypto/pkcs7.h
diff --git a/NorthstarDedicatedTest/include/crypto/pkcs7err.h b/NorthstarDLL/include/crypto/pkcs7err.h
index c195190b..c195190b 100644
--- a/NorthstarDedicatedTest/include/crypto/pkcs7err.h
+++ b/NorthstarDLL/include/crypto/pkcs7err.h
diff --git a/NorthstarDedicatedTest/include/crypto/poly1305.h b/NorthstarDLL/include/crypto/poly1305.h
index ba54f3bd..ba54f3bd 100644
--- a/NorthstarDedicatedTest/include/crypto/poly1305.h
+++ b/NorthstarDLL/include/crypto/poly1305.h
diff --git a/NorthstarDedicatedTest/include/crypto/ppc_arch.h b/NorthstarDLL/include/crypto/ppc_arch.h
index 3b3ce4bf..3b3ce4bf 100644
--- a/NorthstarDedicatedTest/include/crypto/ppc_arch.h
+++ b/NorthstarDLL/include/crypto/ppc_arch.h
diff --git a/NorthstarDedicatedTest/include/crypto/punycode.h b/NorthstarDLL/include/crypto/punycode.h
index 133826d8..133826d8 100644
--- a/NorthstarDedicatedTest/include/crypto/punycode.h
+++ b/NorthstarDLL/include/crypto/punycode.h
diff --git a/NorthstarDedicatedTest/include/crypto/rand.h b/NorthstarDLL/include/crypto/rand.h
index fa3b5b2b..fa3b5b2b 100644
--- a/NorthstarDedicatedTest/include/crypto/rand.h
+++ b/NorthstarDLL/include/crypto/rand.h
diff --git a/NorthstarDedicatedTest/include/crypto/rand_pool.h b/NorthstarDLL/include/crypto/rand_pool.h
index f4d1d954..f4d1d954 100644
--- a/NorthstarDedicatedTest/include/crypto/rand_pool.h
+++ b/NorthstarDLL/include/crypto/rand_pool.h
diff --git a/NorthstarDedicatedTest/include/crypto/randerr.h b/NorthstarDLL/include/crypto/randerr.h
index 832a8b7d..832a8b7d 100644
--- a/NorthstarDedicatedTest/include/crypto/randerr.h
+++ b/NorthstarDLL/include/crypto/randerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/rsa.h b/NorthstarDLL/include/crypto/rsa.h
index 100e7ceb..100e7ceb 100644
--- a/NorthstarDedicatedTest/include/crypto/rsa.h
+++ b/NorthstarDLL/include/crypto/rsa.h
diff --git a/NorthstarDedicatedTest/include/crypto/rsaerr.h b/NorthstarDLL/include/crypto/rsaerr.h
index 9b23500b..9b23500b 100644
--- a/NorthstarDedicatedTest/include/crypto/rsaerr.h
+++ b/NorthstarDLL/include/crypto/rsaerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/security_bits.h b/NorthstarDLL/include/crypto/security_bits.h
index 58f49681..58f49681 100644
--- a/NorthstarDedicatedTest/include/crypto/security_bits.h
+++ b/NorthstarDLL/include/crypto/security_bits.h
diff --git a/NorthstarDedicatedTest/include/crypto/sha.h b/NorthstarDLL/include/crypto/sha.h
index 64305d17..64305d17 100644
--- a/NorthstarDedicatedTest/include/crypto/sha.h
+++ b/NorthstarDLL/include/crypto/sha.h
diff --git a/NorthstarDedicatedTest/include/crypto/siphash.h b/NorthstarDLL/include/crypto/siphash.h
index 0d0767fc..0d0767fc 100644
--- a/NorthstarDedicatedTest/include/crypto/siphash.h
+++ b/NorthstarDLL/include/crypto/siphash.h
diff --git a/NorthstarDedicatedTest/include/crypto/siv.h b/NorthstarDLL/include/crypto/siv.h
index 8dc58bd3..8dc58bd3 100644
--- a/NorthstarDedicatedTest/include/crypto/siv.h
+++ b/NorthstarDLL/include/crypto/siv.h
diff --git a/NorthstarDedicatedTest/include/crypto/sm2.h b/NorthstarDLL/include/crypto/sm2.h
index 9ab6c0b7..9ab6c0b7 100644
--- a/NorthstarDedicatedTest/include/crypto/sm2.h
+++ b/NorthstarDLL/include/crypto/sm2.h
diff --git a/NorthstarDedicatedTest/include/crypto/sm2err.h b/NorthstarDLL/include/crypto/sm2err.h
index 706f4d69..706f4d69 100644
--- a/NorthstarDedicatedTest/include/crypto/sm2err.h
+++ b/NorthstarDLL/include/crypto/sm2err.h
diff --git a/NorthstarDedicatedTest/include/crypto/sm4.h b/NorthstarDLL/include/crypto/sm4.h
index e21ec81c..e21ec81c 100644
--- a/NorthstarDedicatedTest/include/crypto/sm4.h
+++ b/NorthstarDLL/include/crypto/sm4.h
diff --git a/NorthstarDedicatedTest/include/crypto/sparc_arch.h b/NorthstarDLL/include/crypto/sparc_arch.h
index 447e715b..447e715b 100644
--- a/NorthstarDedicatedTest/include/crypto/sparc_arch.h
+++ b/NorthstarDLL/include/crypto/sparc_arch.h
diff --git a/NorthstarDedicatedTest/include/crypto/sparse_array.h b/NorthstarDLL/include/crypto/sparse_array.h
index 7ef74283..7ef74283 100644
--- a/NorthstarDedicatedTest/include/crypto/sparse_array.h
+++ b/NorthstarDLL/include/crypto/sparse_array.h
diff --git a/NorthstarDedicatedTest/include/crypto/store.h b/NorthstarDLL/include/crypto/store.h
index 13d2646b..13d2646b 100644
--- a/NorthstarDedicatedTest/include/crypto/store.h
+++ b/NorthstarDLL/include/crypto/store.h
diff --git a/NorthstarDedicatedTest/include/crypto/storeerr.h b/NorthstarDLL/include/crypto/storeerr.h
index c46d845f..c46d845f 100644
--- a/NorthstarDedicatedTest/include/crypto/storeerr.h
+++ b/NorthstarDLL/include/crypto/storeerr.h
diff --git a/NorthstarDedicatedTest/include/crypto/tserr.h b/NorthstarDLL/include/crypto/tserr.h
index 2f34ba31..2f34ba31 100644
--- a/NorthstarDedicatedTest/include/crypto/tserr.h
+++ b/NorthstarDLL/include/crypto/tserr.h
diff --git a/NorthstarDedicatedTest/include/crypto/types.h b/NorthstarDLL/include/crypto/types.h
index 0d814040..0d814040 100644
--- a/NorthstarDedicatedTest/include/crypto/types.h
+++ b/NorthstarDLL/include/crypto/types.h
diff --git a/NorthstarDedicatedTest/include/crypto/uierr.h b/NorthstarDLL/include/crypto/uierr.h
index 789077a8..789077a8 100644
--- a/NorthstarDedicatedTest/include/crypto/uierr.h
+++ b/NorthstarDLL/include/crypto/uierr.h
diff --git a/NorthstarDedicatedTest/include/crypto/x509.h b/NorthstarDLL/include/crypto/x509.h
index 1f00178e..1f00178e 100644
--- a/NorthstarDedicatedTest/include/crypto/x509.h
+++ b/NorthstarDLL/include/crypto/x509.h
diff --git a/NorthstarDedicatedTest/include/crypto/x509err.h b/NorthstarDLL/include/crypto/x509err.h
index 53f567d9..53f567d9 100644
--- a/NorthstarDedicatedTest/include/crypto/x509err.h
+++ b/NorthstarDLL/include/crypto/x509err.h
diff --git a/NorthstarDedicatedTest/include/crypto/x509v3err.h b/NorthstarDLL/include/crypto/x509v3err.h
index 66d3ad92..66d3ad92 100644
--- a/NorthstarDedicatedTest/include/crypto/x509v3err.h
+++ b/NorthstarDLL/include/crypto/x509v3err.h
diff --git a/NorthstarDedicatedTest/include/httplib.h b/NorthstarDLL/include/httplib.h
index 2b52f0fc..2b52f0fc 100644
--- a/NorthstarDedicatedTest/include/httplib.h
+++ b/NorthstarDLL/include/httplib.h
diff --git a/NorthstarDedicatedTest/include/internal/__DECC_INCLUDE_EPILOGUE.H b/NorthstarDLL/include/internal/__DECC_INCLUDE_EPILOGUE.H
index e57c0eab..e57c0eab 100644
--- a/NorthstarDedicatedTest/include/internal/__DECC_INCLUDE_EPILOGUE.H
+++ b/NorthstarDLL/include/internal/__DECC_INCLUDE_EPILOGUE.H
diff --git a/NorthstarDedicatedTest/include/internal/__DECC_INCLUDE_PROLOGUE.H b/NorthstarDLL/include/internal/__DECC_INCLUDE_PROLOGUE.H
index a0139575..a0139575 100644
--- a/NorthstarDedicatedTest/include/internal/__DECC_INCLUDE_PROLOGUE.H
+++ b/NorthstarDLL/include/internal/__DECC_INCLUDE_PROLOGUE.H
diff --git a/NorthstarDedicatedTest/include/internal/asn1.h b/NorthstarDLL/include/internal/asn1.h
index 3143e340..3143e340 100644
--- a/NorthstarDedicatedTest/include/internal/asn1.h
+++ b/NorthstarDLL/include/internal/asn1.h
diff --git a/NorthstarDedicatedTest/include/internal/bio.h b/NorthstarDLL/include/internal/bio.h
index 2d36a7b9..2d36a7b9 100644
--- a/NorthstarDedicatedTest/include/internal/bio.h
+++ b/NorthstarDLL/include/internal/bio.h
diff --git a/NorthstarDedicatedTest/include/internal/comp.h b/NorthstarDLL/include/internal/comp.h
index 3ad86fc7..3ad86fc7 100644
--- a/NorthstarDedicatedTest/include/internal/comp.h
+++ b/NorthstarDLL/include/internal/comp.h
diff --git a/NorthstarDedicatedTest/include/internal/conf.h b/NorthstarDLL/include/internal/conf.h
index 8c6c29cd..8c6c29cd 100644
--- a/NorthstarDedicatedTest/include/internal/conf.h
+++ b/NorthstarDLL/include/internal/conf.h
diff --git a/NorthstarDedicatedTest/include/internal/constant_time.h b/NorthstarDLL/include/internal/constant_time.h
index 0ed6f823..0ed6f823 100644
--- a/NorthstarDedicatedTest/include/internal/constant_time.h
+++ b/NorthstarDLL/include/internal/constant_time.h
diff --git a/NorthstarDedicatedTest/include/internal/core.h b/NorthstarDLL/include/internal/core.h
index d9dc4241..d9dc4241 100644
--- a/NorthstarDedicatedTest/include/internal/core.h
+++ b/NorthstarDLL/include/internal/core.h
diff --git a/NorthstarDedicatedTest/include/internal/cryptlib.h b/NorthstarDLL/include/internal/cryptlib.h
index 1291299b..1291299b 100644
--- a/NorthstarDedicatedTest/include/internal/cryptlib.h
+++ b/NorthstarDLL/include/internal/cryptlib.h
diff --git a/NorthstarDedicatedTest/include/internal/dane.h b/NorthstarDLL/include/internal/dane.h
index a3d78a7f..a3d78a7f 100644
--- a/NorthstarDedicatedTest/include/internal/dane.h
+++ b/NorthstarDLL/include/internal/dane.h
diff --git a/NorthstarDedicatedTest/include/internal/deprecated.h b/NorthstarDLL/include/internal/deprecated.h
index a313a015..a313a015 100644
--- a/NorthstarDedicatedTest/include/internal/deprecated.h
+++ b/NorthstarDLL/include/internal/deprecated.h
diff --git a/NorthstarDedicatedTest/include/internal/der.h b/NorthstarDLL/include/internal/der.h
index a3e56d0d..a3e56d0d 100644
--- a/NorthstarDedicatedTest/include/internal/der.h
+++ b/NorthstarDLL/include/internal/der.h
diff --git a/NorthstarDedicatedTest/include/internal/dso.h b/NorthstarDLL/include/internal/dso.h
index 160ddb98..160ddb98 100644
--- a/NorthstarDedicatedTest/include/internal/dso.h
+++ b/NorthstarDLL/include/internal/dso.h
diff --git a/NorthstarDedicatedTest/include/internal/dsoerr.h b/NorthstarDLL/include/internal/dsoerr.h
index b1719e83..b1719e83 100644
--- a/NorthstarDedicatedTest/include/internal/dsoerr.h
+++ b/NorthstarDLL/include/internal/dsoerr.h
diff --git a/NorthstarDedicatedTest/include/internal/endian.h b/NorthstarDLL/include/internal/endian.h
index 8b34e03e..8b34e03e 100644
--- a/NorthstarDedicatedTest/include/internal/endian.h
+++ b/NorthstarDLL/include/internal/endian.h
diff --git a/NorthstarDedicatedTest/include/internal/err.h b/NorthstarDLL/include/internal/err.h
index d8a308f0..d8a308f0 100644
--- a/NorthstarDedicatedTest/include/internal/err.h
+++ b/NorthstarDLL/include/internal/err.h
diff --git a/NorthstarDedicatedTest/include/internal/ffc.h b/NorthstarDLL/include/internal/ffc.h
index 79cb06ab..79cb06ab 100644
--- a/NorthstarDedicatedTest/include/internal/ffc.h
+++ b/NorthstarDLL/include/internal/ffc.h
diff --git a/NorthstarDedicatedTest/include/internal/ktls.h b/NorthstarDLL/include/internal/ktls.h
index 95492fd0..95492fd0 100644
--- a/NorthstarDedicatedTest/include/internal/ktls.h
+++ b/NorthstarDLL/include/internal/ktls.h
diff --git a/NorthstarDedicatedTest/include/internal/namemap.h b/NorthstarDLL/include/internal/namemap.h
index a4c60ae6..a4c60ae6 100644
--- a/NorthstarDedicatedTest/include/internal/namemap.h
+++ b/NorthstarDLL/include/internal/namemap.h
diff --git a/NorthstarDedicatedTest/include/internal/nelem.h b/NorthstarDLL/include/internal/nelem.h
index b758513b..b758513b 100644
--- a/NorthstarDedicatedTest/include/internal/nelem.h
+++ b/NorthstarDLL/include/internal/nelem.h
diff --git a/NorthstarDedicatedTest/include/internal/numbers.h b/NorthstarDLL/include/internal/numbers.h
index 4f4d3306..4f4d3306 100644
--- a/NorthstarDedicatedTest/include/internal/numbers.h
+++ b/NorthstarDLL/include/internal/numbers.h
diff --git a/NorthstarDedicatedTest/include/internal/o_dir.h b/NorthstarDLL/include/internal/o_dir.h
index add34d14..add34d14 100644
--- a/NorthstarDedicatedTest/include/internal/o_dir.h
+++ b/NorthstarDLL/include/internal/o_dir.h
diff --git a/NorthstarDedicatedTest/include/internal/packet.h b/NorthstarDLL/include/internal/packet.h
index 170997db..170997db 100644
--- a/NorthstarDedicatedTest/include/internal/packet.h
+++ b/NorthstarDLL/include/internal/packet.h
diff --git a/NorthstarDedicatedTest/include/internal/param_build_set.h b/NorthstarDLL/include/internal/param_build_set.h
index 126211b7..126211b7 100644
--- a/NorthstarDedicatedTest/include/internal/param_build_set.h
+++ b/NorthstarDLL/include/internal/param_build_set.h
diff --git a/NorthstarDedicatedTest/include/internal/passphrase.h b/NorthstarDLL/include/internal/passphrase.h
index 54d997b0..54d997b0 100644
--- a/NorthstarDedicatedTest/include/internal/passphrase.h
+++ b/NorthstarDLL/include/internal/passphrase.h
diff --git a/NorthstarDedicatedTest/include/internal/property.h b/NorthstarDLL/include/internal/property.h
index 82119745..82119745 100644
--- a/NorthstarDedicatedTest/include/internal/property.h
+++ b/NorthstarDLL/include/internal/property.h
diff --git a/NorthstarDedicatedTest/include/internal/propertyerr.h b/NorthstarDLL/include/internal/propertyerr.h
index fbee53f1..fbee53f1 100644
--- a/NorthstarDedicatedTest/include/internal/propertyerr.h
+++ b/NorthstarDLL/include/internal/propertyerr.h
diff --git a/NorthstarDedicatedTest/include/internal/provider.h b/NorthstarDLL/include/internal/provider.h
index d09829d0..d09829d0 100644
--- a/NorthstarDedicatedTest/include/internal/provider.h
+++ b/NorthstarDLL/include/internal/provider.h
diff --git a/NorthstarDedicatedTest/include/internal/refcount.h b/NorthstarDLL/include/internal/refcount.h
index 7412d62f..7412d62f 100644
--- a/NorthstarDedicatedTest/include/internal/refcount.h
+++ b/NorthstarDLL/include/internal/refcount.h
diff --git a/NorthstarDedicatedTest/include/internal/sha3.h b/NorthstarDLL/include/internal/sha3.h
index 80ad86e5..80ad86e5 100644
--- a/NorthstarDedicatedTest/include/internal/sha3.h
+++ b/NorthstarDLL/include/internal/sha3.h
diff --git a/NorthstarDedicatedTest/include/internal/sizes.h b/NorthstarDLL/include/internal/sizes.h
index f6496c81..f6496c81 100644
--- a/NorthstarDedicatedTest/include/internal/sizes.h
+++ b/NorthstarDLL/include/internal/sizes.h
diff --git a/NorthstarDedicatedTest/include/internal/sm3.h b/NorthstarDLL/include/internal/sm3.h
index db1d61f0..db1d61f0 100644
--- a/NorthstarDedicatedTest/include/internal/sm3.h
+++ b/NorthstarDLL/include/internal/sm3.h
diff --git a/NorthstarDedicatedTest/include/internal/sockets.h b/NorthstarDLL/include/internal/sockets.h
index 6e882fa6..6e882fa6 100644
--- a/NorthstarDedicatedTest/include/internal/sockets.h
+++ b/NorthstarDLL/include/internal/sockets.h
diff --git a/NorthstarDedicatedTest/include/internal/sslconf.h b/NorthstarDLL/include/internal/sslconf.h
index fd7f7e33..fd7f7e33 100644
--- a/NorthstarDedicatedTest/include/internal/sslconf.h
+++ b/NorthstarDLL/include/internal/sslconf.h
diff --git a/NorthstarDedicatedTest/include/internal/symhacks.h b/NorthstarDLL/include/internal/symhacks.h
index 33bae51e..33bae51e 100644
--- a/NorthstarDedicatedTest/include/internal/symhacks.h
+++ b/NorthstarDLL/include/internal/symhacks.h
diff --git a/NorthstarDedicatedTest/include/internal/thread_once.h b/NorthstarDLL/include/internal/thread_once.h
index d6cb2eee..d6cb2eee 100644
--- a/NorthstarDedicatedTest/include/internal/thread_once.h
+++ b/NorthstarDLL/include/internal/thread_once.h
diff --git a/NorthstarDedicatedTest/include/internal/tlsgroups.h b/NorthstarDLL/include/internal/tlsgroups.h
index 8a35ced1..8a35ced1 100644
--- a/NorthstarDedicatedTest/include/internal/tlsgroups.h
+++ b/NorthstarDLL/include/internal/tlsgroups.h
diff --git a/NorthstarDedicatedTest/include/internal/tsan_assist.h b/NorthstarDLL/include/internal/tsan_assist.h
index f8285b1d..f8285b1d 100644
--- a/NorthstarDedicatedTest/include/internal/tsan_assist.h
+++ b/NorthstarDLL/include/internal/tsan_assist.h
diff --git a/NorthstarDedicatedTest/include/internal/unicode.h b/NorthstarDLL/include/internal/unicode.h
index a6de8352..a6de8352 100644
--- a/NorthstarDedicatedTest/include/internal/unicode.h
+++ b/NorthstarDLL/include/internal/unicode.h
diff --git a/NorthstarDedicatedTest/include/libcrypto_static.lib b/NorthstarDLL/include/libcrypto_static.lib
index 26c68964..0ddd830c 100644
--- a/NorthstarDedicatedTest/include/libcrypto_static.lib
+++ b/NorthstarDLL/include/libcrypto_static.lib
Binary files differ
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/curl.h b/NorthstarDLL/include/libcurl/include/curl/curl.h
index 7b69ce2d..7b69ce2d 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/curl.h
+++ b/NorthstarDLL/include/libcurl/include/curl/curl.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/curlver.h b/NorthstarDLL/include/libcurl/include/curl/curlver.h
index fe57e430..fe57e430 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/curlver.h
+++ b/NorthstarDLL/include/libcurl/include/curl/curlver.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/easy.h b/NorthstarDLL/include/libcurl/include/curl/easy.h
index 2dbfb26b..2dbfb26b 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/easy.h
+++ b/NorthstarDLL/include/libcurl/include/curl/easy.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/mprintf.h b/NorthstarDLL/include/libcurl/include/curl/mprintf.h
index 3549552d..3549552d 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/mprintf.h
+++ b/NorthstarDLL/include/libcurl/include/curl/mprintf.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/multi.h b/NorthstarDLL/include/libcurl/include/curl/multi.h
index 91cd95d3..91cd95d3 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/multi.h
+++ b/NorthstarDLL/include/libcurl/include/curl/multi.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/options.h b/NorthstarDLL/include/libcurl/include/curl/options.h
index 14373b55..14373b55 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/options.h
+++ b/NorthstarDLL/include/libcurl/include/curl/options.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/stdcheaders.h b/NorthstarDLL/include/libcurl/include/curl/stdcheaders.h
index 60596c75..60596c75 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/stdcheaders.h
+++ b/NorthstarDLL/include/libcurl/include/curl/stdcheaders.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/system.h b/NorthstarDLL/include/libcurl/include/curl/system.h
index faf8fcf8..faf8fcf8 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/system.h
+++ b/NorthstarDLL/include/libcurl/include/curl/system.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/typecheck-gcc.h b/NorthstarDLL/include/libcurl/include/curl/typecheck-gcc.h
index 9e14d8a3..9e14d8a3 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/typecheck-gcc.h
+++ b/NorthstarDLL/include/libcurl/include/curl/typecheck-gcc.h
diff --git a/NorthstarDedicatedTest/include/libcurl/include/curl/urlapi.h b/NorthstarDLL/include/libcurl/include/curl/urlapi.h
index a475f91b..a475f91b 100644
--- a/NorthstarDedicatedTest/include/libcurl/include/curl/urlapi.h
+++ b/NorthstarDLL/include/libcurl/include/curl/urlapi.h
diff --git a/NorthstarDedicatedTest/include/libcurl/lib/libcurl_a.lib b/NorthstarDLL/include/libcurl/lib/libcurl_a.lib
index f0fa49f2..32b917c9 100644
--- a/NorthstarDedicatedTest/include/libcurl/lib/libcurl_a.lib
+++ b/NorthstarDLL/include/libcurl/lib/libcurl_a.lib
Binary files differ
diff --git a/NorthstarDedicatedTest/include/libssl_static.lib b/NorthstarDLL/include/libssl_static.lib
index 3411cb57..f7916421 100644
--- a/NorthstarDedicatedTest/include/libssl_static.lib
+++ b/NorthstarDLL/include/libssl_static.lib
Binary files differ
diff --git a/NorthstarDedicatedTest/include/openssl/__DECC_INCLUDE_EPILOGUE.H b/NorthstarDLL/include/openssl/__DECC_INCLUDE_EPILOGUE.H
index d251d0a0..d251d0a0 100644
--- a/NorthstarDedicatedTest/include/openssl/__DECC_INCLUDE_EPILOGUE.H
+++ b/NorthstarDLL/include/openssl/__DECC_INCLUDE_EPILOGUE.H
diff --git a/NorthstarDedicatedTest/include/openssl/__DECC_INCLUDE_PROLOGUE.H b/NorthstarDLL/include/openssl/__DECC_INCLUDE_PROLOGUE.H
index 91ac6b33..91ac6b33 100644
--- a/NorthstarDedicatedTest/include/openssl/__DECC_INCLUDE_PROLOGUE.H
+++ b/NorthstarDLL/include/openssl/__DECC_INCLUDE_PROLOGUE.H
diff --git a/NorthstarDedicatedTest/include/openssl/aes.h b/NorthstarDLL/include/openssl/aes.h
index d0f9dfc6..d0f9dfc6 100644
--- a/NorthstarDedicatedTest/include/openssl/aes.h
+++ b/NorthstarDLL/include/openssl/aes.h
diff --git a/NorthstarDedicatedTest/include/openssl/asn1.h b/NorthstarDLL/include/openssl/asn1.h
index aada23dc..aada23dc 100644
--- a/NorthstarDedicatedTest/include/openssl/asn1.h
+++ b/NorthstarDLL/include/openssl/asn1.h
diff --git a/NorthstarDedicatedTest/include/openssl/asn1.h.in b/NorthstarDLL/include/openssl/asn1.h.in
index 6d5094a3..6d5094a3 100644
--- a/NorthstarDedicatedTest/include/openssl/asn1.h.in
+++ b/NorthstarDLL/include/openssl/asn1.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/asn1_mac.h b/NorthstarDLL/include/openssl/asn1_mac.h
index fdcb9836..fdcb9836 100644
--- a/NorthstarDedicatedTest/include/openssl/asn1_mac.h
+++ b/NorthstarDLL/include/openssl/asn1_mac.h
diff --git a/NorthstarDedicatedTest/include/openssl/asn1err.h b/NorthstarDLL/include/openssl/asn1err.h
index d4276220..d4276220 100644
--- a/NorthstarDedicatedTest/include/openssl/asn1err.h
+++ b/NorthstarDLL/include/openssl/asn1err.h
diff --git a/NorthstarDedicatedTest/include/openssl/asn1t.h b/NorthstarDLL/include/openssl/asn1t.h
index a725c532..a725c532 100644
--- a/NorthstarDedicatedTest/include/openssl/asn1t.h
+++ b/NorthstarDLL/include/openssl/asn1t.h
diff --git a/NorthstarDedicatedTest/include/openssl/asn1t.h.in b/NorthstarDLL/include/openssl/asn1t.h.in
index b536fe51..b536fe51 100644
--- a/NorthstarDedicatedTest/include/openssl/asn1t.h.in
+++ b/NorthstarDLL/include/openssl/asn1t.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/async.h b/NorthstarDLL/include/openssl/async.h
index bc27d5db..bc27d5db 100644
--- a/NorthstarDedicatedTest/include/openssl/async.h
+++ b/NorthstarDLL/include/openssl/async.h
diff --git a/NorthstarDedicatedTest/include/openssl/asyncerr.h b/NorthstarDLL/include/openssl/asyncerr.h
index c093f7be..c093f7be 100644
--- a/NorthstarDedicatedTest/include/openssl/asyncerr.h
+++ b/NorthstarDLL/include/openssl/asyncerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/bio.h b/NorthstarDLL/include/openssl/bio.h
index 3ef0cafb..3ef0cafb 100644
--- a/NorthstarDedicatedTest/include/openssl/bio.h
+++ b/NorthstarDLL/include/openssl/bio.h
diff --git a/NorthstarDedicatedTest/include/openssl/bio.h.in b/NorthstarDLL/include/openssl/bio.h.in
index 2c65b7e1..2c65b7e1 100644
--- a/NorthstarDedicatedTest/include/openssl/bio.h.in
+++ b/NorthstarDLL/include/openssl/bio.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/bioerr.h b/NorthstarDLL/include/openssl/bioerr.h
index 787b30af..787b30af 100644
--- a/NorthstarDedicatedTest/include/openssl/bioerr.h
+++ b/NorthstarDLL/include/openssl/bioerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/blowfish.h b/NorthstarDLL/include/openssl/blowfish.h
index 667d6423..667d6423 100644
--- a/NorthstarDedicatedTest/include/openssl/blowfish.h
+++ b/NorthstarDLL/include/openssl/blowfish.h
diff --git a/NorthstarDedicatedTest/include/openssl/bn.h b/NorthstarDLL/include/openssl/bn.h
index ecd7f01b..ecd7f01b 100644
--- a/NorthstarDedicatedTest/include/openssl/bn.h
+++ b/NorthstarDLL/include/openssl/bn.h
diff --git a/NorthstarDedicatedTest/include/openssl/bnerr.h b/NorthstarDLL/include/openssl/bnerr.h
index 847d326b..847d326b 100644
--- a/NorthstarDedicatedTest/include/openssl/bnerr.h
+++ b/NorthstarDLL/include/openssl/bnerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/buffer.h b/NorthstarDLL/include/openssl/buffer.h
index 5773b986..5773b986 100644
--- a/NorthstarDedicatedTest/include/openssl/buffer.h
+++ b/NorthstarDLL/include/openssl/buffer.h
diff --git a/NorthstarDedicatedTest/include/openssl/buffererr.h b/NorthstarDLL/include/openssl/buffererr.h
index d18b1f8f..d18b1f8f 100644
--- a/NorthstarDedicatedTest/include/openssl/buffererr.h
+++ b/NorthstarDLL/include/openssl/buffererr.h
diff --git a/NorthstarDedicatedTest/include/openssl/camellia.h b/NorthstarDLL/include/openssl/camellia.h
index 88c2279e..88c2279e 100644
--- a/NorthstarDedicatedTest/include/openssl/camellia.h
+++ b/NorthstarDLL/include/openssl/camellia.h
diff --git a/NorthstarDedicatedTest/include/openssl/cast.h b/NorthstarDLL/include/openssl/cast.h
index 0bf217be..0bf217be 100644
--- a/NorthstarDedicatedTest/include/openssl/cast.h
+++ b/NorthstarDLL/include/openssl/cast.h
diff --git a/NorthstarDedicatedTest/include/openssl/cmac.h b/NorthstarDLL/include/openssl/cmac.h
index f5086183..f5086183 100644
--- a/NorthstarDedicatedTest/include/openssl/cmac.h
+++ b/NorthstarDLL/include/openssl/cmac.h
diff --git a/NorthstarDedicatedTest/include/openssl/cmp.h b/NorthstarDLL/include/openssl/cmp.h
index 7f258dc9..7f258dc9 100644
--- a/NorthstarDedicatedTest/include/openssl/cmp.h
+++ b/NorthstarDLL/include/openssl/cmp.h
diff --git a/NorthstarDedicatedTest/include/openssl/cmp.h.in b/NorthstarDLL/include/openssl/cmp.h.in
index b4734421..b4734421 100644
--- a/NorthstarDedicatedTest/include/openssl/cmp.h.in
+++ b/NorthstarDLL/include/openssl/cmp.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/cmp_util.h b/NorthstarDLL/include/openssl/cmp_util.h
index 9a168922..9a168922 100644
--- a/NorthstarDedicatedTest/include/openssl/cmp_util.h
+++ b/NorthstarDLL/include/openssl/cmp_util.h
diff --git a/NorthstarDedicatedTest/include/openssl/cmperr.h b/NorthstarDLL/include/openssl/cmperr.h
index 3a26fd0b..3a26fd0b 100644
--- a/NorthstarDedicatedTest/include/openssl/cmperr.h
+++ b/NorthstarDLL/include/openssl/cmperr.h
diff --git a/NorthstarDedicatedTest/include/openssl/cms.h b/NorthstarDLL/include/openssl/cms.h
index 5b907f2c..5b907f2c 100644
--- a/NorthstarDedicatedTest/include/openssl/cms.h
+++ b/NorthstarDLL/include/openssl/cms.h
diff --git a/NorthstarDedicatedTest/include/openssl/cms.h.in b/NorthstarDLL/include/openssl/cms.h.in
index da20ddf2..da20ddf2 100644
--- a/NorthstarDedicatedTest/include/openssl/cms.h.in
+++ b/NorthstarDLL/include/openssl/cms.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/cmserr.h b/NorthstarDLL/include/openssl/cmserr.h
index 1c4f4c79..1c4f4c79 100644
--- a/NorthstarDedicatedTest/include/openssl/cmserr.h
+++ b/NorthstarDLL/include/openssl/cmserr.h
diff --git a/NorthstarDedicatedTest/include/openssl/comp.h b/NorthstarDLL/include/openssl/comp.h
index 06ff5810..06ff5810 100644
--- a/NorthstarDedicatedTest/include/openssl/comp.h
+++ b/NorthstarDLL/include/openssl/comp.h
diff --git a/NorthstarDedicatedTest/include/openssl/comperr.h b/NorthstarDLL/include/openssl/comperr.h
index 01dd3e6b..01dd3e6b 100644
--- a/NorthstarDedicatedTest/include/openssl/comperr.h
+++ b/NorthstarDLL/include/openssl/comperr.h
diff --git a/NorthstarDedicatedTest/include/openssl/conf.h b/NorthstarDLL/include/openssl/conf.h
index 07793f17..07793f17 100644
--- a/NorthstarDedicatedTest/include/openssl/conf.h
+++ b/NorthstarDLL/include/openssl/conf.h
diff --git a/NorthstarDedicatedTest/include/openssl/conf.h.in b/NorthstarDLL/include/openssl/conf.h.in
index b0bd579a..b0bd579a 100644
--- a/NorthstarDedicatedTest/include/openssl/conf.h.in
+++ b/NorthstarDLL/include/openssl/conf.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/conf_api.h b/NorthstarDLL/include/openssl/conf_api.h
index ed67d577..ed67d577 100644
--- a/NorthstarDedicatedTest/include/openssl/conf_api.h
+++ b/NorthstarDLL/include/openssl/conf_api.h
diff --git a/NorthstarDedicatedTest/include/openssl/conferr.h b/NorthstarDLL/include/openssl/conferr.h
index 496e2e1e..496e2e1e 100644
--- a/NorthstarDedicatedTest/include/openssl/conferr.h
+++ b/NorthstarDLL/include/openssl/conferr.h
diff --git a/NorthstarDedicatedTest/include/openssl/configuration.h b/NorthstarDLL/include/openssl/configuration.h
index d9662edd..d9662edd 100644
--- a/NorthstarDedicatedTest/include/openssl/configuration.h
+++ b/NorthstarDLL/include/openssl/configuration.h
diff --git a/NorthstarDedicatedTest/include/openssl/configuration.h.in b/NorthstarDLL/include/openssl/configuration.h.in
index b84dc1df..b84dc1df 100644
--- a/NorthstarDedicatedTest/include/openssl/configuration.h.in
+++ b/NorthstarDLL/include/openssl/configuration.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/conftypes.h b/NorthstarDLL/include/openssl/conftypes.h
index 17cefaa4..17cefaa4 100644
--- a/NorthstarDedicatedTest/include/openssl/conftypes.h
+++ b/NorthstarDLL/include/openssl/conftypes.h
diff --git a/NorthstarDedicatedTest/include/openssl/core.h b/NorthstarDLL/include/openssl/core.h
index 9683ac70..9683ac70 100644
--- a/NorthstarDedicatedTest/include/openssl/core.h
+++ b/NorthstarDLL/include/openssl/core.h
diff --git a/NorthstarDedicatedTest/include/openssl/core_dispatch.h b/NorthstarDLL/include/openssl/core_dispatch.h
index 99fcda00..99fcda00 100644
--- a/NorthstarDedicatedTest/include/openssl/core_dispatch.h
+++ b/NorthstarDLL/include/openssl/core_dispatch.h
diff --git a/NorthstarDedicatedTest/include/openssl/core_names.h b/NorthstarDLL/include/openssl/core_names.h
index b549dae9..b549dae9 100644
--- a/NorthstarDedicatedTest/include/openssl/core_names.h
+++ b/NorthstarDLL/include/openssl/core_names.h
diff --git a/NorthstarDedicatedTest/include/openssl/core_object.h b/NorthstarDLL/include/openssl/core_object.h
index 62ccf39d..62ccf39d 100644
--- a/NorthstarDedicatedTest/include/openssl/core_object.h
+++ b/NorthstarDLL/include/openssl/core_object.h
diff --git a/NorthstarDedicatedTest/include/openssl/crmf.h b/NorthstarDLL/include/openssl/crmf.h
index b2a82edb..b2a82edb 100644
--- a/NorthstarDedicatedTest/include/openssl/crmf.h
+++ b/NorthstarDLL/include/openssl/crmf.h
diff --git a/NorthstarDedicatedTest/include/openssl/crmf.h.in b/NorthstarDLL/include/openssl/crmf.h.in
index 4d37ea6d..4d37ea6d 100644
--- a/NorthstarDedicatedTest/include/openssl/crmf.h.in
+++ b/NorthstarDLL/include/openssl/crmf.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/crmferr.h b/NorthstarDLL/include/openssl/crmferr.h
index b242b922..b242b922 100644
--- a/NorthstarDedicatedTest/include/openssl/crmferr.h
+++ b/NorthstarDLL/include/openssl/crmferr.h
diff --git a/NorthstarDedicatedTest/include/openssl/crypto.h b/NorthstarDLL/include/openssl/crypto.h
index ef327f20..ef327f20 100644
--- a/NorthstarDedicatedTest/include/openssl/crypto.h
+++ b/NorthstarDLL/include/openssl/crypto.h
diff --git a/NorthstarDedicatedTest/include/openssl/crypto.h.in b/NorthstarDLL/include/openssl/crypto.h.in
index 724e2ca5..724e2ca5 100644
--- a/NorthstarDedicatedTest/include/openssl/crypto.h.in
+++ b/NorthstarDLL/include/openssl/crypto.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/cryptoerr.h b/NorthstarDLL/include/openssl/cryptoerr.h
index c6a04d9b..c6a04d9b 100644
--- a/NorthstarDedicatedTest/include/openssl/cryptoerr.h
+++ b/NorthstarDLL/include/openssl/cryptoerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/cryptoerr_legacy.h b/NorthstarDLL/include/openssl/cryptoerr_legacy.h
index ccab33a5..ccab33a5 100644
--- a/NorthstarDedicatedTest/include/openssl/cryptoerr_legacy.h
+++ b/NorthstarDLL/include/openssl/cryptoerr_legacy.h
diff --git a/NorthstarDedicatedTest/include/openssl/ct.h b/NorthstarDLL/include/openssl/ct.h
index 06c41b70..06c41b70 100644
--- a/NorthstarDedicatedTest/include/openssl/ct.h
+++ b/NorthstarDLL/include/openssl/ct.h
diff --git a/NorthstarDedicatedTest/include/openssl/ct.h.in b/NorthstarDLL/include/openssl/ct.h.in
index 16086b33..16086b33 100644
--- a/NorthstarDedicatedTest/include/openssl/ct.h.in
+++ b/NorthstarDLL/include/openssl/ct.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/cterr.h b/NorthstarDLL/include/openssl/cterr.h
index 935d32d8..935d32d8 100644
--- a/NorthstarDedicatedTest/include/openssl/cterr.h
+++ b/NorthstarDLL/include/openssl/cterr.h
diff --git a/NorthstarDedicatedTest/include/openssl/decoder.h b/NorthstarDLL/include/openssl/decoder.h
index d4ee2cf4..d4ee2cf4 100644
--- a/NorthstarDedicatedTest/include/openssl/decoder.h
+++ b/NorthstarDLL/include/openssl/decoder.h
diff --git a/NorthstarDedicatedTest/include/openssl/decodererr.h b/NorthstarDLL/include/openssl/decodererr.h
index 4212a38b..4212a38b 100644
--- a/NorthstarDedicatedTest/include/openssl/decodererr.h
+++ b/NorthstarDLL/include/openssl/decodererr.h
diff --git a/NorthstarDedicatedTest/include/openssl/des.h b/NorthstarDLL/include/openssl/des.h
index 09798a61..09798a61 100644
--- a/NorthstarDedicatedTest/include/openssl/des.h
+++ b/NorthstarDLL/include/openssl/des.h
diff --git a/NorthstarDedicatedTest/include/openssl/dh.h b/NorthstarDLL/include/openssl/dh.h
index b97871ec..b97871ec 100644
--- a/NorthstarDedicatedTest/include/openssl/dh.h
+++ b/NorthstarDLL/include/openssl/dh.h
diff --git a/NorthstarDedicatedTest/include/openssl/dherr.h b/NorthstarDLL/include/openssl/dherr.h
index 5d2a762a..5d2a762a 100644
--- a/NorthstarDedicatedTest/include/openssl/dherr.h
+++ b/NorthstarDLL/include/openssl/dherr.h
diff --git a/NorthstarDedicatedTest/include/openssl/dsa.h b/NorthstarDLL/include/openssl/dsa.h
index 5c0e4cdd..5c0e4cdd 100644
--- a/NorthstarDedicatedTest/include/openssl/dsa.h
+++ b/NorthstarDLL/include/openssl/dsa.h
diff --git a/NorthstarDedicatedTest/include/openssl/dsaerr.h b/NorthstarDLL/include/openssl/dsaerr.h
index 5f0ca8d1..5f0ca8d1 100644
--- a/NorthstarDedicatedTest/include/openssl/dsaerr.h
+++ b/NorthstarDLL/include/openssl/dsaerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/dtls1.h b/NorthstarDLL/include/openssl/dtls1.h
index 5dc6b541..5dc6b541 100644
--- a/NorthstarDedicatedTest/include/openssl/dtls1.h
+++ b/NorthstarDLL/include/openssl/dtls1.h
diff --git a/NorthstarDedicatedTest/include/openssl/e_os2.h b/NorthstarDLL/include/openssl/e_os2.h
index 67289092..67289092 100644
--- a/NorthstarDedicatedTest/include/openssl/e_os2.h
+++ b/NorthstarDLL/include/openssl/e_os2.h
diff --git a/NorthstarDedicatedTest/include/openssl/ebcdic.h b/NorthstarDLL/include/openssl/ebcdic.h
index e0ae1aa8..e0ae1aa8 100644
--- a/NorthstarDedicatedTest/include/openssl/ebcdic.h
+++ b/NorthstarDLL/include/openssl/ebcdic.h
diff --git a/NorthstarDedicatedTest/include/openssl/ec.h b/NorthstarDLL/include/openssl/ec.h
index f59b4f92..f59b4f92 100644
--- a/NorthstarDedicatedTest/include/openssl/ec.h
+++ b/NorthstarDLL/include/openssl/ec.h
diff --git a/NorthstarDedicatedTest/include/openssl/ecdh.h b/NorthstarDLL/include/openssl/ecdh.h
index 56bd4cc2..56bd4cc2 100644
--- a/NorthstarDedicatedTest/include/openssl/ecdh.h
+++ b/NorthstarDLL/include/openssl/ecdh.h
diff --git a/NorthstarDedicatedTest/include/openssl/ecdsa.h b/NorthstarDLL/include/openssl/ecdsa.h
index 56bd4cc2..56bd4cc2 100644
--- a/NorthstarDedicatedTest/include/openssl/ecdsa.h
+++ b/NorthstarDLL/include/openssl/ecdsa.h
diff --git a/NorthstarDedicatedTest/include/openssl/ecerr.h b/NorthstarDLL/include/openssl/ecerr.h
index 49088d20..49088d20 100644
--- a/NorthstarDedicatedTest/include/openssl/ecerr.h
+++ b/NorthstarDLL/include/openssl/ecerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/encoder.h b/NorthstarDLL/include/openssl/encoder.h
index c37a6f16..c37a6f16 100644
--- a/NorthstarDedicatedTest/include/openssl/encoder.h
+++ b/NorthstarDLL/include/openssl/encoder.h
diff --git a/NorthstarDedicatedTest/include/openssl/encodererr.h b/NorthstarDLL/include/openssl/encodererr.h
index 5e318b14..5e318b14 100644
--- a/NorthstarDedicatedTest/include/openssl/encodererr.h
+++ b/NorthstarDLL/include/openssl/encodererr.h
diff --git a/NorthstarDedicatedTest/include/openssl/engine.h b/NorthstarDLL/include/openssl/engine.h
index 25c3cf7c..25c3cf7c 100644
--- a/NorthstarDedicatedTest/include/openssl/engine.h
+++ b/NorthstarDLL/include/openssl/engine.h
diff --git a/NorthstarDedicatedTest/include/openssl/engineerr.h b/NorthstarDLL/include/openssl/engineerr.h
index d439b682..d439b682 100644
--- a/NorthstarDedicatedTest/include/openssl/engineerr.h
+++ b/NorthstarDLL/include/openssl/engineerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/err.h b/NorthstarDLL/include/openssl/err.h
index 3c7299db..3c7299db 100644
--- a/NorthstarDedicatedTest/include/openssl/err.h
+++ b/NorthstarDLL/include/openssl/err.h
diff --git a/NorthstarDedicatedTest/include/openssl/err.h.in b/NorthstarDLL/include/openssl/err.h.in
index 7ca0b970..7ca0b970 100644
--- a/NorthstarDedicatedTest/include/openssl/err.h.in
+++ b/NorthstarDLL/include/openssl/err.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/ess.h b/NorthstarDLL/include/openssl/ess.h
index dad596a6..dad596a6 100644
--- a/NorthstarDedicatedTest/include/openssl/ess.h
+++ b/NorthstarDLL/include/openssl/ess.h
diff --git a/NorthstarDedicatedTest/include/openssl/ess.h.in b/NorthstarDLL/include/openssl/ess.h.in
index d1a685b9..d1a685b9 100644
--- a/NorthstarDedicatedTest/include/openssl/ess.h.in
+++ b/NorthstarDLL/include/openssl/ess.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/esserr.h b/NorthstarDLL/include/openssl/esserr.h
index 165ce7c4..165ce7c4 100644
--- a/NorthstarDedicatedTest/include/openssl/esserr.h
+++ b/NorthstarDLL/include/openssl/esserr.h
diff --git a/NorthstarDedicatedTest/include/openssl/evp.h b/NorthstarDLL/include/openssl/evp.h
index 18503817..18503817 100644
--- a/NorthstarDedicatedTest/include/openssl/evp.h
+++ b/NorthstarDLL/include/openssl/evp.h
diff --git a/NorthstarDedicatedTest/include/openssl/evperr.h b/NorthstarDLL/include/openssl/evperr.h
index a5053f6c..a5053f6c 100644
--- a/NorthstarDedicatedTest/include/openssl/evperr.h
+++ b/NorthstarDLL/include/openssl/evperr.h
diff --git a/NorthstarDedicatedTest/include/openssl/fips_names.h b/NorthstarDLL/include/openssl/fips_names.h
index 0fdf5440..0fdf5440 100644
--- a/NorthstarDedicatedTest/include/openssl/fips_names.h
+++ b/NorthstarDLL/include/openssl/fips_names.h
diff --git a/NorthstarDedicatedTest/include/openssl/fipskey.h b/NorthstarDLL/include/openssl/fipskey.h
index ccc1d2f4..ccc1d2f4 100644
--- a/NorthstarDedicatedTest/include/openssl/fipskey.h
+++ b/NorthstarDLL/include/openssl/fipskey.h
diff --git a/NorthstarDedicatedTest/include/openssl/fipskey.h.in b/NorthstarDLL/include/openssl/fipskey.h.in
index 56b947e8..56b947e8 100644
--- a/NorthstarDedicatedTest/include/openssl/fipskey.h.in
+++ b/NorthstarDLL/include/openssl/fipskey.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/hmac.h b/NorthstarDLL/include/openssl/hmac.h
index f9e1bff3..f9e1bff3 100644
--- a/NorthstarDedicatedTest/include/openssl/hmac.h
+++ b/NorthstarDLL/include/openssl/hmac.h
diff --git a/NorthstarDedicatedTest/include/openssl/http.h b/NorthstarDLL/include/openssl/http.h
index f7ab2142..f7ab2142 100644
--- a/NorthstarDedicatedTest/include/openssl/http.h
+++ b/NorthstarDLL/include/openssl/http.h
diff --git a/NorthstarDedicatedTest/include/openssl/httperr.h b/NorthstarDLL/include/openssl/httperr.h
index ee089592..ee089592 100644
--- a/NorthstarDedicatedTest/include/openssl/httperr.h
+++ b/NorthstarDLL/include/openssl/httperr.h
diff --git a/NorthstarDedicatedTest/include/openssl/idea.h b/NorthstarDLL/include/openssl/idea.h
index 1f9bb3b3..1f9bb3b3 100644
--- a/NorthstarDedicatedTest/include/openssl/idea.h
+++ b/NorthstarDLL/include/openssl/idea.h
diff --git a/NorthstarDedicatedTest/include/openssl/kdf.h b/NorthstarDLL/include/openssl/kdf.h
index 0983230a..0983230a 100644
--- a/NorthstarDedicatedTest/include/openssl/kdf.h
+++ b/NorthstarDLL/include/openssl/kdf.h
diff --git a/NorthstarDedicatedTest/include/openssl/kdferr.h b/NorthstarDLL/include/openssl/kdferr.h
index 963d766d..963d766d 100644
--- a/NorthstarDedicatedTest/include/openssl/kdferr.h
+++ b/NorthstarDLL/include/openssl/kdferr.h
diff --git a/NorthstarDedicatedTest/include/openssl/lhash.h b/NorthstarDLL/include/openssl/lhash.h
index 39dd6254..39dd6254 100644
--- a/NorthstarDedicatedTest/include/openssl/lhash.h
+++ b/NorthstarDLL/include/openssl/lhash.h
diff --git a/NorthstarDedicatedTest/include/openssl/lhash.h.in b/NorthstarDLL/include/openssl/lhash.h.in
index febefa3c..febefa3c 100644
--- a/NorthstarDedicatedTest/include/openssl/lhash.h.in
+++ b/NorthstarDLL/include/openssl/lhash.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/macros.h b/NorthstarDLL/include/openssl/macros.h
index a6bc3f1f..a6bc3f1f 100644
--- a/NorthstarDedicatedTest/include/openssl/macros.h
+++ b/NorthstarDLL/include/openssl/macros.h
diff --git a/NorthstarDedicatedTest/include/openssl/md2.h b/NorthstarDLL/include/openssl/md2.h
index 5d4cb77e..5d4cb77e 100644
--- a/NorthstarDedicatedTest/include/openssl/md2.h
+++ b/NorthstarDLL/include/openssl/md2.h
diff --git a/NorthstarDedicatedTest/include/openssl/md4.h b/NorthstarDLL/include/openssl/md4.h
index 6c150a6c..6c150a6c 100644
--- a/NorthstarDedicatedTest/include/openssl/md4.h
+++ b/NorthstarDLL/include/openssl/md4.h
diff --git a/NorthstarDedicatedTest/include/openssl/md5.h b/NorthstarDLL/include/openssl/md5.h
index 77a57734..77a57734 100644
--- a/NorthstarDedicatedTest/include/openssl/md5.h
+++ b/NorthstarDLL/include/openssl/md5.h
diff --git a/NorthstarDedicatedTest/include/openssl/mdc2.h b/NorthstarDLL/include/openssl/mdc2.h
index 5a7ee289..5a7ee289 100644
--- a/NorthstarDedicatedTest/include/openssl/mdc2.h
+++ b/NorthstarDLL/include/openssl/mdc2.h
diff --git a/NorthstarDedicatedTest/include/openssl/modes.h b/NorthstarDLL/include/openssl/modes.h
index e1907991..e1907991 100644
--- a/NorthstarDedicatedTest/include/openssl/modes.h
+++ b/NorthstarDLL/include/openssl/modes.h
diff --git a/NorthstarDedicatedTest/include/openssl/obj_mac.h b/NorthstarDLL/include/openssl/obj_mac.h
index 0e860276..0e860276 100644
--- a/NorthstarDedicatedTest/include/openssl/obj_mac.h
+++ b/NorthstarDLL/include/openssl/obj_mac.h
diff --git a/NorthstarDedicatedTest/include/openssl/objects.h b/NorthstarDLL/include/openssl/objects.h
index 9ea91c27..9ea91c27 100644
--- a/NorthstarDedicatedTest/include/openssl/objects.h
+++ b/NorthstarDLL/include/openssl/objects.h
diff --git a/NorthstarDedicatedTest/include/openssl/objectserr.h b/NorthstarDLL/include/openssl/objectserr.h
index 585217f6..585217f6 100644
--- a/NorthstarDedicatedTest/include/openssl/objectserr.h
+++ b/NorthstarDLL/include/openssl/objectserr.h
diff --git a/NorthstarDedicatedTest/include/openssl/ocsp.h b/NorthstarDLL/include/openssl/ocsp.h
index 5688381e..5688381e 100644
--- a/NorthstarDedicatedTest/include/openssl/ocsp.h
+++ b/NorthstarDLL/include/openssl/ocsp.h
diff --git a/NorthstarDedicatedTest/include/openssl/ocsp.h.in b/NorthstarDLL/include/openssl/ocsp.h.in
index e2cc2716..e2cc2716 100644
--- a/NorthstarDedicatedTest/include/openssl/ocsp.h.in
+++ b/NorthstarDLL/include/openssl/ocsp.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/ocsperr.h b/NorthstarDLL/include/openssl/ocsperr.h
index 46a0523c..46a0523c 100644
--- a/NorthstarDedicatedTest/include/openssl/ocsperr.h
+++ b/NorthstarDLL/include/openssl/ocsperr.h
diff --git a/NorthstarDedicatedTest/include/openssl/opensslconf.h b/NorthstarDLL/include/openssl/opensslconf.h
index 1e83371f..1e83371f 100644
--- a/NorthstarDedicatedTest/include/openssl/opensslconf.h
+++ b/NorthstarDLL/include/openssl/opensslconf.h
diff --git a/NorthstarDedicatedTest/include/openssl/opensslv.h b/NorthstarDLL/include/openssl/opensslv.h
index 612d5aec..612d5aec 100644
--- a/NorthstarDedicatedTest/include/openssl/opensslv.h
+++ b/NorthstarDLL/include/openssl/opensslv.h
diff --git a/NorthstarDedicatedTest/include/openssl/opensslv.h.in b/NorthstarDLL/include/openssl/opensslv.h.in
index 3f47a2ac..3f47a2ac 100644
--- a/NorthstarDedicatedTest/include/openssl/opensslv.h.in
+++ b/NorthstarDLL/include/openssl/opensslv.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/ossl_typ.h b/NorthstarDLL/include/openssl/ossl_typ.h
index 82a58988..82a58988 100644
--- a/NorthstarDedicatedTest/include/openssl/ossl_typ.h
+++ b/NorthstarDLL/include/openssl/ossl_typ.h
diff --git a/NorthstarDedicatedTest/include/openssl/param_build.h b/NorthstarDLL/include/openssl/param_build.h
index f29fdb29..f29fdb29 100644
--- a/NorthstarDedicatedTest/include/openssl/param_build.h
+++ b/NorthstarDLL/include/openssl/param_build.h
diff --git a/NorthstarDedicatedTest/include/openssl/params.h b/NorthstarDLL/include/openssl/params.h
index d75eab07..d75eab07 100644
--- a/NorthstarDedicatedTest/include/openssl/params.h
+++ b/NorthstarDLL/include/openssl/params.h
diff --git a/NorthstarDedicatedTest/include/openssl/pem.h b/NorthstarDLL/include/openssl/pem.h
index 80940dfa..80940dfa 100644
--- a/NorthstarDedicatedTest/include/openssl/pem.h
+++ b/NorthstarDLL/include/openssl/pem.h
diff --git a/NorthstarDedicatedTest/include/openssl/pem2.h b/NorthstarDLL/include/openssl/pem2.h
index a8a5325b..a8a5325b 100644
--- a/NorthstarDedicatedTest/include/openssl/pem2.h
+++ b/NorthstarDLL/include/openssl/pem2.h
diff --git a/NorthstarDedicatedTest/include/openssl/pemerr.h b/NorthstarDLL/include/openssl/pemerr.h
index 18f6d9ef..18f6d9ef 100644
--- a/NorthstarDedicatedTest/include/openssl/pemerr.h
+++ b/NorthstarDLL/include/openssl/pemerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/pkcs12.h b/NorthstarDLL/include/openssl/pkcs12.h
index f0da0867..f0da0867 100644
--- a/NorthstarDedicatedTest/include/openssl/pkcs12.h
+++ b/NorthstarDLL/include/openssl/pkcs12.h
diff --git a/NorthstarDedicatedTest/include/openssl/pkcs12.h.in b/NorthstarDLL/include/openssl/pkcs12.h.in
index c98eebfb..c98eebfb 100644
--- a/NorthstarDedicatedTest/include/openssl/pkcs12.h.in
+++ b/NorthstarDLL/include/openssl/pkcs12.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/pkcs12err.h b/NorthstarDLL/include/openssl/pkcs12err.h
index 933c8329..933c8329 100644
--- a/NorthstarDedicatedTest/include/openssl/pkcs12err.h
+++ b/NorthstarDLL/include/openssl/pkcs12err.h
diff --git a/NorthstarDedicatedTest/include/openssl/pkcs7.h b/NorthstarDLL/include/openssl/pkcs7.h
index 097d2dbb..097d2dbb 100644
--- a/NorthstarDedicatedTest/include/openssl/pkcs7.h
+++ b/NorthstarDLL/include/openssl/pkcs7.h
diff --git a/NorthstarDedicatedTest/include/openssl/pkcs7.h.in b/NorthstarDLL/include/openssl/pkcs7.h.in
index f5c55a3f..f5c55a3f 100644
--- a/NorthstarDedicatedTest/include/openssl/pkcs7.h.in
+++ b/NorthstarDLL/include/openssl/pkcs7.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/pkcs7err.h b/NorthstarDLL/include/openssl/pkcs7err.h
index ceb1a501..ceb1a501 100644
--- a/NorthstarDedicatedTest/include/openssl/pkcs7err.h
+++ b/NorthstarDLL/include/openssl/pkcs7err.h
diff --git a/NorthstarDedicatedTest/include/openssl/prov_ssl.h b/NorthstarDLL/include/openssl/prov_ssl.h
index d3e0896c..d3e0896c 100644
--- a/NorthstarDedicatedTest/include/openssl/prov_ssl.h
+++ b/NorthstarDLL/include/openssl/prov_ssl.h
diff --git a/NorthstarDedicatedTest/include/openssl/proverr.h b/NorthstarDLL/include/openssl/proverr.h
index ad67a8f8..ad67a8f8 100644
--- a/NorthstarDedicatedTest/include/openssl/proverr.h
+++ b/NorthstarDLL/include/openssl/proverr.h
diff --git a/NorthstarDedicatedTest/include/openssl/provider.h b/NorthstarDLL/include/openssl/provider.h
index dc86ff58..dc86ff58 100644
--- a/NorthstarDedicatedTest/include/openssl/provider.h
+++ b/NorthstarDLL/include/openssl/provider.h
diff --git a/NorthstarDedicatedTest/include/openssl/rand.h b/NorthstarDLL/include/openssl/rand.h
index ad3054fd..ad3054fd 100644
--- a/NorthstarDedicatedTest/include/openssl/rand.h
+++ b/NorthstarDLL/include/openssl/rand.h
diff --git a/NorthstarDedicatedTest/include/openssl/randerr.h b/NorthstarDLL/include/openssl/randerr.h
index b5e08e43..b5e08e43 100644
--- a/NorthstarDedicatedTest/include/openssl/randerr.h
+++ b/NorthstarDLL/include/openssl/randerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/rc2.h b/NorthstarDLL/include/openssl/rc2.h
index ff633fd8..ff633fd8 100644
--- a/NorthstarDedicatedTest/include/openssl/rc2.h
+++ b/NorthstarDLL/include/openssl/rc2.h
diff --git a/NorthstarDedicatedTest/include/openssl/rc4.h b/NorthstarDLL/include/openssl/rc4.h
index 600b2885..600b2885 100644
--- a/NorthstarDedicatedTest/include/openssl/rc4.h
+++ b/NorthstarDLL/include/openssl/rc4.h
diff --git a/NorthstarDedicatedTest/include/openssl/rc5.h b/NorthstarDLL/include/openssl/rc5.h
index de833523..de833523 100644
--- a/NorthstarDedicatedTest/include/openssl/rc5.h
+++ b/NorthstarDLL/include/openssl/rc5.h
diff --git a/NorthstarDedicatedTest/include/openssl/ripemd.h b/NorthstarDLL/include/openssl/ripemd.h
index 900ee317..900ee317 100644
--- a/NorthstarDedicatedTest/include/openssl/ripemd.h
+++ b/NorthstarDLL/include/openssl/ripemd.h
diff --git a/NorthstarDedicatedTest/include/openssl/rsa.h b/NorthstarDLL/include/openssl/rsa.h
index a55c9727..a55c9727 100644
--- a/NorthstarDedicatedTest/include/openssl/rsa.h
+++ b/NorthstarDLL/include/openssl/rsa.h
diff --git a/NorthstarDedicatedTest/include/openssl/rsaerr.h b/NorthstarDLL/include/openssl/rsaerr.h
index c58463c7..c58463c7 100644
--- a/NorthstarDedicatedTest/include/openssl/rsaerr.h
+++ b/NorthstarDLL/include/openssl/rsaerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/safestack.h b/NorthstarDLL/include/openssl/safestack.h
index 159ccf2a..159ccf2a 100644
--- a/NorthstarDedicatedTest/include/openssl/safestack.h
+++ b/NorthstarDLL/include/openssl/safestack.h
diff --git a/NorthstarDedicatedTest/include/openssl/safestack.h.in b/NorthstarDLL/include/openssl/safestack.h.in
index 6b366079..6b366079 100644
--- a/NorthstarDedicatedTest/include/openssl/safestack.h.in
+++ b/NorthstarDLL/include/openssl/safestack.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/seed.h b/NorthstarDLL/include/openssl/seed.h
index edb218ae..edb218ae 100644
--- a/NorthstarDedicatedTest/include/openssl/seed.h
+++ b/NorthstarDLL/include/openssl/seed.h
diff --git a/NorthstarDedicatedTest/include/openssl/self_test.h b/NorthstarDLL/include/openssl/self_test.h
index 77c600a0..77c600a0 100644
--- a/NorthstarDedicatedTest/include/openssl/self_test.h
+++ b/NorthstarDLL/include/openssl/self_test.h
diff --git a/NorthstarDedicatedTest/include/openssl/sha.h b/NorthstarDLL/include/openssl/sha.h
index 6e65a040..6e65a040 100644
--- a/NorthstarDedicatedTest/include/openssl/sha.h
+++ b/NorthstarDLL/include/openssl/sha.h
diff --git a/NorthstarDedicatedTest/include/openssl/srp.h b/NorthstarDLL/include/openssl/srp.h
index a86fa5d2..a86fa5d2 100644
--- a/NorthstarDedicatedTest/include/openssl/srp.h
+++ b/NorthstarDLL/include/openssl/srp.h
diff --git a/NorthstarDedicatedTest/include/openssl/srp.h.in b/NorthstarDLL/include/openssl/srp.h.in
index dfbe845b..dfbe845b 100644
--- a/NorthstarDedicatedTest/include/openssl/srp.h.in
+++ b/NorthstarDLL/include/openssl/srp.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/srtp.h b/NorthstarDLL/include/openssl/srtp.h
index d64606e5..d64606e5 100644
--- a/NorthstarDedicatedTest/include/openssl/srtp.h
+++ b/NorthstarDLL/include/openssl/srtp.h
diff --git a/NorthstarDedicatedTest/include/openssl/ssl.h b/NorthstarDLL/include/openssl/ssl.h
index 0763a33c..0763a33c 100644
--- a/NorthstarDedicatedTest/include/openssl/ssl.h
+++ b/NorthstarDLL/include/openssl/ssl.h
diff --git a/NorthstarDedicatedTest/include/openssl/ssl.h.in b/NorthstarDLL/include/openssl/ssl.h.in
index 9c00eb3d..9c00eb3d 100644
--- a/NorthstarDedicatedTest/include/openssl/ssl.h.in
+++ b/NorthstarDLL/include/openssl/ssl.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/ssl2.h b/NorthstarDLL/include/openssl/ssl2.h
index 428ead05..428ead05 100644
--- a/NorthstarDedicatedTest/include/openssl/ssl2.h
+++ b/NorthstarDLL/include/openssl/ssl2.h
diff --git a/NorthstarDedicatedTest/include/openssl/ssl3.h b/NorthstarDLL/include/openssl/ssl3.h
index 49bd51f2..49bd51f2 100644
--- a/NorthstarDedicatedTest/include/openssl/ssl3.h
+++ b/NorthstarDLL/include/openssl/ssl3.h
diff --git a/NorthstarDedicatedTest/include/openssl/sslerr.h b/NorthstarDLL/include/openssl/sslerr.h
index a4746d70..a4746d70 100644
--- a/NorthstarDedicatedTest/include/openssl/sslerr.h
+++ b/NorthstarDLL/include/openssl/sslerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/sslerr_legacy.h b/NorthstarDLL/include/openssl/sslerr_legacy.h
index ccf6d3b3..ccf6d3b3 100644
--- a/NorthstarDedicatedTest/include/openssl/sslerr_legacy.h
+++ b/NorthstarDLL/include/openssl/sslerr_legacy.h
diff --git a/NorthstarDedicatedTest/include/openssl/stack.h b/NorthstarDLL/include/openssl/stack.h
index f0c5c547..f0c5c547 100644
--- a/NorthstarDedicatedTest/include/openssl/stack.h
+++ b/NorthstarDLL/include/openssl/stack.h
diff --git a/NorthstarDedicatedTest/include/openssl/store.h b/NorthstarDLL/include/openssl/store.h
index 3c1445e0..3c1445e0 100644
--- a/NorthstarDedicatedTest/include/openssl/store.h
+++ b/NorthstarDLL/include/openssl/store.h
diff --git a/NorthstarDedicatedTest/include/openssl/storeerr.h b/NorthstarDLL/include/openssl/storeerr.h
index 00529c88..00529c88 100644
--- a/NorthstarDedicatedTest/include/openssl/storeerr.h
+++ b/NorthstarDLL/include/openssl/storeerr.h
diff --git a/NorthstarDedicatedTest/include/openssl/symhacks.h b/NorthstarDLL/include/openssl/symhacks.h
index 816f8f99..816f8f99 100644
--- a/NorthstarDedicatedTest/include/openssl/symhacks.h
+++ b/NorthstarDLL/include/openssl/symhacks.h
diff --git a/NorthstarDedicatedTest/include/openssl/tls1.h b/NorthstarDLL/include/openssl/tls1.h
index d6e9331f..d6e9331f 100644
--- a/NorthstarDedicatedTest/include/openssl/tls1.h
+++ b/NorthstarDLL/include/openssl/tls1.h
diff --git a/NorthstarDedicatedTest/include/openssl/trace.h b/NorthstarDLL/include/openssl/trace.h
index 28200133..28200133 100644
--- a/NorthstarDedicatedTest/include/openssl/trace.h
+++ b/NorthstarDLL/include/openssl/trace.h
diff --git a/NorthstarDedicatedTest/include/openssl/ts.h b/NorthstarDLL/include/openssl/ts.h
index 5136e4e9..5136e4e9 100644
--- a/NorthstarDedicatedTest/include/openssl/ts.h
+++ b/NorthstarDLL/include/openssl/ts.h
diff --git a/NorthstarDedicatedTest/include/openssl/tserr.h b/NorthstarDLL/include/openssl/tserr.h
index e1b943e4..e1b943e4 100644
--- a/NorthstarDedicatedTest/include/openssl/tserr.h
+++ b/NorthstarDLL/include/openssl/tserr.h
diff --git a/NorthstarDedicatedTest/include/openssl/txt_db.h b/NorthstarDLL/include/openssl/txt_db.h
index af169a30..af169a30 100644
--- a/NorthstarDedicatedTest/include/openssl/txt_db.h
+++ b/NorthstarDLL/include/openssl/txt_db.h
diff --git a/NorthstarDedicatedTest/include/openssl/types.h b/NorthstarDLL/include/openssl/types.h
index de9f1665..de9f1665 100644
--- a/NorthstarDedicatedTest/include/openssl/types.h
+++ b/NorthstarDLL/include/openssl/types.h
diff --git a/NorthstarDedicatedTest/include/openssl/ui.h b/NorthstarDLL/include/openssl/ui.h
index 835b0eba..835b0eba 100644
--- a/NorthstarDedicatedTest/include/openssl/ui.h
+++ b/NorthstarDLL/include/openssl/ui.h
diff --git a/NorthstarDedicatedTest/include/openssl/ui.h.in b/NorthstarDLL/include/openssl/ui.h.in
index eb9a580f..eb9a580f 100644
--- a/NorthstarDedicatedTest/include/openssl/ui.h.in
+++ b/NorthstarDLL/include/openssl/ui.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/uierr.h b/NorthstarDLL/include/openssl/uierr.h
index 473b04ed..473b04ed 100644
--- a/NorthstarDedicatedTest/include/openssl/uierr.h
+++ b/NorthstarDLL/include/openssl/uierr.h
diff --git a/NorthstarDedicatedTest/include/openssl/whrlpool.h b/NorthstarDLL/include/openssl/whrlpool.h
index 05ba4632..05ba4632 100644
--- a/NorthstarDedicatedTest/include/openssl/whrlpool.h
+++ b/NorthstarDLL/include/openssl/whrlpool.h
diff --git a/NorthstarDedicatedTest/include/openssl/x509.h b/NorthstarDLL/include/openssl/x509.h
index db57a9bf..db57a9bf 100644
--- a/NorthstarDedicatedTest/include/openssl/x509.h
+++ b/NorthstarDLL/include/openssl/x509.h
diff --git a/NorthstarDedicatedTest/include/openssl/x509.h.in b/NorthstarDLL/include/openssl/x509.h.in
index b4efbb55..b4efbb55 100644
--- a/NorthstarDedicatedTest/include/openssl/x509.h.in
+++ b/NorthstarDLL/include/openssl/x509.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/x509_vfy.h b/NorthstarDLL/include/openssl/x509_vfy.h
index e04df0d3..e04df0d3 100644
--- a/NorthstarDedicatedTest/include/openssl/x509_vfy.h
+++ b/NorthstarDLL/include/openssl/x509_vfy.h
diff --git a/NorthstarDedicatedTest/include/openssl/x509_vfy.h.in b/NorthstarDLL/include/openssl/x509_vfy.h.in
index 80f18bd7..80f18bd7 100644
--- a/NorthstarDedicatedTest/include/openssl/x509_vfy.h.in
+++ b/NorthstarDLL/include/openssl/x509_vfy.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/x509err.h b/NorthstarDLL/include/openssl/x509err.h
index a56facd4..a56facd4 100644
--- a/NorthstarDedicatedTest/include/openssl/x509err.h
+++ b/NorthstarDLL/include/openssl/x509err.h
diff --git a/NorthstarDedicatedTest/include/openssl/x509v3.h b/NorthstarDLL/include/openssl/x509v3.h
index 78c390b3..78c390b3 100644
--- a/NorthstarDedicatedTest/include/openssl/x509v3.h
+++ b/NorthstarDLL/include/openssl/x509v3.h
diff --git a/NorthstarDedicatedTest/include/openssl/x509v3.h.in b/NorthstarDLL/include/openssl/x509v3.h.in
index d00a66a3..d00a66a3 100644
--- a/NorthstarDedicatedTest/include/openssl/x509v3.h.in
+++ b/NorthstarDLL/include/openssl/x509v3.h.in
diff --git a/NorthstarDedicatedTest/include/openssl/x509v3err.h b/NorthstarDLL/include/openssl/x509v3err.h
index 1ae3a562..1ae3a562 100644
--- a/NorthstarDedicatedTest/include/openssl/x509v3err.h
+++ b/NorthstarDLL/include/openssl/x509v3err.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/allocators.h b/NorthstarDLL/include/rapidjson/allocators.h
index 98affe03..98affe03 100644
--- a/NorthstarDedicatedTest/include/rapidjson/allocators.h
+++ b/NorthstarDLL/include/rapidjson/allocators.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/document.h b/NorthstarDLL/include/rapidjson/document.h
index e3e20dfb..e3e20dfb 100644
--- a/NorthstarDedicatedTest/include/rapidjson/document.h
+++ b/NorthstarDLL/include/rapidjson/document.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/encodedstream.h b/NorthstarDLL/include/rapidjson/encodedstream.h
index 14506838..14506838 100644
--- a/NorthstarDedicatedTest/include/rapidjson/encodedstream.h
+++ b/NorthstarDLL/include/rapidjson/encodedstream.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/encodings.h b/NorthstarDLL/include/rapidjson/encodings.h
index baa7c2b1..baa7c2b1 100644
--- a/NorthstarDedicatedTest/include/rapidjson/encodings.h
+++ b/NorthstarDLL/include/rapidjson/encodings.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/error/en.h b/NorthstarDLL/include/rapidjson/error/en.h
index 2db838bf..2db838bf 100644
--- a/NorthstarDedicatedTest/include/rapidjson/error/en.h
+++ b/NorthstarDLL/include/rapidjson/error/en.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/error/error.h b/NorthstarDLL/include/rapidjson/error/error.h
index 95cb31a7..95cb31a7 100644
--- a/NorthstarDedicatedTest/include/rapidjson/error/error.h
+++ b/NorthstarDLL/include/rapidjson/error/error.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/filereadstream.h b/NorthstarDLL/include/rapidjson/filereadstream.h
index b56ea13b..b56ea13b 100644
--- a/NorthstarDedicatedTest/include/rapidjson/filereadstream.h
+++ b/NorthstarDLL/include/rapidjson/filereadstream.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/filewritestream.h b/NorthstarDLL/include/rapidjson/filewritestream.h
index 6378dd60..6378dd60 100644
--- a/NorthstarDedicatedTest/include/rapidjson/filewritestream.h
+++ b/NorthstarDLL/include/rapidjson/filewritestream.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/fwd.h b/NorthstarDLL/include/rapidjson/fwd.h
index e8104e84..e8104e84 100644
--- a/NorthstarDedicatedTest/include/rapidjson/fwd.h
+++ b/NorthstarDLL/include/rapidjson/fwd.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/biginteger.h b/NorthstarDLL/include/rapidjson/internal/biginteger.h
index 9d3e88c9..9d3e88c9 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/biginteger.h
+++ b/NorthstarDLL/include/rapidjson/internal/biginteger.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/diyfp.h b/NorthstarDLL/include/rapidjson/internal/diyfp.h
index c9fefdc6..c9fefdc6 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/diyfp.h
+++ b/NorthstarDLL/include/rapidjson/internal/diyfp.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/dtoa.h b/NorthstarDLL/include/rapidjson/internal/dtoa.h
index 8d6350e6..8d6350e6 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/dtoa.h
+++ b/NorthstarDLL/include/rapidjson/internal/dtoa.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/ieee754.h b/NorthstarDLL/include/rapidjson/internal/ieee754.h
index 82bb0b99..82bb0b99 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/ieee754.h
+++ b/NorthstarDLL/include/rapidjson/internal/ieee754.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/itoa.h b/NorthstarDLL/include/rapidjson/internal/itoa.h
index 01a4e7e7..01a4e7e7 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/itoa.h
+++ b/NorthstarDLL/include/rapidjson/internal/itoa.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/meta.h b/NorthstarDLL/include/rapidjson/internal/meta.h
index 5a9aaa42..5a9aaa42 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/meta.h
+++ b/NorthstarDLL/include/rapidjson/internal/meta.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/pow10.h b/NorthstarDLL/include/rapidjson/internal/pow10.h
index 02f475d7..02f475d7 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/pow10.h
+++ b/NorthstarDLL/include/rapidjson/internal/pow10.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/regex.h b/NorthstarDLL/include/rapidjson/internal/regex.h
index 422a5240..422a5240 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/regex.h
+++ b/NorthstarDLL/include/rapidjson/internal/regex.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/stack.h b/NorthstarDLL/include/rapidjson/internal/stack.h
index 022c9aab..022c9aab 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/stack.h
+++ b/NorthstarDLL/include/rapidjson/internal/stack.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/strfunc.h b/NorthstarDLL/include/rapidjson/internal/strfunc.h
index 2edfae52..2edfae52 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/strfunc.h
+++ b/NorthstarDLL/include/rapidjson/internal/strfunc.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/strtod.h b/NorthstarDLL/include/rapidjson/internal/strtod.h
index 289c413b..289c413b 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/strtod.h
+++ b/NorthstarDLL/include/rapidjson/internal/strtod.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/internal/swap.h b/NorthstarDLL/include/rapidjson/internal/swap.h
index 666e49f9..666e49f9 100644
--- a/NorthstarDedicatedTest/include/rapidjson/internal/swap.h
+++ b/NorthstarDLL/include/rapidjson/internal/swap.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/istreamwrapper.h b/NorthstarDLL/include/rapidjson/istreamwrapper.h
index f5fe2897..f5fe2897 100644
--- a/NorthstarDedicatedTest/include/rapidjson/istreamwrapper.h
+++ b/NorthstarDLL/include/rapidjson/istreamwrapper.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/memorybuffer.h b/NorthstarDLL/include/rapidjson/memorybuffer.h
index 39bee1de..39bee1de 100644
--- a/NorthstarDedicatedTest/include/rapidjson/memorybuffer.h
+++ b/NorthstarDLL/include/rapidjson/memorybuffer.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/memorystream.h b/NorthstarDLL/include/rapidjson/memorystream.h
index 1d71d8a4..1d71d8a4 100644
--- a/NorthstarDedicatedTest/include/rapidjson/memorystream.h
+++ b/NorthstarDLL/include/rapidjson/memorystream.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/msinttypes/inttypes.h b/NorthstarDLL/include/rapidjson/msinttypes/inttypes.h
index 18111286..18111286 100644
--- a/NorthstarDedicatedTest/include/rapidjson/msinttypes/inttypes.h
+++ b/NorthstarDLL/include/rapidjson/msinttypes/inttypes.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/msinttypes/stdint.h b/NorthstarDLL/include/rapidjson/msinttypes/stdint.h
index 3d4477b9..3d4477b9 100644
--- a/NorthstarDedicatedTest/include/rapidjson/msinttypes/stdint.h
+++ b/NorthstarDLL/include/rapidjson/msinttypes/stdint.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/ostreamwrapper.h b/NorthstarDLL/include/rapidjson/ostreamwrapper.h
index 6f4667c0..6f4667c0 100644
--- a/NorthstarDedicatedTest/include/rapidjson/ostreamwrapper.h
+++ b/NorthstarDLL/include/rapidjson/ostreamwrapper.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/pointer.h b/NorthstarDLL/include/rapidjson/pointer.h
index 0206ac1c..0206ac1c 100644
--- a/NorthstarDedicatedTest/include/rapidjson/pointer.h
+++ b/NorthstarDLL/include/rapidjson/pointer.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/prettywriter.h b/NorthstarDLL/include/rapidjson/prettywriter.h
index 0dcb0fee..0dcb0fee 100644
--- a/NorthstarDedicatedTest/include/rapidjson/prettywriter.h
+++ b/NorthstarDLL/include/rapidjson/prettywriter.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/rapidjson.h b/NorthstarDLL/include/rapidjson/rapidjson.h
index 053b2ce4..053b2ce4 100644
--- a/NorthstarDedicatedTest/include/rapidjson/rapidjson.h
+++ b/NorthstarDLL/include/rapidjson/rapidjson.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/reader.h b/NorthstarDLL/include/rapidjson/reader.h
index 19f8849b..19f8849b 100644
--- a/NorthstarDedicatedTest/include/rapidjson/reader.h
+++ b/NorthstarDLL/include/rapidjson/reader.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/schema.h b/NorthstarDLL/include/rapidjson/schema.h
index b182aa27..b182aa27 100644
--- a/NorthstarDedicatedTest/include/rapidjson/schema.h
+++ b/NorthstarDLL/include/rapidjson/schema.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/stream.h b/NorthstarDLL/include/rapidjson/stream.h
index fef82c25..fef82c25 100644
--- a/NorthstarDedicatedTest/include/rapidjson/stream.h
+++ b/NorthstarDLL/include/rapidjson/stream.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/stringbuffer.h b/NorthstarDLL/include/rapidjson/stringbuffer.h
index 78f34d20..78f34d20 100644
--- a/NorthstarDedicatedTest/include/rapidjson/stringbuffer.h
+++ b/NorthstarDLL/include/rapidjson/stringbuffer.h
diff --git a/NorthstarDedicatedTest/include/rapidjson/writer.h b/NorthstarDLL/include/rapidjson/writer.h
index 94f22dd5..94f22dd5 100644
--- a/NorthstarDedicatedTest/include/rapidjson/writer.h
+++ b/NorthstarDLL/include/rapidjson/writer.h
diff --git a/NorthstarDedicatedTest/include/spdlog/async.h b/NorthstarDLL/include/spdlog/async.h
index f7956305..f7956305 100644
--- a/NorthstarDedicatedTest/include/spdlog/async.h
+++ b/NorthstarDLL/include/spdlog/async.h
diff --git a/NorthstarDedicatedTest/include/spdlog/async_logger-inl.h b/NorthstarDLL/include/spdlog/async_logger-inl.h
index f8c9694c..f8c9694c 100644
--- a/NorthstarDedicatedTest/include/spdlog/async_logger-inl.h
+++ b/NorthstarDLL/include/spdlog/async_logger-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/async_logger.h b/NorthstarDLL/include/spdlog/async_logger.h
index 6f299672..6f299672 100644
--- a/NorthstarDedicatedTest/include/spdlog/async_logger.h
+++ b/NorthstarDLL/include/spdlog/async_logger.h
diff --git a/NorthstarDedicatedTest/include/spdlog/cfg/argv.h b/NorthstarDLL/include/spdlog/cfg/argv.h
index 36d9f1c4..36d9f1c4 100644
--- a/NorthstarDedicatedTest/include/spdlog/cfg/argv.h
+++ b/NorthstarDLL/include/spdlog/cfg/argv.h
diff --git a/NorthstarDedicatedTest/include/spdlog/cfg/env.h b/NorthstarDLL/include/spdlog/cfg/env.h
index 1f39ebbb..1f39ebbb 100644
--- a/NorthstarDedicatedTest/include/spdlog/cfg/env.h
+++ b/NorthstarDLL/include/spdlog/cfg/env.h
diff --git a/NorthstarDedicatedTest/include/spdlog/cfg/helpers-inl.h b/NorthstarDLL/include/spdlog/cfg/helpers-inl.h
index 9e4daede..9e4daede 100644
--- a/NorthstarDedicatedTest/include/spdlog/cfg/helpers-inl.h
+++ b/NorthstarDLL/include/spdlog/cfg/helpers-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/cfg/helpers.h b/NorthstarDLL/include/spdlog/cfg/helpers.h
index a795f39a..a795f39a 100644
--- a/NorthstarDedicatedTest/include/spdlog/cfg/helpers.h
+++ b/NorthstarDLL/include/spdlog/cfg/helpers.h
diff --git a/NorthstarDedicatedTest/include/spdlog/common-inl.h b/NorthstarDLL/include/spdlog/common-inl.h
index 378efe60..378efe60 100644
--- a/NorthstarDedicatedTest/include/spdlog/common-inl.h
+++ b/NorthstarDLL/include/spdlog/common-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/common.h b/NorthstarDLL/include/spdlog/common.h
index fb9a3660..fb9a3660 100644
--- a/NorthstarDedicatedTest/include/spdlog/common.h
+++ b/NorthstarDLL/include/spdlog/common.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/backtracer-inl.h b/NorthstarDLL/include/spdlog/details/backtracer-inl.h
index 21553c26..21553c26 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/backtracer-inl.h
+++ b/NorthstarDLL/include/spdlog/details/backtracer-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/backtracer.h b/NorthstarDLL/include/spdlog/details/backtracer.h
index b7476bc9..1da5d4c7 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/backtracer.h
+++ b/NorthstarDLL/include/spdlog/details/backtracer.h
@@ -42,4 +42,4 @@ public:
#ifdef SPDLOG_HEADER_ONLY
#include "backtracer-inl.h"
-#endif \ No newline at end of file
+#endif
diff --git a/NorthstarDedicatedTest/include/spdlog/details/circular_q.h b/NorthstarDLL/include/spdlog/details/circular_q.h
index 1f2712e7..1f2712e7 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/circular_q.h
+++ b/NorthstarDLL/include/spdlog/details/circular_q.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/console_globals.h b/NorthstarDLL/include/spdlog/details/console_globals.h
index 665201dd..665201dd 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/console_globals.h
+++ b/NorthstarDLL/include/spdlog/details/console_globals.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/file_helper-inl.h b/NorthstarDLL/include/spdlog/details/file_helper-inl.h
index 30f3cf55..30f3cf55 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/file_helper-inl.h
+++ b/NorthstarDLL/include/spdlog/details/file_helper-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/file_helper.h b/NorthstarDLL/include/spdlog/details/file_helper.h
index 5395d9cb..5395d9cb 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/file_helper.h
+++ b/NorthstarDLL/include/spdlog/details/file_helper.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/fmt_helper.h b/NorthstarDLL/include/spdlog/details/fmt_helper.h
index 5dc311a0..5dc311a0 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/fmt_helper.h
+++ b/NorthstarDLL/include/spdlog/details/fmt_helper.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/log_msg-inl.h b/NorthstarDLL/include/spdlog/details/log_msg-inl.h
index af11e0da..af11e0da 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/log_msg-inl.h
+++ b/NorthstarDLL/include/spdlog/details/log_msg-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/log_msg.h b/NorthstarDLL/include/spdlog/details/log_msg.h
index 834ca4df..834ca4df 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/log_msg.h
+++ b/NorthstarDLL/include/spdlog/details/log_msg.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/log_msg_buffer-inl.h b/NorthstarDLL/include/spdlog/details/log_msg_buffer-inl.h
index ca9429bb..ca9429bb 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/log_msg_buffer-inl.h
+++ b/NorthstarDLL/include/spdlog/details/log_msg_buffer-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/log_msg_buffer.h b/NorthstarDLL/include/spdlog/details/log_msg_buffer.h
index 4410110f..4410110f 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/log_msg_buffer.h
+++ b/NorthstarDLL/include/spdlog/details/log_msg_buffer.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/mpmc_blocking_q.h b/NorthstarDLL/include/spdlog/details/mpmc_blocking_q.h
index 5c3cca76..5c3cca76 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/mpmc_blocking_q.h
+++ b/NorthstarDLL/include/spdlog/details/mpmc_blocking_q.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/null_mutex.h b/NorthstarDLL/include/spdlog/details/null_mutex.h
index 83533d4f..83533d4f 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/null_mutex.h
+++ b/NorthstarDLL/include/spdlog/details/null_mutex.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/os-inl.h b/NorthstarDLL/include/spdlog/details/os-inl.h
index a701e13f..a701e13f 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/os-inl.h
+++ b/NorthstarDLL/include/spdlog/details/os-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/os.h b/NorthstarDLL/include/spdlog/details/os.h
index 9fda1447..9fda1447 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/os.h
+++ b/NorthstarDLL/include/spdlog/details/os.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/periodic_worker-inl.h b/NorthstarDLL/include/spdlog/details/periodic_worker-inl.h
index 1d794994..1d794994 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/periodic_worker-inl.h
+++ b/NorthstarDLL/include/spdlog/details/periodic_worker-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/periodic_worker.h b/NorthstarDLL/include/spdlog/details/periodic_worker.h
index 42373665..42373665 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/periodic_worker.h
+++ b/NorthstarDLL/include/spdlog/details/periodic_worker.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/registry-inl.h b/NorthstarDLL/include/spdlog/details/registry-inl.h
index a60faabc..a60faabc 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/registry-inl.h
+++ b/NorthstarDLL/include/spdlog/details/registry-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/registry.h b/NorthstarDLL/include/spdlog/details/registry.h
index b069c3f5..b069c3f5 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/registry.h
+++ b/NorthstarDLL/include/spdlog/details/registry.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/synchronous_factory.h b/NorthstarDLL/include/spdlog/details/synchronous_factory.h
index b48f5932..e1e42268 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/synchronous_factory.h
+++ b/NorthstarDLL/include/spdlog/details/synchronous_factory.h
@@ -21,4 +21,4 @@ struct synchronous_factory
return new_logger;
}
};
-} // namespace spdlog \ No newline at end of file
+} // namespace spdlog
diff --git a/NorthstarDedicatedTest/include/spdlog/details/tcp_client-windows.h b/NorthstarDLL/include/spdlog/details/tcp_client-windows.h
index 7ee72927..7ee72927 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/tcp_client-windows.h
+++ b/NorthstarDLL/include/spdlog/details/tcp_client-windows.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/tcp_client.h b/NorthstarDLL/include/spdlog/details/tcp_client.h
index 9f3bb99e..9f3bb99e 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/tcp_client.h
+++ b/NorthstarDLL/include/spdlog/details/tcp_client.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/thread_pool-inl.h b/NorthstarDLL/include/spdlog/details/thread_pool-inl.h
index c1df4361..c1df4361 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/thread_pool-inl.h
+++ b/NorthstarDLL/include/spdlog/details/thread_pool-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/thread_pool.h b/NorthstarDLL/include/spdlog/details/thread_pool.h
index 61e25252..61e25252 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/thread_pool.h
+++ b/NorthstarDLL/include/spdlog/details/thread_pool.h
diff --git a/NorthstarDedicatedTest/include/spdlog/details/windows_include.h b/NorthstarDLL/include/spdlog/details/windows_include.h
index 6a2f14f9..6a2f14f9 100644
--- a/NorthstarDedicatedTest/include/spdlog/details/windows_include.h
+++ b/NorthstarDLL/include/spdlog/details/windows_include.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bin_to_hex.h b/NorthstarDLL/include/spdlog/fmt/bin_to_hex.h
index 1e2b054b..1e2b054b 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bin_to_hex.h
+++ b/NorthstarDLL/include/spdlog/fmt/bin_to_hex.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/LICENSE.rst b/NorthstarDLL/include/spdlog/fmt/bundled/LICENSE.rst
index f0ec3db4..f0ec3db4 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/LICENSE.rst
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/LICENSE.rst
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/chrono.h b/NorthstarDLL/include/spdlog/fmt/bundled/chrono.h
index bdfe2aa0..bdfe2aa0 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/chrono.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/chrono.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/color.h b/NorthstarDLL/include/spdlog/fmt/bundled/color.h
index 94e3419d..94e3419d 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/color.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/color.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/compile.h b/NorthstarDLL/include/spdlog/fmt/bundled/compile.h
index 3a33b020..3a33b020 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/compile.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/compile.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/core.h b/NorthstarDLL/include/spdlog/fmt/bundled/core.h
index 0a81e0cc..0a81e0cc 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/core.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/core.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/format-inl.h b/NorthstarDLL/include/spdlog/fmt/bundled/format-inl.h
index 8f2fe735..8f2fe735 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/format-inl.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/format-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/format.h b/NorthstarDLL/include/spdlog/fmt/bundled/format.h
index 1a037b02..1a037b02 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/format.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/format.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/locale.h b/NorthstarDLL/include/spdlog/fmt/bundled/locale.h
index 7301bf92..7301bf92 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/locale.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/locale.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/os.h b/NorthstarDLL/include/spdlog/fmt/bundled/os.h
index d44ea0c9..d44ea0c9 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/os.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/os.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/ostream.h b/NorthstarDLL/include/spdlog/fmt/bundled/ostream.h
index 29c58ec1..29c58ec1 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/ostream.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/ostream.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/posix.h b/NorthstarDLL/include/spdlog/fmt/bundled/posix.h
index da19e9d5..da19e9d5 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/posix.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/posix.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/printf.h b/NorthstarDLL/include/spdlog/fmt/bundled/printf.h
index 8c28ac23..8c28ac23 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/printf.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/printf.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/ranges.h b/NorthstarDLL/include/spdlog/fmt/bundled/ranges.h
index 632f0494..632f0494 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/bundled/ranges.h
+++ b/NorthstarDLL/include/spdlog/fmt/bundled/ranges.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/chrono.h b/NorthstarDLL/include/spdlog/fmt/chrono.h
index e1fb7a06..e1fb7a06 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/chrono.h
+++ b/NorthstarDLL/include/spdlog/fmt/chrono.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/fmt.h b/NorthstarDLL/include/spdlog/fmt/fmt.h
index 746d2f2c..ec10ac33 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/fmt.h
+++ b/NorthstarDLL/include/spdlog/fmt/fmt.h
@@ -24,4 +24,4 @@
#else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib
#include <fmt/core.h>
#include <fmt/format.h>
-#endif \ No newline at end of file
+#endif
diff --git a/NorthstarDedicatedTest/include/spdlog/fmt/ostr.h b/NorthstarDLL/include/spdlog/fmt/ostr.h
index f82eb679..f82eb679 100644
--- a/NorthstarDedicatedTest/include/spdlog/fmt/ostr.h
+++ b/NorthstarDLL/include/spdlog/fmt/ostr.h
diff --git a/NorthstarDedicatedTest/include/spdlog/formatter.h b/NorthstarDLL/include/spdlog/formatter.h
index 5086fb21..5086fb21 100644
--- a/NorthstarDedicatedTest/include/spdlog/formatter.h
+++ b/NorthstarDLL/include/spdlog/formatter.h
diff --git a/NorthstarDedicatedTest/include/spdlog/fwd.h b/NorthstarDLL/include/spdlog/fwd.h
index cc05ddd4..cc05ddd4 100644
--- a/NorthstarDedicatedTest/include/spdlog/fwd.h
+++ b/NorthstarDLL/include/spdlog/fwd.h
diff --git a/NorthstarDedicatedTest/include/spdlog/logger-inl.h b/NorthstarDLL/include/spdlog/logger-inl.h
index d01c08da..d01c08da 100644
--- a/NorthstarDedicatedTest/include/spdlog/logger-inl.h
+++ b/NorthstarDLL/include/spdlog/logger-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/logger.h b/NorthstarDLL/include/spdlog/logger.h
index a34c5221..a34c5221 100644
--- a/NorthstarDedicatedTest/include/spdlog/logger.h
+++ b/NorthstarDLL/include/spdlog/logger.h
diff --git a/NorthstarDedicatedTest/include/spdlog/pattern_formatter-inl.h b/NorthstarDLL/include/spdlog/pattern_formatter-inl.h
index 54346e1e..54346e1e 100644
--- a/NorthstarDedicatedTest/include/spdlog/pattern_formatter-inl.h
+++ b/NorthstarDLL/include/spdlog/pattern_formatter-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/pattern_formatter.h b/NorthstarDLL/include/spdlog/pattern_formatter.h
index bc13ae10..bc13ae10 100644
--- a/NorthstarDedicatedTest/include/spdlog/pattern_formatter.h
+++ b/NorthstarDLL/include/spdlog/pattern_formatter.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/android_sink.h b/NorthstarDLL/include/spdlog/sinks/android_sink.h
index 9686adff..659beabb 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/android_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/android_sink.h
@@ -116,4 +116,4 @@ inline std::shared_ptr<logger> android_logger_st(const std::string &logger_name,
} // namespace spdlog
-#endif // __ANDROID__ \ No newline at end of file
+#endif // __ANDROID__
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/ansicolor_sink-inl.h b/NorthstarDLL/include/spdlog/sinks/ansicolor_sink-inl.h
index 61c0a719..61c0a719 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/ansicolor_sink-inl.h
+++ b/NorthstarDLL/include/spdlog/sinks/ansicolor_sink-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/ansicolor_sink.h b/NorthstarDLL/include/spdlog/sinks/ansicolor_sink.h
index 4438f706..4438f706 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/ansicolor_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/ansicolor_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/base_sink-inl.h b/NorthstarDLL/include/spdlog/sinks/base_sink-inl.h
index b15fb0e6..b15fb0e6 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/base_sink-inl.h
+++ b/NorthstarDLL/include/spdlog/sinks/base_sink-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/base_sink.h b/NorthstarDLL/include/spdlog/sinks/base_sink.h
index bf5072f8..bf5072f8 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/base_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/base_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/basic_file_sink-inl.h b/NorthstarDLL/include/spdlog/sinks/basic_file_sink-inl.h
index 1260d15c..1260d15c 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/basic_file_sink-inl.h
+++ b/NorthstarDLL/include/spdlog/sinks/basic_file_sink-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/basic_file_sink.h b/NorthstarDLL/include/spdlog/sinks/basic_file_sink.h
index 0ab9a4a1..4a742624 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/basic_file_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/basic_file_sink.h
@@ -55,4 +55,4 @@ inline std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, c
#ifdef SPDLOG_HEADER_ONLY
#include "basic_file_sink-inl.h"
-#endif \ No newline at end of file
+#endif
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/daily_file_sink.h b/NorthstarDLL/include/spdlog/sinks/daily_file_sink.h
index 16be821a..16be821a 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/daily_file_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/daily_file_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/dist_sink.h b/NorthstarDLL/include/spdlog/sinks/dist_sink.h
index 8fccb4ee..8fccb4ee 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/dist_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/dist_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/dup_filter_sink.h b/NorthstarDLL/include/spdlog/sinks/dup_filter_sink.h
index c9a08d68..c9a08d68 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/dup_filter_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/dup_filter_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/hourly_file_sink.h b/NorthstarDLL/include/spdlog/sinks/hourly_file_sink.h
index f5e34366..f5e34366 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/hourly_file_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/hourly_file_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/msvc_sink.h b/NorthstarDLL/include/spdlog/sinks/msvc_sink.h
index 8fec428d..8fec428d 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/msvc_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/msvc_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/null_sink.h b/NorthstarDLL/include/spdlog/sinks/null_sink.h
index eb832801..eb832801 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/null_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/null_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/ostream_sink.h b/NorthstarDLL/include/spdlog/sinks/ostream_sink.h
index 95c1e962..95c1e962 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/ostream_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/ostream_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/ringbuffer_sink.h b/NorthstarDLL/include/spdlog/sinks/ringbuffer_sink.h
index 1ee3f691..1ee3f691 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/ringbuffer_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/ringbuffer_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/rotating_file_sink-inl.h b/NorthstarDLL/include/spdlog/sinks/rotating_file_sink-inl.h
index d715ebf3..d715ebf3 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/rotating_file_sink-inl.h
+++ b/NorthstarDLL/include/spdlog/sinks/rotating_file_sink-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/rotating_file_sink.h b/NorthstarDLL/include/spdlog/sinks/rotating_file_sink.h
index e1e85a7d..e1e85a7d 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/rotating_file_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/rotating_file_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/sink-inl.h b/NorthstarDLL/include/spdlog/sinks/sink-inl.h
index a8dd6a6c..a8dd6a6c 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/sink-inl.h
+++ b/NorthstarDLL/include/spdlog/sinks/sink-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/sink.h b/NorthstarDLL/include/spdlog/sinks/sink.h
index be99744d..be99744d 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/stdout_color_sinks-inl.h b/NorthstarDLL/include/spdlog/sinks/stdout_color_sinks-inl.h
index 653aca80..935f1ccc 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/stdout_color_sinks-inl.h
+++ b/NorthstarDLL/include/spdlog/sinks/stdout_color_sinks-inl.h
@@ -35,4 +35,4 @@ SPDLOG_INLINE std::shared_ptr<logger> stderr_color_st(const std::string &logger_
{
return Factory::template create<sinks::stderr_color_sink_st>(logger_name, mode);
}
-} // namespace spdlog \ No newline at end of file
+} // namespace spdlog
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/stdout_color_sinks.h b/NorthstarDLL/include/spdlog/sinks/stdout_color_sinks.h
index e67aa91b..e67aa91b 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/stdout_color_sinks.h
+++ b/NorthstarDLL/include/spdlog/sinks/stdout_color_sinks.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/stdout_sinks-inl.h b/NorthstarDLL/include/spdlog/sinks/stdout_sinks-inl.h
index 25192607..25192607 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/stdout_sinks-inl.h
+++ b/NorthstarDLL/include/spdlog/sinks/stdout_sinks-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/stdout_sinks.h b/NorthstarDLL/include/spdlog/sinks/stdout_sinks.h
index 40688a46..40688a46 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/stdout_sinks.h
+++ b/NorthstarDLL/include/spdlog/sinks/stdout_sinks.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/syslog_sink.h b/NorthstarDLL/include/spdlog/sinks/syslog_sink.h
index 7c38fcb5..7c38fcb5 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/syslog_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/syslog_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/systemd_sink.h b/NorthstarDLL/include/spdlog/sinks/systemd_sink.h
index d23824b8..d23824b8 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/systemd_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/systemd_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/tcp_sink.h b/NorthstarDLL/include/spdlog/sinks/tcp_sink.h
index 9dd9e51d..9dd9e51d 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/tcp_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/tcp_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/win_eventlog_sink.h b/NorthstarDLL/include/spdlog/sinks/win_eventlog_sink.h
index 68170dd9..68170dd9 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/win_eventlog_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/win_eventlog_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/wincolor_sink-inl.h b/NorthstarDLL/include/spdlog/sinks/wincolor_sink-inl.h
index e2676d3c..e2676d3c 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/wincolor_sink-inl.h
+++ b/NorthstarDLL/include/spdlog/sinks/wincolor_sink-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/sinks/wincolor_sink.h b/NorthstarDLL/include/spdlog/sinks/wincolor_sink.h
index a82f1b24..a82f1b24 100644
--- a/NorthstarDedicatedTest/include/spdlog/sinks/wincolor_sink.h
+++ b/NorthstarDLL/include/spdlog/sinks/wincolor_sink.h
diff --git a/NorthstarDedicatedTest/include/spdlog/spdlog-inl.h b/NorthstarDLL/include/spdlog/spdlog-inl.h
index 96e09f59..96e09f59 100644
--- a/NorthstarDedicatedTest/include/spdlog/spdlog-inl.h
+++ b/NorthstarDLL/include/spdlog/spdlog-inl.h
diff --git a/NorthstarDedicatedTest/include/spdlog/spdlog.h b/NorthstarDLL/include/spdlog/spdlog.h
index bb130d94..bb130d94 100644
--- a/NorthstarDedicatedTest/include/spdlog/spdlog.h
+++ b/NorthstarDLL/include/spdlog/spdlog.h
diff --git a/NorthstarDedicatedTest/include/spdlog/stopwatch.h b/NorthstarDLL/include/spdlog/stopwatch.h
index bb976b19..bb976b19 100644
--- a/NorthstarDedicatedTest/include/spdlog/stopwatch.h
+++ b/NorthstarDLL/include/spdlog/stopwatch.h
diff --git a/NorthstarDedicatedTest/include/spdlog/tweakme.h b/NorthstarDLL/include/spdlog/tweakme.h
index 31e417ab..31e417ab 100644
--- a/NorthstarDedicatedTest/include/spdlog/tweakme.h
+++ b/NorthstarDLL/include/spdlog/tweakme.h
diff --git a/NorthstarDedicatedTest/include/spdlog/version.h b/NorthstarDLL/include/spdlog/version.h
index 828f78cb..828f78cb 100644
--- a/NorthstarDedicatedTest/include/spdlog/version.h
+++ b/NorthstarDLL/include/spdlog/version.h
diff --git a/NorthstarDedicatedTest/keyvalues.cpp b/NorthstarDLL/keyvalues.cpp
index 2063be62..98a9ce66 100644
--- a/NorthstarDedicatedTest/keyvalues.cpp
+++ b/NorthstarDLL/keyvalues.cpp
@@ -1,45 +1,16 @@
#include "pch.h"
-#include "keyvalues.h"
#include "modmanager.h"
#include "filesystem.h"
-#include "hookutils.h"
#include <fstream>
-// hook forward defs
-typedef char (*KeyValues__LoadFromBufferType)(
- void* self, const char* resourceName, const char* pBuffer, void* pFileSystem, void* a5, void* a6, int a7);
-KeyValues__LoadFromBufferType KeyValues__LoadFromBuffer;
-char KeyValues__LoadFromBufferHook(
- void* self, const char* resourceName, const char* pBuffer, void* pFileSystem, void* a5, void* a6, int a7);
-
-void InitialiseKeyValues(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x426C30, &KeyValues__LoadFromBufferHook, reinterpret_cast<LPVOID*>(&KeyValues__LoadFromBuffer));
-}
-
-void* savedFilesystemPtr;
-
-char KeyValues__LoadFromBufferHook(void* self, const char* resourceName, const char* pBuffer, void* pFileSystem, void* a5, void* a6, int a7)
-{
- // this is just to allow playlists to get a valid pFileSystem ptr for kv building, other functions that call this particular overload of
- // LoadFromBuffer seem to get called on network stuff exclusively not exactly sure what the address wanted here is, so just taking it
- // from a function call that always happens before playlists is loaded
- if (pFileSystem != nullptr)
- savedFilesystemPtr = pFileSystem;
- if (!pFileSystem && !strcmp(resourceName, "playlists"))
- pFileSystem = savedFilesystemPtr;
-
- return KeyValues__LoadFromBuffer(self, resourceName, pBuffer, pFileSystem, a5, a6, a7);
-}
+AUTOHOOK_INIT()
void ModManager::TryBuildKeyValues(const char* filename)
{
spdlog::info("Building KeyValues for file {}", filename);
- std::string normalisedPath = fs::path(filename).lexically_normal().string();
+ std::string normalisedPath = g_pModManager->NormaliseModFilePath(fs::path(filename));
fs::path compiledPath = GetCompiledAssetsPath() / filename;
fs::path compiledDir = compiledPath.parent_path();
fs::create_directories(compiledDir);
@@ -54,14 +25,14 @@ void ModManager::TryBuildKeyValues(const char* filename)
// copy over patch kv files, and add #bases to new file, last mods' patches should be applied first
// note: #include should be identical but it's actually just broken, thanks respawn
- for (int64_t i = m_loadedMods.size() - 1; i > -1; i--)
+ for (int64_t i = m_LoadedMods.size() - 1; i > -1; i--)
{
- if (!m_loadedMods[i].Enabled)
+ if (!m_LoadedMods[i].m_bEnabled)
continue;
size_t fileHash = STR_HASH(normalisedPath);
- auto modKv = m_loadedMods[i].KeyValues.find(fileHash);
- if (modKv != m_loadedMods[i].KeyValues.end())
+ auto modKv = m_LoadedMods[i].KeyValues.find(fileHash);
+ if (modKv != m_LoadedMods[i].KeyValues.end())
{
// should result in smth along the lines of #include "mod_patch_5_mp_weapon_car.txt"
@@ -76,7 +47,7 @@ void ModManager::TryBuildKeyValues(const char* filename)
fs::remove(compiledDir / patchFilePath);
- fs::copy_file(m_loadedMods[i].ModDirectory / "keyvalues" / filename, compiledDir / patchFilePath);
+ fs::copy_file(m_LoadedMods[i].m_ModDirectory / "keyvalues" / filename, compiledDir / patchFilePath);
}
}
@@ -86,7 +57,7 @@ void ModManager::TryBuildKeyValues(const char* filename)
newKvs += "\"\n";
// load original file, so we can parse out the name of the root obj (e.g. WeaponData for weapons)
- std::string originalFile = ReadVPKOriginalFile(filename);
+ std::string originalFile = R2::ReadVPKOriginalFile(filename);
if (!originalFile.length())
{
@@ -96,7 +67,6 @@ void ModManager::TryBuildKeyValues(const char* filename)
char rootName[64];
memset(rootName, 0, sizeof(rootName));
- rootName[63] = '\0';
// iterate until we hit an ascii char that isn't in a # command or comment to get root obj name
int i = 0;
@@ -127,11 +97,36 @@ void ModManager::TryBuildKeyValues(const char* filename)
writeStream.close();
ModOverrideFile overrideFile;
- overrideFile.owningMod = nullptr;
- overrideFile.path = normalisedPath;
+ overrideFile.m_pOwningMod = nullptr;
+ overrideFile.m_Path = normalisedPath;
- if (m_modFiles.find(normalisedPath) == m_modFiles.end())
- m_modFiles.insert(std::make_pair(normalisedPath, overrideFile));
+ if (m_ModFiles.find(normalisedPath) == m_ModFiles.end())
+ m_ModFiles.insert(std::make_pair(normalisedPath, overrideFile));
else
- m_modFiles[normalisedPath] = overrideFile;
-} \ No newline at end of file
+ m_ModFiles[normalisedPath] = overrideFile;
+}
+
+// clang-format off
+AUTOHOOK(KeyValues__LoadFromBuffer, engine.dll + 0x426C30,
+char, __fastcall, (void* self, const char* resourceName, const char* pBuffer, void* pFileSystem, void* a5, void* a6, int a7))
+// clang-format on
+{
+ static void* pSavedFilesystemPtr = nullptr;
+
+ // this is just to allow playlists to get a valid pFileSystem ptr for kv building, other functions that call this particular overload of
+ // LoadFromBuffer seem to get called on network stuff exclusively not exactly sure what the address wanted here is, so just taking it
+ // from a function call that always happens before playlists is loaded
+
+ // note: would be better if we could serialize this to disk for playlists, as this method breaks saving playlists in demos
+ if (pFileSystem != nullptr)
+ pSavedFilesystemPtr = pFileSystem;
+ if (!pFileSystem && !strcmp(resourceName, "playlists"))
+ pFileSystem = pSavedFilesystemPtr;
+
+ return KeyValues__LoadFromBuffer(self, resourceName, pBuffer, pFileSystem, a5, a6, a7);
+}
+
+ON_DLL_LOAD("engine.dll", KeyValues, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+}
diff --git a/NorthstarDedicatedTest/languagehooks.cpp b/NorthstarDLL/languagehooks.cpp
index c8d43901..d00beb68 100644
--- a/NorthstarDedicatedTest/languagehooks.cpp
+++ b/NorthstarDLL/languagehooks.cpp
@@ -1,18 +1,13 @@
#include "pch.h"
-#include "languagehooks.h"
-#include "gameutils.h"
+#include "tier0.h"
+
#include <filesystem>
#include <regex>
-namespace fs = std::filesystem;
-
-typedef char* (*GetGameLanguageType)();
-char* GetGameLanguage();
+AUTOHOOK_INIT()
typedef LANGID (*Tier0_DetectDefaultLanguageType)();
-GetGameLanguageType GetGameLanguageOriginal;
-
bool CheckLangAudioExists(char* lang)
{
std::string path {"r2\\sound\\general_"};
@@ -52,7 +47,10 @@ std::string GetAnyInstalledAudioLanguage()
return "NO LANGUAGE DETECTED";
}
-char* GetGameLanguageHook()
+// clang-format off
+AUTOHOOK(GetGameLanguage, tier0.dll + 0xF560,
+char*, __fastcall, ())
+// clang-format on
{
auto tier0Handle = GetModuleHandleA("tier0.dll");
auto Tier0_DetectDefaultLanguageType = GetProcAddress(tier0Handle, "Tier0_DetectDefaultLanguage");
@@ -60,7 +58,7 @@ char* GetGameLanguageHook()
bool& canOriginDictateLang = *(bool*)((char*)tier0Handle + 0xA9A90);
const char* forcedLanguage;
- if (CommandLine()->CheckParm("-language", &forcedLanguage))
+ if (Tier0::CommandLine()->CheckParm("-language", &forcedLanguage))
{
if (!CheckLangAudioExists((char*)forcedLanguage))
{
@@ -79,7 +77,7 @@ char* GetGameLanguageHook()
canOriginDictateLang = true; // let it try
{
- auto lang = GetGameLanguageOriginal();
+ auto lang = GetGameLanguage();
if (!CheckLangAudioExists(lang))
{
if (strcmp(lang, "russian") !=
@@ -97,7 +95,7 @@ char* GetGameLanguageHook()
Tier0_DetectDefaultLanguageType(); // force the global in tier0 to be populated with language inferred from user's system rather than
// defaulting to Russian
canOriginDictateLang = false; // Origin has no say anymore, we will fallback to user's system setup language
- auto lang = GetGameLanguageOriginal();
+ auto lang = GetGameLanguage();
spdlog::info("Detected system language: {}", lang);
if (!CheckLangAudioExists(lang))
{
@@ -112,8 +110,7 @@ char* GetGameLanguageHook()
return lang;
}
-void InitialiseTier0LanguageHooks(HMODULE baseAddress)
+ON_DLL_LOAD_CLIENT("tier0.dll", LanguageHooks, (CModule module))
{
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0xF560, &GetGameLanguageHook, reinterpret_cast<LPVOID*>(&GetGameLanguageOriginal));
-} \ No newline at end of file
+ AUTOHOOK_DISPATCH()
+}
diff --git a/NorthstarDLL/latencyflex.cpp b/NorthstarDLL/latencyflex.cpp
new file mode 100644
index 00000000..620e031a
--- /dev/null
+++ b/NorthstarDLL/latencyflex.cpp
@@ -0,0 +1,44 @@
+#include "pch.h"
+#include "convar.h"
+
+AUTOHOOK_INIT()
+
+ConVar* Cvar_r_latencyflex;
+
+void (*m_winelfx_WaitAndBeginFrame)();
+
+// clang-format off
+AUTOHOOK(OnRenderStart, client.dll + 0x1952C0,
+void, __fastcall, ())
+// clang-format on
+{
+ if (Cvar_r_latencyflex->GetBool() && m_winelfx_WaitAndBeginFrame)
+ m_winelfx_WaitAndBeginFrame();
+
+ OnRenderStart();
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", LatencyFlex, ConVar, (CModule module))
+{
+ // Connect to the LatencyFleX service
+ // LatencyFleX is an open source vendor agnostic replacement for Nvidia Reflex input latency reduction technology.
+ // https://ishitatsuyuki.github.io/post/latencyflex/
+ HMODULE pLfxModule;
+
+ if (pLfxModule = LoadLibraryA("latencyflex_layer.dll"))
+ m_winelfx_WaitAndBeginFrame =
+ reinterpret_cast<void (*)()>(reinterpret_cast<void*>(GetProcAddress(pLfxModule, "lfx_WaitAndBeginFrame")));
+ else if (pLfxModule = LoadLibraryA("latencyflex_wine.dll"))
+ m_winelfx_WaitAndBeginFrame =
+ reinterpret_cast<void (*)()>(reinterpret_cast<void*>(GetProcAddress(pLfxModule, "winelfx_WaitAndBeginFrame")));
+ else
+ {
+ spdlog::info("Unable to load LatencyFleX library, LatencyFleX disabled.");
+ return;
+ }
+
+ AUTOHOOK_DISPATCH()
+
+ spdlog::info("LatencyFleX initialized.");
+ Cvar_r_latencyflex = new ConVar("r_latencyflex", "1", FCVAR_ARCHIVE, "Whether or not to use LatencyFleX input latency reduction.");
+}
diff --git a/NorthstarDLL/limits.cpp b/NorthstarDLL/limits.cpp
new file mode 100644
index 00000000..fd635136
--- /dev/null
+++ b/NorthstarDLL/limits.cpp
@@ -0,0 +1,299 @@
+#include "pch.h"
+#include "limits.h"
+#include "hoststate.h"
+#include "r2client.h"
+#include "r2engine.h"
+#include "r2server.h"
+#include "maxplayers.h"
+#include "tier0.h"
+#include "vector.h"
+#include "serverauthentication.h"
+
+AUTOHOOK_INIT()
+
+ServerLimitsManager* g_pServerLimits;
+
+ConVar* Cvar_net_datablock_enabled;
+
+// todo: make this work on higher timescales, also possibly disable when sv_cheats is set
+void ServerLimitsManager::RunFrame(double flCurrentTime, float flFrameTime)
+{
+ if (Cvar_sv_antispeedhack_enable->GetBool())
+ {
+ // for each player, set their usercmd processing budget for the frame to the last frametime for the server
+ for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ {
+ R2::CBaseClient* player = &R2::g_pClientArray[i];
+
+ if (m_PlayerLimitData.find(player) != m_PlayerLimitData.end())
+ {
+ PlayerLimitData* pLimitData = &g_pServerLimits->m_PlayerLimitData[player];
+ if (pLimitData->flFrameUserCmdBudget < 0.016666667 * Cvar_sv_antispeedhack_maxtickbudget->GetFloat())
+ pLimitData->flFrameUserCmdBudget +=
+ fmax(flFrameTime, 0.016666667) * g_pServerLimits->Cvar_sv_antispeedhack_budgetincreasemultiplier->GetFloat();
+ }
+ }
+ }
+}
+
+void ServerLimitsManager::AddPlayer(R2::CBaseClient* player)
+{
+ PlayerLimitData limitData;
+ limitData.flFrameUserCmdBudget = 0.016666667 * Cvar_sv_antispeedhack_maxtickbudget->GetFloat();
+
+ m_PlayerLimitData.insert(std::make_pair(player, limitData));
+}
+
+void ServerLimitsManager::RemovePlayer(R2::CBaseClient* player)
+{
+ if (m_PlayerLimitData.find(player) != m_PlayerLimitData.end())
+ m_PlayerLimitData.erase(player);
+}
+
+bool ServerLimitsManager::CheckStringCommandLimits(R2::CBaseClient* player)
+{
+ if (CVar_sv_quota_stringcmdspersecond->GetInt() != -1)
+ {
+ // note: this isn't super perfect, legit clients can trigger it in lobby if they try, mostly good enough tho imo
+ if (Tier0::Plat_FloatTime() - m_PlayerLimitData[player].lastClientCommandQuotaStart >= 1.0)
+ {
+ // reset quota
+ m_PlayerLimitData[player].lastClientCommandQuotaStart = Tier0::Plat_FloatTime();
+ m_PlayerLimitData[player].numClientCommandsInQuota = 0;
+ }
+
+ m_PlayerLimitData[player].numClientCommandsInQuota++;
+ if (m_PlayerLimitData[player].numClientCommandsInQuota > CVar_sv_quota_stringcmdspersecond->GetInt())
+ {
+ // too many stringcmds, dc player
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ServerLimitsManager::CheckChatLimits(R2::CBaseClient* player)
+{
+ if (Tier0::Plat_FloatTime() - m_PlayerLimitData[player].lastSayTextLimitStart >= 1.0)
+ {
+ m_PlayerLimitData[player].lastSayTextLimitStart = Tier0::Plat_FloatTime();
+ m_PlayerLimitData[player].sayTextLimitCount = 0;
+ }
+
+ if (m_PlayerLimitData[player].sayTextLimitCount >= Cvar_sv_max_chat_messages_per_sec->GetInt())
+ return false;
+
+ m_PlayerLimitData[player].sayTextLimitCount++;
+ return true;
+}
+
+// clang-format off
+AUTOHOOK(CNetChan__ProcessMessages, engine.dll + 0x2140A0,
+char, __fastcall, (void* self, void* buf))
+// clang-format on
+{
+ enum eNetChanLimitMode
+ {
+ NETCHANLIMIT_WARN,
+ NETCHANLIMIT_KICK
+ };
+
+ double startTime = Tier0::Plat_FloatTime();
+ char ret = CNetChan__ProcessMessages(self, buf);
+
+ // check processing limits, unless we're in a level transition
+ if (R2::g_pHostState->m_iCurrentState == R2::HostState_t::HS_RUN && Tier0::ThreadInServerFrameThread())
+ {
+ // player that sent the message
+ R2::CBaseClient* sender = *(R2::CBaseClient**)((char*)self + 368);
+
+ // if no sender, return
+ // relatively certain this is fine?
+ if (!sender || !g_pServerLimits->m_PlayerLimitData.count(sender))
+ return ret;
+
+ // reset every second
+ if (startTime - g_pServerLimits->m_PlayerLimitData[sender].lastNetChanProcessingLimitStart >= 1.0 ||
+ g_pServerLimits->m_PlayerLimitData[sender].lastNetChanProcessingLimitStart == -1.0)
+ {
+ g_pServerLimits->m_PlayerLimitData[sender].lastNetChanProcessingLimitStart = startTime;
+ g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime = 0.0;
+ }
+ g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime += (Tier0::Plat_FloatTime() * 1000) - (startTime * 1000);
+
+ if (g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime >=
+ g_pServerLimits->Cvar_net_chan_limit_msec_per_sec->GetInt())
+ {
+ spdlog::warn(
+ "Client {} hit netchan processing limit with {}ms of processing time this second (max is {})",
+ (char*)sender + 0x16,
+ g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime,
+ g_pServerLimits->Cvar_net_chan_limit_msec_per_sec->GetInt());
+
+ // never kick local player
+ if (g_pServerLimits->Cvar_net_chan_limit_mode->GetInt() != NETCHANLIMIT_WARN && strcmp(R2::g_pLocalPlayerUserID, sender->m_UID))
+ {
+ R2::CBaseClient__Disconnect(sender, 1, "Exceeded net channel processing limit");
+ return false;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// clang-format off
+AUTOHOOK(ProcessConnectionlessPacket, engine.dll + 0x117800,
+bool, , (void* a1, R2::netpacket_t* packet))
+// clang-format on
+{
+ if (packet->adr.type == R2::NA_IP &&
+ (!(packet->data[4] == 'N' && Cvar_net_datablock_enabled->GetBool()) || !Cvar_net_datablock_enabled->GetBool()))
+ {
+ // bad lookup: optimise later tm
+ UnconnectedPlayerLimitData* sendData = nullptr;
+ for (UnconnectedPlayerLimitData& foundSendData : g_pServerLimits->m_UnconnectedPlayerLimitData)
+ {
+ if (!memcmp(packet->adr.ip, foundSendData.ip, 16))
+ {
+ sendData = &foundSendData;
+ break;
+ }
+ }
+
+ if (!sendData)
+ {
+ sendData = &g_pServerLimits->m_UnconnectedPlayerLimitData.emplace_back();
+ memcpy(sendData->ip, packet->adr.ip, 16);
+ }
+
+ if (Tier0::Plat_FloatTime() < sendData->timeoutEnd)
+ return false;
+
+ if (Tier0::Plat_FloatTime() - sendData->lastQuotaStart >= 1.0)
+ {
+ sendData->lastQuotaStart = Tier0::Plat_FloatTime();
+ sendData->packetCount = 0;
+ }
+
+ sendData->packetCount++;
+
+ if (sendData->packetCount >= g_pServerLimits->Cvar_sv_querylimit_per_sec->GetInt())
+ {
+ spdlog::warn(
+ "Client went over connectionless ratelimit of {} per sec with packet of type {}",
+ g_pServerLimits->Cvar_sv_querylimit_per_sec->GetInt(),
+ packet->data[4]);
+
+ // timeout for a minute
+ sendData->timeoutEnd = Tier0::Plat_FloatTime() + 60.0;
+ return false;
+ }
+ }
+
+ return ProcessConnectionlessPacket(a1, packet);
+}
+
+// this is weird and i'm not sure if it's correct, so not using for now
+/*AUTOHOOK(CBasePlayer__PhysicsSimulate, server.dll + 0x5A6E50, bool, __fastcall, (void* self, int a2, char a3))
+{
+ spdlog::info("CBasePlayer::PhysicsSimulate");
+ return CBasePlayer__PhysicsSimulate(self, a2, a3);
+}*/
+
+struct alignas(4) SV_CUserCmd
+{
+ DWORD command_number;
+ DWORD tick_count;
+ float command_time;
+ Vector3 worldViewAngles;
+ BYTE gap18[4];
+ Vector3 localViewAngles;
+ Vector3 attackangles;
+ Vector3 move;
+ DWORD buttons;
+ BYTE impulse;
+ short weaponselect;
+ DWORD meleetarget;
+ BYTE gap4C[24];
+ char headoffset;
+ BYTE gap65[11];
+ Vector3 cameraPos;
+ Vector3 cameraAngles;
+ BYTE gap88[4];
+ int tickSomething;
+ DWORD dword90;
+ DWORD predictedServerEventAck;
+ DWORD dword98;
+ float frameTime;
+};
+
+// clang-format off
+AUTOHOOK(CPlayerMove__RunCommand, server.dll + 0x5B8100,
+void, __fastcall, (void* self, R2::CBasePlayer* player, SV_CUserCmd* pUserCmd, uint64_t a4))
+// clang-format on
+{
+ if (g_pServerLimits->Cvar_sv_antispeedhack_enable->GetBool())
+ {
+ R2::CBaseClient* pClient = &R2::g_pClientArray[player->m_nPlayerIndex - 1];
+
+ if (g_pServerLimits->m_PlayerLimitData.find(pClient) != g_pServerLimits->m_PlayerLimitData.end())
+ {
+ PlayerLimitData* pLimitData = &g_pServerLimits->m_PlayerLimitData[pClient];
+
+ pLimitData->flFrameUserCmdBudget = fmax(0.0, pLimitData->flFrameUserCmdBudget - pUserCmd->frameTime);
+
+ if (pLimitData->flFrameUserCmdBudget <= 0.0)
+ {
+ spdlog::warn("player {} went over usercmd budget ({})", pClient->m_Name, pLimitData->flFrameUserCmdBudget);
+ return;
+ }
+ // else
+ // spdlog::info("{}: {}", pClient->m_Name, pLimitData->flFrameUserCmdBudget);
+ }
+ }
+
+ CPlayerMove__RunCommand(self, player, pUserCmd, a4);
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", ServerLimits, ConVar, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(engine.dll)
+
+ g_pServerLimits = new ServerLimitsManager;
+
+ g_pServerLimits->CVar_sv_quota_stringcmdspersecond = new ConVar(
+ "sv_quota_stringcmdspersecond",
+ "60",
+ FCVAR_GAMEDLL,
+ "How many string commands per second clients are allowed to submit, 0 to disallow all string commands, -1 to disable");
+ g_pServerLimits->Cvar_net_chan_limit_mode =
+ new ConVar("net_chan_limit_mode", "0", FCVAR_GAMEDLL, "The mode for netchan processing limits: 0 = warn, 1 = kick");
+ g_pServerLimits->Cvar_net_chan_limit_msec_per_sec = new ConVar(
+ "net_chan_limit_msec_per_sec",
+ "100",
+ FCVAR_GAMEDLL,
+ "Netchannel processing is limited to so many milliseconds, abort connection if exceeding budget");
+ g_pServerLimits->Cvar_sv_querylimit_per_sec = new ConVar("sv_querylimit_per_sec", "15", FCVAR_GAMEDLL, "");
+ g_pServerLimits->Cvar_sv_max_chat_messages_per_sec = new ConVar("sv_max_chat_messages_per_sec", "5", FCVAR_GAMEDLL, "");
+ g_pServerLimits->Cvar_sv_antispeedhack_enable =
+ new ConVar("sv_antispeedhack_enable", "0", FCVAR_NONE, "whether to enable antispeedhack protections");
+ g_pServerLimits->Cvar_sv_antispeedhack_maxtickbudget = new ConVar(
+ "sv_antispeedhack_maxtickbudget",
+ "64",
+ FCVAR_GAMEDLL,
+ "Maximum number of client-issued usercmd ticks that can be replayed in packet loss conditions, 0 to allow no restrictions");
+ g_pServerLimits->Cvar_sv_antispeedhack_budgetincreasemultiplier = new ConVar(
+ "sv_antispeedhack_budgetincreasemultiplier",
+ "1.2",
+ FCVAR_GAMEDLL,
+ "Increase usercmd processing budget by tickinterval * value per tick");
+
+ Cvar_net_datablock_enabled = R2::g_pCVar->FindVar("net_datablock_enabled");
+}
+
+ON_DLL_LOAD("server.dll", ServerLimitsServer, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(server.dll)
+}
diff --git a/NorthstarDLL/limits.h b/NorthstarDLL/limits.h
new file mode 100644
index 00000000..068f91c9
--- /dev/null
+++ b/NorthstarDLL/limits.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "r2engine.h"
+#include "convar.h"
+#include <unordered_map>
+
+struct PlayerLimitData
+{
+ double lastClientCommandQuotaStart = -1.0;
+ int numClientCommandsInQuota = 0;
+
+ double lastNetChanProcessingLimitStart = -1.0;
+ double netChanProcessingLimitTime = 0.0;
+
+ double lastSayTextLimitStart = -1.0;
+ int sayTextLimitCount = 0;
+
+ float flFrameUserCmdBudget = 0.0;
+};
+
+struct UnconnectedPlayerLimitData
+{
+ char ip[16];
+ double lastQuotaStart = 0.0;
+ int packetCount = 0;
+ double timeoutEnd = -1.0;
+};
+
+class ServerLimitsManager
+{
+ public:
+ ConVar* CVar_sv_quota_stringcmdspersecond;
+ ConVar* Cvar_net_chan_limit_mode;
+ ConVar* Cvar_net_chan_limit_msec_per_sec;
+ ConVar* Cvar_sv_querylimit_per_sec;
+ ConVar* Cvar_sv_max_chat_messages_per_sec;
+ ConVar* Cvar_sv_antispeedhack_enable;
+ ConVar* Cvar_sv_antispeedhack_maxtickbudget;
+ ConVar* Cvar_sv_antispeedhack_budgetincreasemultiplier;
+
+ std::unordered_map<R2::CBaseClient*, PlayerLimitData> m_PlayerLimitData;
+ std::vector<UnconnectedPlayerLimitData> m_UnconnectedPlayerLimitData;
+
+ public:
+ void RunFrame(double flCurrentTime, float flFrameTime);
+ void AddPlayer(R2::CBaseClient* player);
+ void RemovePlayer(R2::CBaseClient* player);
+ bool CheckStringCommandLimits(R2::CBaseClient* player);
+ bool CheckChatLimits(R2::CBaseClient* player);
+};
+
+extern ServerLimitsManager* g_pServerLimits;
diff --git a/NorthstarDedicatedTest/localchatwriter.cpp b/NorthstarDLL/localchatwriter.cpp
index 72a5afa7..efa7eeee 100644
--- a/NorthstarDedicatedTest/localchatwriter.cpp
+++ b/NorthstarDLL/localchatwriter.cpp
@@ -37,12 +37,11 @@ class vgui_BaseRichText_vtable
void(__fastcall* SetVerticalScrollbar)(vgui_BaseRichText* self, bool state);
void(__fastcall* SetMaximumCharCount)(vgui_BaseRichText* self, int maxChars);
- void(__fastcall* InsertColorChange)(vgui_BaseRichText* self, vgui_Color col);
+ void(__fastcall* InsertColorChange)(vgui_BaseRichText* self, Color col);
void(__fastcall* InsertIndentChange)(vgui_BaseRichText* self, int pixelsIndent);
void(__fastcall* InsertClickableTextStart)(vgui_BaseRichText* self, const char* pchClickAction);
void(__fastcall* InsertClickableTextEnd)(vgui_BaseRichText* self);
- void(__fastcall* InsertPossibleURLString)(
- vgui_BaseRichText* self, const char* text, vgui_Color URLTextColor, vgui_Color normalTextColor);
+ void(__fastcall* InsertPossibleURLString)(vgui_BaseRichText* self, const char* text, Color URLTextColor, Color normalTextColor);
void(__fastcall* InsertFade)(vgui_BaseRichText* self, float flSustain, float flLength);
void(__fastcall* ResetAllFades)(vgui_BaseRichText* self, bool bHold, bool bOnlyExpired, float flNewSustain);
void(__fastcall* SetToFullHeight)(vgui_BaseRichText* self);
@@ -81,25 +80,25 @@ LocalChatWriter::SwatchColor swatchColors[4] = {
LocalChatWriter::NetworkNameColor,
};
-vgui_Color darkColors[8] = {
- vgui_Color {0, 0, 0, 255},
- vgui_Color {205, 49, 49, 255},
- vgui_Color {13, 188, 121, 255},
- vgui_Color {229, 229, 16, 255},
- vgui_Color {36, 114, 200, 255},
- vgui_Color {188, 63, 188, 255},
- vgui_Color {17, 168, 205, 255},
- vgui_Color {229, 229, 229, 255}};
-
-vgui_Color lightColors[8] = {
- vgui_Color {102, 102, 102, 255},
- vgui_Color {241, 76, 76, 255},
- vgui_Color {35, 209, 139, 255},
- vgui_Color {245, 245, 67, 255},
- vgui_Color {59, 142, 234, 255},
- vgui_Color {214, 112, 214, 255},
- vgui_Color {41, 184, 219, 255},
- vgui_Color {255, 255, 255, 255}};
+Color darkColors[8] = {
+ Color {0, 0, 0, 255},
+ Color {205, 49, 49, 255},
+ Color {13, 188, 121, 255},
+ Color {229, 229, 16, 255},
+ Color {36, 114, 200, 255},
+ Color {188, 63, 188, 255},
+ Color {17, 168, 205, 255},
+ Color {229, 229, 229, 255}};
+
+Color lightColors[8] = {
+ Color {102, 102, 102, 255},
+ Color {241, 76, 76, 255},
+ Color {35, 209, 139, 255},
+ Color {245, 245, 67, 255},
+ Color {59, 142, 234, 255},
+ Color {214, 112, 214, 255},
+ Color {41, 184, 219, 255},
+ Color {255, 255, 255, 255}};
class AnsiEscapeParser
{
@@ -144,7 +143,7 @@ class AnsiEscapeParser
LocalChatWriter* m_writer;
Next m_next = Next::ControlType;
- vgui_Color m_expandedColor {0, 0, 0, 0};
+ Color m_expandedColor {0, 0, 0, 0};
Next HandleControlType(unsigned long val)
{
@@ -190,7 +189,7 @@ class AnsiEscapeParser
// Next values are r,g,b
if (val == 2)
{
- m_expandedColor = {0, 0, 0, 255};
+ m_expandedColor.SetColor(0, 0, 0, 255);
return Next::ForegroundR;
}
// Next value is 8-bit swatch color
@@ -219,13 +218,12 @@ class AnsiEscapeParser
unsigned char blue = code % 6;
unsigned char green = ((code - blue) / 6) % 6;
unsigned char red = (code - blue - (green * 6)) / 36;
- m_writer->InsertColorChange(
- vgui_Color {(unsigned char)(red * 51), (unsigned char)(green * 51), (unsigned char)(blue * 51), 255});
+ m_writer->InsertColorChange(Color {(unsigned char)(red * 51), (unsigned char)(green * 51), (unsigned char)(blue * 51), 255});
}
else if (val < UCHAR_MAX)
{
unsigned char brightness = (val - 232) * 10 + 8;
- m_writer->InsertColorChange(vgui_Color {brightness, brightness, brightness, 255});
+ m_writer->InsertColorChange(Color {brightness, brightness, brightness, 255});
}
return Next::ControlType;
@@ -236,7 +234,7 @@ class AnsiEscapeParser
if (val >= UCHAR_MAX)
return Next::ControlType;
- m_expandedColor.r = (unsigned char)val;
+ m_expandedColor[0] = (unsigned char)val;
return Next::ForegroundG;
}
@@ -245,7 +243,7 @@ class AnsiEscapeParser
if (val >= UCHAR_MAX)
return Next::ControlType;
- m_expandedColor.g = (unsigned char)val;
+ m_expandedColor[1] = (unsigned char)val;
return Next::ForegroundB;
}
@@ -254,7 +252,7 @@ class AnsiEscapeParser
if (val >= UCHAR_MAX)
return Next::ControlType;
- m_expandedColor.b = (unsigned char)val;
+ m_expandedColor[2] = (unsigned char)val;
m_writer->InsertColorChange(m_expandedColor);
return Next::ControlType;
}
@@ -280,12 +278,11 @@ void LocalChatWriter::Write(const char* str)
if (startOfEscape != str)
{
// There is some text before the escape sequence, just print that
-
size_t copyChars = startOfEscape - str;
if (copyChars > 255)
copyChars = 255;
- strncpy(writeBuffer, str, copyChars);
- writeBuffer[copyChars] = 0;
+
+ strncpy_s(writeBuffer, copyChars + 1, str, copyChars);
InsertText(writeBuffer);
}
@@ -320,6 +317,8 @@ void LocalChatWriter::InsertChar(wchar_t ch)
void LocalChatWriter::InsertText(const char* str)
{
+ spdlog::info(str);
+
WCHAR messageUnicode[288];
ConvertANSIToUnicode(str, -1, messageUnicode, 274);
@@ -347,7 +346,7 @@ void LocalChatWriter::InsertText(const wchar_t* str)
InsertDefaultFade();
}
-void LocalChatWriter::InsertColorChange(vgui_Color color)
+void LocalChatWriter::InsertColorChange(Color color)
{
for (CHudChat* hud = *CHudChat::allHuds; hud != NULL; hud = hud->next)
{
@@ -358,20 +357,24 @@ void LocalChatWriter::InsertColorChange(vgui_Color color)
}
}
-static vgui_Color GetHudSwatchColor(CHudChat* hud, LocalChatWriter::SwatchColor swatchColor)
+static Color GetHudSwatchColor(CHudChat* hud, LocalChatWriter::SwatchColor swatchColor)
{
switch (swatchColor)
{
case LocalChatWriter::MainTextColor:
return hud->m_mainTextColor;
+
case LocalChatWriter::SameTeamNameColor:
return hud->m_sameTeamColor;
+
case LocalChatWriter::EnemyTeamNameColor:
return hud->m_enemyTeamColor;
+
case LocalChatWriter::NetworkNameColor:
return hud->m_networkNameColor;
}
- return vgui_Color {0, 0, 0, 0};
+
+ return Color(0, 0, 0, 0);
}
void LocalChatWriter::InsertSwatchColorChange(SwatchColor swatchColor)
@@ -436,12 +439,12 @@ void LocalChatWriter::InsertDefaultFade()
}
}
-void InitialiseLocalChatWriter(HMODULE baseAddress)
+ON_DLL_LOAD_CLIENT("client.dll", LocalChatWriter, (CModule module))
{
- gGameSettings = (CGameSettings**)((char*)baseAddress + 0x11BAA48);
- gChatFadeLength = (CGameFloatVar**)((char*)baseAddress + 0x11BAB78);
- gChatFadeSustain = (CGameFloatVar**)((char*)baseAddress + 0x11BAC08);
- CHudChat::allHuds = (CHudChat**)((char*)baseAddress + 0x11BA9E8);
+ gGameSettings = module.Offset(0x11BAA48).As<CGameSettings**>();
+ gChatFadeLength = module.Offset(0x11BAB78).As<CGameFloatVar**>();
+ gChatFadeSustain = module.Offset(0x11BAC08).As<CGameFloatVar**>();
+ CHudChat::allHuds = module.Offset(0x11BA9E8).As<CHudChat**>();
- ConvertANSIToUnicode = (ConvertANSIToUnicodeType)((char*)baseAddress + 0x7339A0);
+ ConvertANSIToUnicode = module.Offset(0x7339A0).As<ConvertANSIToUnicodeType>();
}
diff --git a/NorthstarDedicatedTest/localchatwriter.h b/NorthstarDLL/localchatwriter.h
index 8048e084..0df0cac8 100644
--- a/NorthstarDedicatedTest/localchatwriter.h
+++ b/NorthstarDLL/localchatwriter.h
@@ -1,13 +1,6 @@
#pragma once
#include "pch.h"
-
-struct vgui_Color
-{
- unsigned char r;
- unsigned char g;
- unsigned char b;
- unsigned char a;
-};
+#include "color.h"
class vgui_BaseRichText;
@@ -18,10 +11,10 @@ class CHudChat
char unknown1[720];
- vgui_Color m_sameTeamColor;
- vgui_Color m_enemyTeamColor;
- vgui_Color m_mainTextColor;
- vgui_Color m_networkNameColor;
+ Color m_sameTeamColor;
+ Color m_enemyTeamColor;
+ Color m_mainTextColor;
+ Color m_networkNameColor;
char unknown2[12];
@@ -61,7 +54,7 @@ class LocalChatWriter
void InsertChar(wchar_t ch);
void InsertText(const char* str);
void InsertText(const wchar_t* str);
- void InsertColorChange(vgui_Color color);
+ void InsertColorChange(Color color);
void InsertSwatchColorChange(SwatchColor color);
private:
@@ -70,5 +63,3 @@ class LocalChatWriter
const char* ApplyAnsiEscape(const char* escape);
void InsertDefaultFade();
};
-
-void InitialiseLocalChatWriter(HMODULE baseAddress);
diff --git a/NorthstarDLL/logging.cpp b/NorthstarDLL/logging.cpp
new file mode 100644
index 00000000..7c6d50a6
--- /dev/null
+++ b/NorthstarDLL/logging.cpp
@@ -0,0 +1,259 @@
+#include "pch.h"
+#include "logging.h"
+#include "convar.h"
+#include "concommand.h"
+#include "nsprefix.h"
+#include "bitbuf.h"
+#include "tier0.h"
+#include "spdlog/sinks/basic_file_sink.h"
+
+#include <iomanip>
+#include <sstream>
+
+AUTOHOOK_INIT()
+
+ConVar* Cvar_spewlog_enable;
+
+enum class SpewType_t
+{
+ SPEW_MESSAGE = 0,
+
+ SPEW_WARNING,
+ SPEW_ASSERT,
+ SPEW_ERROR,
+ SPEW_LOG,
+
+ SPEW_TYPE_COUNT
+};
+
+const std::unordered_map<SpewType_t, const char*> PrintSpewTypes = {
+ {SpewType_t::SPEW_MESSAGE, "SPEW_MESSAGE"},
+ {SpewType_t::SPEW_WARNING, "SPEW_WARNING"},
+ {SpewType_t::SPEW_ASSERT, "SPEW_ASSERT"},
+ {SpewType_t::SPEW_ERROR, "SPEW_ERROR"},
+ {SpewType_t::SPEW_LOG, "SPEW_LOG"}};
+
+// clang-format off
+AUTOHOOK(EngineSpewFunc, engine.dll + 0x11CA80,
+void, __fastcall, (void* pEngineServer, SpewType_t type, const char* format, va_list args))
+// clang-format on
+{
+ if (!Cvar_spewlog_enable->GetBool())
+ return;
+
+ const char* typeStr = PrintSpewTypes.at(type);
+ char formatted[2048] = {0};
+ bool bShouldFormat = true;
+
+ // because titanfall 2 is quite possibly the worst thing to yet exist, it sometimes gives invalid specifiers which will crash
+ // ttf2sdk had a way to prevent them from crashing but it doesnt work in debug builds
+ // so we use this instead
+ for (int i = 0; format[i]; i++)
+ {
+ if (format[i] == '%')
+ {
+ switch (format[i + 1])
+ {
+ // this is fucking awful lol
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ case 'a':
+ case 'A':
+ case 'c':
+ case 's':
+ case 'p':
+ case 'n':
+ case '%':
+ case '-':
+ case '+':
+ case ' ':
+ case '#':
+ case '*':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ break;
+
+ default:
+ {
+ bShouldFormat = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (bShouldFormat)
+ vsnprintf(formatted, sizeof(formatted), format, args);
+ else
+ spdlog::warn("Failed to format {} \"{}\"", typeStr, format);
+
+ auto endpos = strlen(formatted);
+ if (formatted[endpos - 1] == '\n')
+ formatted[endpos - 1] = '\0'; // cut off repeated newline
+
+ spdlog::info("[SERVER {}] {}", typeStr, formatted);
+}
+
+// used for printing the output of status
+// clang-format off
+AUTOHOOK(Status_ConMsg, engine.dll + 0x15ABD0,
+void,, (const char* text, ...))
+// clang-format on
+{
+ char formatted[2048];
+ va_list list;
+
+ va_start(list, text);
+ vsprintf_s(formatted, text, list);
+ va_end(list);
+
+ auto endpos = strlen(formatted);
+ if (formatted[endpos - 1] == '\n')
+ formatted[endpos - 1] = '\0'; // cut off repeated newline
+
+ spdlog::info(formatted);
+}
+
+// clang-format off
+AUTOHOOK(CClientState_ProcessPrint, engine.dll + 0x1A1530,
+bool,, (void* thisptr, uintptr_t msg))
+// clang-format on
+{
+ char* text = *(char**)(msg + 0x20);
+
+ auto endpos = strlen(text);
+ if (text[endpos - 1] == '\n')
+ text[endpos - 1] = '\0'; // cut off repeated newline
+
+ spdlog::info(text);
+ return true;
+}
+
+ConVar* Cvar_cl_showtextmsg;
+
+class ICenterPrint
+{
+ public:
+ virtual void ctor() = 0;
+ virtual void Clear(void) = 0;
+ virtual void ColorPrint(int r, int g, int b, int a, wchar_t* text) = 0;
+ virtual void ColorPrint(int r, int g, int b, int a, char* text) = 0;
+ virtual void Print(wchar_t* text) = 0;
+ virtual void Print(char* text) = 0;
+ virtual void SetTextColor(int r, int g, int b, int a) = 0;
+};
+
+ICenterPrint* pInternalCenterPrint = NULL;
+
+enum class TextMsgPrintType_t
+{
+ HUD_PRINTNOTIFY = 1,
+ HUD_PRINTCONSOLE,
+ HUD_PRINTTALK,
+ HUD_PRINTCENTER
+};
+
+// clang-format off
+AUTOHOOK(TextMsg, client.dll + 0x198710,
+void,, (BFRead* msg))
+// clang-format on
+{
+ TextMsgPrintType_t msg_dest = (TextMsgPrintType_t)msg->ReadByte();
+
+ char text[256];
+ msg->ReadString(text, sizeof(text));
+
+ if (!Cvar_cl_showtextmsg->GetBool())
+ return;
+
+ switch (msg_dest)
+ {
+ case TextMsgPrintType_t::HUD_PRINTCENTER:
+ pInternalCenterPrint->Print(text);
+ break;
+
+ default:
+ spdlog::warn("Unimplemented TextMsg type {}! printing to console", msg_dest);
+ [[fallthrough]];
+
+ case TextMsgPrintType_t::HUD_PRINTCONSOLE:
+ auto endpos = strlen(text);
+ if (text[endpos - 1] == '\n')
+ text[endpos - 1] = '\0'; // cut off repeated newline
+
+ spdlog::info(text);
+ break;
+ }
+}
+
+// clang-format off
+AUTOHOOK(ConCommand_echo, engine.dll + 0x123680,
+void,, (const CCommand& arg))
+// clang-format on
+{
+ if (arg.ArgC() >= 2)
+ spdlog::info("[echo] {}", arg.ArgS());
+}
+
+// This needs to be called after hooks are loaded so we can access the command line args
+void CreateLogFiles()
+{
+ if (strstr(GetCommandLineA(), "-disablelogs"))
+ {
+ spdlog::default_logger()->set_level(spdlog::level::off);
+ }
+ else
+ {
+ // todo: might be good to delete logs that are too old
+ time_t time = std::time(nullptr);
+ tm currentTime = *std::localtime(&time);
+ std::stringstream stream;
+
+ stream << std::put_time(&currentTime, (GetNorthstarPrefix() + "/logs/nslog%Y-%m-%d %H-%M-%S.txt").c_str());
+ spdlog::default_logger()->sinks().push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(stream.str(), false));
+ spdlog::flush_on(spdlog::level::info);
+ }
+}
+
+void InitialiseLogging()
+{
+ AllocConsole();
+
+ // Bind stdout to receive console output.
+ // these two lines are responsible for stuff to not show up in the console sometimes, from talking about it on discord
+ // apparently they were meant to make logging work when using -northstar, however from testing it seems that it doesnt
+ // work regardless of these two lines
+ // freopen("CONOUT$", "w", stdout);
+ // freopen("CONOUT$", "w", stderr);
+ spdlog::default_logger()->set_pattern("[%H:%M:%S] [%l] %v");
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("engine.dll", EngineSpewFuncHooks, ConVar, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(engine.dll)
+
+ Cvar_spewlog_enable = new ConVar("spewlog_enable", "1", FCVAR_NONE, "Enables/disables whether the engine spewfunc should be logged");
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientPrintHooks, ConVar, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(client.dll)
+
+ Cvar_cl_showtextmsg = new ConVar("cl_showtextmsg", "1", FCVAR_NONE, "Enable/disable text messages printing on the screen.");
+ pInternalCenterPrint = module.Offset(0x216E940).As<ICenterPrint*>();
+}
diff --git a/NorthstarDLL/logging.h b/NorthstarDLL/logging.h
new file mode 100644
index 00000000..83fd0c12
--- /dev/null
+++ b/NorthstarDLL/logging.h
@@ -0,0 +1,4 @@
+#pragma once
+
+void CreateLogFiles();
+void InitialiseLogging();
diff --git a/NorthstarDedicatedTest/main.h b/NorthstarDLL/main.h
index 64f9cfd2..412f1e25 100644
--- a/NorthstarDedicatedTest/main.h
+++ b/NorthstarDLL/main.h
@@ -1,4 +1,4 @@
#pragma once
extern "C" __declspec(dllexport) bool InitialiseNorthstar();
-extern "C" __declspec(dllexport) bool LoadPlugins(); \ No newline at end of file
+extern "C" __declspec(dllexport) bool LoadPlugins();
diff --git a/NorthstarDLL/masterserver.cpp b/NorthstarDLL/masterserver.cpp
new file mode 100644
index 00000000..b8e00bdc
--- /dev/null
+++ b/NorthstarDLL/masterserver.cpp
@@ -0,0 +1,1076 @@
+#include "pch.h"
+#include "masterserver.h"
+#include "concommand.h"
+#include "playlist.h"
+#include "serverauthentication.h"
+#include "tier0.h"
+#include "r2engine.h"
+#include "modmanager.h"
+#include "misccommands.h"
+#include "version.h"
+
+#include "rapidjson/document.h"
+#include "rapidjson/stringbuffer.h"
+#include "rapidjson/writer.h"
+#include "rapidjson/error/en.h"
+
+#include <cstring>
+#include <regex>
+
+MasterServerManager* g_pMasterServerManager;
+
+ConVar* Cvar_ns_masterserver_hostname;
+ConVar* Cvar_ns_curl_log_enable;
+
+RemoteServerInfo::RemoteServerInfo(
+ const char* newId,
+ const char* newName,
+ const char* newDescription,
+ const char* newMap,
+ const char* newPlaylist,
+ int newPlayerCount,
+ int newMaxPlayers,
+ bool newRequiresPassword)
+{
+ // passworded servers don't have public ips
+ requiresPassword = newRequiresPassword;
+
+ strncpy_s((char*)id, sizeof(id), newId, sizeof(id) - 1);
+ strncpy_s((char*)name, sizeof(name), newName, sizeof(name) - 1);
+
+ description = std::string(newDescription);
+
+ strncpy_s((char*)map, sizeof(map), newMap, sizeof(map) - 1);
+ strncpy_s((char*)playlist, sizeof(playlist), newPlaylist, sizeof(playlist) - 1);
+
+ playerCount = newPlayerCount;
+ maxPlayers = newMaxPlayers;
+}
+
+void SetCommonHttpClientOptions(CURL* curl)
+{
+ curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, Cvar_ns_curl_log_enable->GetBool());
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, &NSUserAgent);
+ // curl_easy_setopt(curl, CURLOPT_STDERR, stdout);
+ if (Tier0::CommandLine()->FindParm("-msinsecure")) // TODO: this check doesn't seem to work
+ {
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ }
+}
+
+void MasterServerManager::ClearServerList()
+{
+ // this doesn't really do anything lol, probably isn't threadsafe
+ m_bRequestingServerList = true;
+
+ m_vRemoteServers.clear();
+
+ m_bRequestingServerList = false;
+}
+
+size_t CurlWriteToStringBufferCallback(char* contents, size_t size, size_t nmemb, void* userp)
+{
+ ((std::string*)userp)->append((char*)contents, size * nmemb);
+ return size * nmemb;
+}
+
+void MasterServerManager::AuthenticateOriginWithMasterServer(const char* uid, const char* originToken)
+{
+ if (m_bOriginAuthWithMasterServerInProgress)
+ return;
+
+ // do this here so it's instantly set
+ m_bOriginAuthWithMasterServerInProgress = true;
+ std::string uidStr(uid);
+ std::string tokenStr(originToken);
+
+ std::thread requestThread(
+ [this, uidStr, tokenStr]()
+ {
+ spdlog::info("Trying to authenticate with northstar masterserver for user {}", uidStr);
+
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+ std::string readBuffer;
+ curl_easy_setopt(
+ curl,
+ CURLOPT_URL,
+ fmt::format("{}/client/origin_auth?id={}&token={}", Cvar_ns_masterserver_hostname->GetString(), uidStr, tokenStr).c_str());
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ {
+ m_bSuccessfullyConnected = true;
+
+ rapidjson_document originAuthInfo;
+ originAuthInfo.Parse(readBuffer.c_str());
+
+ if (originAuthInfo.HasParseError())
+ {
+ spdlog::error(
+ "Failed reading origin auth info response: encountered parse error \"{}\"",
+ rapidjson::GetParseError_En(originAuthInfo.GetParseError()));
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!originAuthInfo.IsObject() || !originAuthInfo.HasMember("success"))
+ {
+ spdlog::error("Failed reading origin auth info response: malformed response object {}", readBuffer);
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (originAuthInfo["success"].IsTrue() && originAuthInfo.HasMember("token") && originAuthInfo["token"].IsString())
+ {
+ strncpy_s(
+ m_sOwnClientAuthToken,
+ sizeof(m_sOwnClientAuthToken),
+ originAuthInfo["token"].GetString(),
+ sizeof(m_sOwnClientAuthToken) - 1);
+ spdlog::info("Northstar origin authentication completed successfully!");
+ }
+ else
+ spdlog::error("Northstar origin authentication failed");
+ }
+ else
+ {
+ spdlog::error("Failed performing northstar origin auth: error {}", curl_easy_strerror(result));
+ m_bSuccessfullyConnected = false;
+ }
+
+ // we goto this instead of returning so we always hit this
+ REQUEST_END_CLEANUP:
+ m_bOriginAuthWithMasterServerInProgress = false;
+ m_bOriginAuthWithMasterServerDone = true;
+ curl_easy_cleanup(curl);
+ });
+
+ requestThread.detach();
+}
+
+void MasterServerManager::RequestServerList()
+{
+ // do this here so it's instantly set on call for scripts
+ m_bScriptRequestingServerList = true;
+
+ std::thread requestThread(
+ [this]()
+ {
+ // make sure we never have 2 threads writing at once
+ // i sure do hope this is actually threadsafe
+ while (m_bRequestingServerList)
+ Sleep(100);
+
+ m_bRequestingServerList = true;
+ m_bScriptRequestingServerList = true;
+
+ spdlog::info("Requesting server list from {}", Cvar_ns_masterserver_hostname->GetString());
+
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+
+ std::string readBuffer;
+ curl_easy_setopt(curl, CURLOPT_URL, fmt::format("{}/client/servers", Cvar_ns_masterserver_hostname->GetString()).c_str());
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ {
+ m_bSuccessfullyConnected = true;
+
+ rapidjson_document serverInfoJson;
+ serverInfoJson.Parse(readBuffer.c_str());
+
+ if (serverInfoJson.HasParseError())
+ {
+ spdlog::error(
+ "Failed reading masterserver response: encountered parse error \"{}\"",
+ rapidjson::GetParseError_En(serverInfoJson.GetParseError()));
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (serverInfoJson.IsObject() && serverInfoJson.HasMember("error"))
+ {
+ spdlog::error("Failed reading masterserver response: got fastify error response");
+ spdlog::error(readBuffer);
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!serverInfoJson.IsArray())
+ {
+ spdlog::error("Failed reading masterserver response: root object is not an array");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ rapidjson::GenericArray<false, rapidjson_document::GenericValue> serverArray = serverInfoJson.GetArray();
+
+ spdlog::info("Got {} servers", serverArray.Size());
+
+ for (auto& serverObj : serverArray)
+ {
+ if (!serverObj.IsObject())
+ {
+ spdlog::error("Failed reading masterserver response: member of server array is not an object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ // todo: verify json props are fine before adding to m_remoteServers
+ if (!serverObj.HasMember("id") || !serverObj["id"].IsString() || !serverObj.HasMember("name") ||
+ !serverObj["name"].IsString() || !serverObj.HasMember("description") || !serverObj["description"].IsString() ||
+ !serverObj.HasMember("map") || !serverObj["map"].IsString() || !serverObj.HasMember("playlist") ||
+ !serverObj["playlist"].IsString() || !serverObj.HasMember("playerCount") || !serverObj["playerCount"].IsNumber() ||
+ !serverObj.HasMember("maxPlayers") || !serverObj["maxPlayers"].IsNumber() || !serverObj.HasMember("hasPassword") ||
+ !serverObj["hasPassword"].IsBool() || !serverObj.HasMember("modInfo") || !serverObj["modInfo"].HasMember("Mods") ||
+ !serverObj["modInfo"]["Mods"].IsArray())
+ {
+ spdlog::error("Failed reading masterserver response: malformed server object");
+ continue;
+ };
+
+ const char* id = serverObj["id"].GetString();
+
+ RemoteServerInfo* newServer = nullptr;
+
+ bool createNewServerInfo = true;
+ for (RemoteServerInfo& server : m_vRemoteServers)
+ {
+ // if server already exists, update info rather than adding to it
+ if (!strncmp((const char*)server.id, id, 32))
+ {
+ server = RemoteServerInfo(
+ id,
+ serverObj["name"].GetString(),
+ serverObj["description"].GetString(),
+ serverObj["map"].GetString(),
+ serverObj["playlist"].GetString(),
+ serverObj["playerCount"].GetInt(),
+ serverObj["maxPlayers"].GetInt(),
+ serverObj["hasPassword"].IsTrue());
+ newServer = &server;
+ createNewServerInfo = false;
+ break;
+ }
+ }
+
+ // server didn't exist
+ if (createNewServerInfo)
+ newServer = &m_vRemoteServers.emplace_back(
+ id,
+ serverObj["name"].GetString(),
+ serverObj["description"].GetString(),
+ serverObj["map"].GetString(),
+ serverObj["playlist"].GetString(),
+ serverObj["playerCount"].GetInt(),
+ serverObj["maxPlayers"].GetInt(),
+ serverObj["hasPassword"].IsTrue());
+
+ newServer->requiredMods.clear();
+ for (auto& requiredMod : serverObj["modInfo"]["Mods"].GetArray())
+ {
+ RemoteModInfo modInfo;
+
+ if (!requiredMod.HasMember("RequiredOnClient") || !requiredMod["RequiredOnClient"].IsTrue())
+ continue;
+
+ if (!requiredMod.HasMember("Name") || !requiredMod["Name"].IsString())
+ continue;
+ modInfo.Name = requiredMod["Name"].GetString();
+
+ if (!requiredMod.HasMember("Version") || !requiredMod["Version"].IsString())
+ continue;
+ modInfo.Version = requiredMod["Version"].GetString();
+
+ newServer->requiredMods.push_back(modInfo);
+ }
+ // Can probably re-enable this later with a -verbose flag, but slows down loading of the server browser quite a bit as
+ // is
+ // spdlog::info(
+ // "Server {} on map {} with playlist {} has {}/{} players", serverObj["name"].GetString(),
+ // serverObj["map"].GetString(), serverObj["playlist"].GetString(), serverObj["playerCount"].GetInt(),
+ // serverObj["maxPlayers"].GetInt());
+ }
+
+ std::sort(
+ m_vRemoteServers.begin(),
+ m_vRemoteServers.end(),
+ [](RemoteServerInfo& a, RemoteServerInfo& b) { return a.playerCount > b.playerCount; });
+ }
+ else
+ {
+ spdlog::error("Failed requesting servers: error {}", curl_easy_strerror(result));
+ m_bSuccessfullyConnected = false;
+ }
+
+ // we goto this instead of returning so we always hit this
+ REQUEST_END_CLEANUP:
+ m_bRequestingServerList = false;
+ m_bScriptRequestingServerList = false;
+ curl_easy_cleanup(curl);
+ });
+
+ requestThread.detach();
+}
+
+void MasterServerManager::RequestMainMenuPromos()
+{
+ m_bHasMainMenuPromoData = false;
+
+ std::thread requestThread(
+ [this]()
+ {
+ while (m_bOriginAuthWithMasterServerInProgress || !m_bOriginAuthWithMasterServerDone)
+ Sleep(500);
+
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+
+ std::string readBuffer;
+ curl_easy_setopt(
+ curl, CURLOPT_URL, fmt::format("{}/client/mainmenupromos", Cvar_ns_masterserver_hostname->GetString()).c_str());
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ {
+ m_bSuccessfullyConnected = true;
+
+ rapidjson_document mainMenuPromoJson;
+ mainMenuPromoJson.Parse(readBuffer.c_str());
+
+ if (mainMenuPromoJson.HasParseError())
+ {
+ spdlog::error(
+ "Failed reading masterserver main menu promos response: encountered parse error \"{}\"",
+ rapidjson::GetParseError_En(mainMenuPromoJson.GetParseError()));
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!mainMenuPromoJson.IsObject())
+ {
+ spdlog::error("Failed reading masterserver main menu promos response: root object is not an object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (mainMenuPromoJson.HasMember("error"))
+ {
+ spdlog::error("Failed reading masterserver response: got fastify error response");
+ spdlog::error(readBuffer);
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!mainMenuPromoJson.HasMember("newInfo") || !mainMenuPromoJson["newInfo"].IsObject() ||
+ !mainMenuPromoJson["newInfo"].HasMember("Title1") || !mainMenuPromoJson["newInfo"]["Title1"].IsString() ||
+ !mainMenuPromoJson["newInfo"].HasMember("Title2") || !mainMenuPromoJson["newInfo"]["Title2"].IsString() ||
+ !mainMenuPromoJson["newInfo"].HasMember("Title3") || !mainMenuPromoJson["newInfo"]["Title3"].IsString() ||
+
+ !mainMenuPromoJson.HasMember("largeButton") || !mainMenuPromoJson["largeButton"].IsObject() ||
+ !mainMenuPromoJson["largeButton"].HasMember("Title") || !mainMenuPromoJson["largeButton"]["Title"].IsString() ||
+ !mainMenuPromoJson["largeButton"].HasMember("Text") || !mainMenuPromoJson["largeButton"]["Text"].IsString() ||
+ !mainMenuPromoJson["largeButton"].HasMember("Url") || !mainMenuPromoJson["largeButton"]["Url"].IsString() ||
+ !mainMenuPromoJson["largeButton"].HasMember("ImageIndex") ||
+ !mainMenuPromoJson["largeButton"]["ImageIndex"].IsNumber() ||
+
+ !mainMenuPromoJson.HasMember("smallButton1") || !mainMenuPromoJson["smallButton1"].IsObject() ||
+ !mainMenuPromoJson["smallButton1"].HasMember("Title") || !mainMenuPromoJson["smallButton1"]["Title"].IsString() ||
+ !mainMenuPromoJson["smallButton1"].HasMember("Url") || !mainMenuPromoJson["smallButton1"]["Url"].IsString() ||
+ !mainMenuPromoJson["smallButton1"].HasMember("ImageIndex") ||
+ !mainMenuPromoJson["smallButton1"]["ImageIndex"].IsNumber() ||
+
+ !mainMenuPromoJson.HasMember("smallButton2") || !mainMenuPromoJson["smallButton2"].IsObject() ||
+ !mainMenuPromoJson["smallButton2"].HasMember("Title") || !mainMenuPromoJson["smallButton2"]["Title"].IsString() ||
+ !mainMenuPromoJson["smallButton2"].HasMember("Url") || !mainMenuPromoJson["smallButton2"]["Url"].IsString() ||
+ !mainMenuPromoJson["smallButton2"].HasMember("ImageIndex") ||
+ !mainMenuPromoJson["smallButton2"]["ImageIndex"].IsNumber())
+ {
+ spdlog::error("Failed reading masterserver main menu promos response: malformed json object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ m_sMainMenuPromoData.newInfoTitle1 = mainMenuPromoJson["newInfo"]["Title1"].GetString();
+ m_sMainMenuPromoData.newInfoTitle2 = mainMenuPromoJson["newInfo"]["Title2"].GetString();
+ m_sMainMenuPromoData.newInfoTitle3 = mainMenuPromoJson["newInfo"]["Title3"].GetString();
+
+ m_sMainMenuPromoData.largeButtonTitle = mainMenuPromoJson["largeButton"]["Title"].GetString();
+ m_sMainMenuPromoData.largeButtonText = mainMenuPromoJson["largeButton"]["Text"].GetString();
+ m_sMainMenuPromoData.largeButtonUrl = mainMenuPromoJson["largeButton"]["Url"].GetString();
+ m_sMainMenuPromoData.largeButtonImageIndex = mainMenuPromoJson["largeButton"]["ImageIndex"].GetInt();
+
+ m_sMainMenuPromoData.smallButton1Title = mainMenuPromoJson["smallButton1"]["Title"].GetString();
+ m_sMainMenuPromoData.smallButton1Url = mainMenuPromoJson["smallButton1"]["Url"].GetString();
+ m_sMainMenuPromoData.smallButton1ImageIndex = mainMenuPromoJson["smallButton1"]["ImageIndex"].GetInt();
+
+ m_sMainMenuPromoData.smallButton2Title = mainMenuPromoJson["smallButton2"]["Title"].GetString();
+ m_sMainMenuPromoData.smallButton2Url = mainMenuPromoJson["smallButton2"]["Url"].GetString();
+ m_sMainMenuPromoData.smallButton2ImageIndex = mainMenuPromoJson["smallButton2"]["ImageIndex"].GetInt();
+
+ m_bHasMainMenuPromoData = true;
+ }
+ else
+ {
+ spdlog::error("Failed requesting main menu promos: error {}", curl_easy_strerror(result));
+ m_bSuccessfullyConnected = false;
+ }
+
+ REQUEST_END_CLEANUP:
+ // nothing lol
+ curl_easy_cleanup(curl);
+ });
+
+ requestThread.detach();
+}
+
+void MasterServerManager::AuthenticateWithOwnServer(const char* uid, const char* playerToken)
+{
+ // dont wait, just stop if we're trying to do 2 auth requests at once
+ if (m_bAuthenticatingWithGameServer)
+ return;
+
+ m_bAuthenticatingWithGameServer = true;
+ m_bScriptAuthenticatingWithGameServer = true;
+ m_bSuccessfullyAuthenticatedWithGameServer = false;
+
+ std::string uidStr(uid);
+ std::string tokenStr(playerToken);
+
+ std::thread requestThread(
+ [this, uidStr, tokenStr]()
+ {
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+
+ std::string readBuffer;
+ curl_easy_setopt(
+ curl,
+ CURLOPT_URL,
+ fmt::format("{}/client/auth_with_self?id={}&playerToken={}", Cvar_ns_masterserver_hostname->GetString(), uidStr, tokenStr)
+ .c_str());
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ {
+ m_bSuccessfullyConnected = true;
+
+ rapidjson_document authInfoJson;
+ authInfoJson.Parse(readBuffer.c_str());
+
+ if (authInfoJson.HasParseError())
+ {
+ spdlog::error(
+ "Failed reading masterserver authentication response: encountered parse error \"{}\"",
+ rapidjson::GetParseError_En(authInfoJson.GetParseError()));
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!authInfoJson.IsObject())
+ {
+ spdlog::error("Failed reading masterserver authentication response: root object is not an object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (authInfoJson.HasMember("error"))
+ {
+ spdlog::error("Failed reading masterserver response: got fastify error response");
+ spdlog::error(readBuffer);
+
+ if (authInfoJson["error"].HasMember("enum"))
+ m_sAuthFailureReason = authInfoJson["error"]["enum"].GetString();
+ else
+ m_sAuthFailureReason = "No error message provided";
+
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!authInfoJson["success"].IsTrue())
+ {
+ spdlog::error("Authentication with masterserver failed: \"success\" is not true");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!authInfoJson.HasMember("success") || !authInfoJson.HasMember("id") || !authInfoJson["id"].IsString() ||
+ !authInfoJson.HasMember("authToken") || !authInfoJson["authToken"].IsString() ||
+ !authInfoJson.HasMember("persistentData") || !authInfoJson["persistentData"].IsArray())
+ {
+ spdlog::error("Failed reading masterserver authentication response: malformed json object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ RemoteAuthData newAuthData {};
+ strncpy_s(newAuthData.uid, sizeof(newAuthData.uid), authInfoJson["id"].GetString(), sizeof(newAuthData.uid) - 1);
+
+ newAuthData.pdataSize = authInfoJson["persistentData"].GetArray().Size();
+ newAuthData.pdata = new char[newAuthData.pdataSize];
+ // memcpy(newAuthData.pdata, authInfoJson["persistentData"].GetString(), newAuthData.pdataSize);
+
+ int i = 0;
+ // note: persistentData is a uint8array because i had problems getting strings to behave, it sucks but it's just how it be
+ // unfortunately potentially refactor later
+ for (auto& byte : authInfoJson["persistentData"].GetArray())
+ {
+ if (!byte.IsUint() || byte.GetUint() > 255)
+ {
+ spdlog::error("Failed reading masterserver authentication response: malformed json object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ newAuthData.pdata[i++] = static_cast<char>(byte.GetUint());
+ }
+
+ std::lock_guard<std::mutex> guard(g_pServerAuthentication->m_AuthDataMutex);
+ g_pServerAuthentication->m_RemoteAuthenticationData.clear();
+ g_pServerAuthentication->m_RemoteAuthenticationData.insert(
+ std::make_pair(authInfoJson["authToken"].GetString(), newAuthData));
+
+ m_bSuccessfullyAuthenticatedWithGameServer = true;
+ }
+ else
+ {
+ spdlog::error("Failed authenticating with own server: error {}", curl_easy_strerror(result));
+ m_bSuccessfullyConnected = false;
+ m_bSuccessfullyAuthenticatedWithGameServer = false;
+ m_bScriptAuthenticatingWithGameServer = false;
+ }
+
+ REQUEST_END_CLEANUP:
+ m_bAuthenticatingWithGameServer = false;
+ m_bScriptAuthenticatingWithGameServer = false;
+
+ if (m_bNewgameAfterSelfAuth)
+ {
+ // pretty sure this is threadsafe?
+ R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "ns_end_reauth_and_leave_to_lobby", R2::cmd_source_t::kCommandSrcCode);
+ m_bNewgameAfterSelfAuth = false;
+ }
+
+ curl_easy_cleanup(curl);
+ });
+
+ requestThread.detach();
+}
+
+void MasterServerManager::AuthenticateWithServer(const char* uid, const char* playerToken, const char* serverId, const char* password)
+{
+ // dont wait, just stop if we're trying to do 2 auth requests at once
+ if (m_bAuthenticatingWithGameServer)
+ return;
+
+ m_bAuthenticatingWithGameServer = true;
+ m_bScriptAuthenticatingWithGameServer = true;
+ m_bSuccessfullyAuthenticatedWithGameServer = false;
+
+ std::string uidStr(uid);
+ std::string tokenStr(playerToken);
+ std::string serverIdStr(serverId);
+ std::string passwordStr(password);
+
+ std::thread requestThread(
+ [this, uidStr, tokenStr, serverIdStr, passwordStr]()
+ {
+ // esnure that any persistence saving is done, so we know masterserver has newest
+ while (m_bSavingPersistentData)
+ Sleep(100);
+
+ spdlog::info("Attempting authentication with server of id \"{}\"", serverIdStr);
+
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+
+ std::string readBuffer;
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+
+ {
+ char* escapedPassword = curl_easy_escape(curl, passwordStr.c_str(), passwordStr.length());
+
+ curl_easy_setopt(
+ curl,
+ CURLOPT_URL,
+ fmt::format(
+ "{}/client/auth_with_server?id={}&playerToken={}&server={}&password={}",
+ Cvar_ns_masterserver_hostname->GetString(),
+ uidStr,
+ tokenStr,
+ serverIdStr,
+ escapedPassword)
+ .c_str());
+
+ curl_free(escapedPassword);
+ }
+
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ {
+ m_bSuccessfullyConnected = true;
+
+ rapidjson_document connectionInfoJson;
+ connectionInfoJson.Parse(readBuffer.c_str());
+
+ if (connectionInfoJson.HasParseError())
+ {
+ spdlog::error(
+ "Failed reading masterserver authentication response: encountered parse error \"{}\"",
+ rapidjson::GetParseError_En(connectionInfoJson.GetParseError()));
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!connectionInfoJson.IsObject())
+ {
+ spdlog::error("Failed reading masterserver authentication response: root object is not an object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (connectionInfoJson.HasMember("error"))
+ {
+ spdlog::error("Failed reading masterserver response: got fastify error response");
+ spdlog::error(readBuffer);
+
+ if (connectionInfoJson["error"].HasMember("enum"))
+ m_sAuthFailureReason = connectionInfoJson["error"]["enum"].GetString();
+ else
+ m_sAuthFailureReason = "No error message provided";
+
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!connectionInfoJson["success"].IsTrue())
+ {
+ spdlog::error("Authentication with masterserver failed: \"success\" is not true");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!connectionInfoJson.HasMember("success") || !connectionInfoJson.HasMember("ip") ||
+ !connectionInfoJson["ip"].IsString() || !connectionInfoJson.HasMember("port") ||
+ !connectionInfoJson["port"].IsNumber() || !connectionInfoJson.HasMember("authToken") ||
+ !connectionInfoJson["authToken"].IsString())
+ {
+ spdlog::error("Failed reading masterserver authentication response: malformed json object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ m_pendingConnectionInfo.ip.S_un.S_addr = inet_addr(connectionInfoJson["ip"].GetString());
+ m_pendingConnectionInfo.port = (unsigned short)connectionInfoJson["port"].GetUint();
+
+ strncpy_s(
+ m_pendingConnectionInfo.authToken,
+ sizeof(m_pendingConnectionInfo.authToken),
+ connectionInfoJson["authToken"].GetString(),
+ sizeof(m_pendingConnectionInfo.authToken) - 1);
+
+ m_bHasPendingConnectionInfo = true;
+ m_bSuccessfullyAuthenticatedWithGameServer = true;
+ }
+ else
+ {
+ spdlog::error("Failed authenticating with server: error {}", curl_easy_strerror(result));
+ m_bSuccessfullyConnected = false;
+ m_bSuccessfullyAuthenticatedWithGameServer = false;
+ m_bScriptAuthenticatingWithGameServer = false;
+ }
+
+ REQUEST_END_CLEANUP:
+ m_bAuthenticatingWithGameServer = false;
+ m_bScriptAuthenticatingWithGameServer = false;
+ curl_easy_cleanup(curl);
+ });
+
+ requestThread.detach();
+}
+
+void MasterServerManager::WritePlayerPersistentData(const char* playerId, const char* pdata, size_t pdataSize)
+{
+ // still call this if we don't have a server id, since lobbies that aren't port forwarded need to be able to call it
+ m_bSavingPersistentData = true;
+ if (!pdataSize)
+ {
+ spdlog::warn("attempted to write pdata of size 0!");
+ return;
+ }
+
+ std::string strPlayerId(playerId);
+ std::string strPdata(pdata, pdataSize);
+
+ std::thread requestThread(
+ [this, strPlayerId, strPdata, pdataSize]
+ {
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+
+ std::string readBuffer;
+ curl_easy_setopt(
+ curl,
+ CURLOPT_URL,
+ fmt::format(
+ "{}/accounts/write_persistence?id={}&serverId={}",
+ Cvar_ns_masterserver_hostname->GetString(),
+ strPlayerId,
+ m_sOwnServerId)
+ .c_str());
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+
+ curl_mime* mime = curl_mime_init(curl);
+ curl_mimepart* part = curl_mime_addpart(mime);
+
+ curl_mime_data(part, strPdata.c_str(), pdataSize);
+ curl_mime_name(part, "pdata");
+ curl_mime_filename(part, "file.pdata");
+ curl_mime_type(part, "application/octet-stream");
+
+ curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ m_bSuccessfullyConnected = true;
+ else
+ m_bSuccessfullyConnected = false;
+
+ curl_easy_cleanup(curl);
+
+ m_bSavingPersistentData = false;
+ });
+
+ requestThread.detach();
+}
+
+class MasterServerPresenceReporter : public ServerPresenceReporter
+{
+ const int MAX_REGISTRATION_ATTEMPTS = 5;
+
+ bool m_bShouldTryRegisterServer;
+ bool m_bHasAddServerRequest;
+ int m_nNumRegistrationAttempts;
+
+ void CreatePresence(const ServerPresence* pServerPresence) override
+ {
+ m_bShouldTryRegisterServer = true;
+ m_bHasAddServerRequest = false;
+ m_nNumRegistrationAttempts = 0;
+ }
+
+ void ReportPresence(const ServerPresence* pServerPresence) override
+ {
+ // make a copy of presence for multithreading purposes
+ ServerPresence threadedPresence(pServerPresence);
+
+ if (!*g_pMasterServerManager->m_sOwnServerId)
+ {
+ if (m_bShouldTryRegisterServer && !m_bHasAddServerRequest)
+ {
+ // add server
+ std::thread addServerThread(
+ [this, threadedPresence]
+ {
+ g_pMasterServerManager->m_sOwnServerId[0] = 0;
+ g_pMasterServerManager->m_sOwnServerAuthToken[0] = 0;
+
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+
+ std::string readBuffer;
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+
+ curl_mime* mime = curl_mime_init(curl);
+ curl_mimepart* part = curl_mime_addpart(mime);
+
+ curl_mime_data(
+ part, g_pMasterServerManager->m_sOwnModInfoJson.c_str(), g_pMasterServerManager->m_sOwnModInfoJson.size());
+ curl_mime_name(part, "modinfo");
+ curl_mime_filename(part, "modinfo.json");
+ curl_mime_type(part, "application/json");
+
+ curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+
+ // format every paramter because computers hate me
+ {
+ char* nameEscaped = curl_easy_escape(curl, threadedPresence.m_sServerName.c_str(), NULL);
+ char* descEscaped = curl_easy_escape(curl, threadedPresence.m_sServerDesc.c_str(), NULL);
+ char* mapEscaped = curl_easy_escape(curl, threadedPresence.m_MapName, NULL);
+ char* playlistEscaped = curl_easy_escape(curl, threadedPresence.m_PlaylistName, NULL);
+ char* passwordEscaped = curl_easy_escape(curl, threadedPresence.m_Password, NULL);
+
+ curl_easy_setopt(
+ curl,
+ CURLOPT_URL,
+ fmt::format(
+ "{}/server/"
+ "add_server?port={}&authPort={}&name={}&description={}&map={}&playlist={}&maxPlayers={}&password={}",
+ Cvar_ns_masterserver_hostname->GetString(),
+ threadedPresence.m_iPort,
+ threadedPresence.m_iAuthPort,
+ nameEscaped,
+ descEscaped,
+ mapEscaped,
+ playlistEscaped,
+ threadedPresence.m_iMaxPlayers,
+ passwordEscaped)
+ .c_str());
+
+ curl_free(nameEscaped);
+ curl_free(descEscaped);
+ curl_free(mapEscaped);
+ curl_free(playlistEscaped);
+ curl_free(passwordEscaped);
+ }
+
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ {
+ g_pMasterServerManager->m_bSuccessfullyConnected = true;
+
+ rapidjson_document serverAddedJson;
+ serverAddedJson.Parse(readBuffer.c_str());
+
+ if (serverAddedJson.HasParseError())
+ {
+ spdlog::error(
+ "Failed reading masterserver authentication response: encountered parse error \"{}\"",
+ rapidjson::GetParseError_En(serverAddedJson.GetParseError()));
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!serverAddedJson.IsObject())
+ {
+ spdlog::error("Failed reading masterserver authentication response: root object is not an object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (serverAddedJson.HasMember("error"))
+ {
+ spdlog::error("Failed reading masterserver response: got fastify error response");
+ spdlog::error(readBuffer);
+
+ if (serverAddedJson["error"].HasMember("enum") &&
+ !strcmp(serverAddedJson["error"]["enum"].GetString(), "DUPLICATE_SERVER"))
+ {
+ if (++m_nNumRegistrationAttempts == MAX_REGISTRATION_ATTEMPTS)
+ m_bShouldTryRegisterServer = false;
+
+ goto REQUEST_END_CLEANUP_RETRY;
+ }
+
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!serverAddedJson["success"].IsTrue())
+ {
+ spdlog::error("Adding server to masterserver failed: \"success\" is not true");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ if (!serverAddedJson.HasMember("id") || !serverAddedJson["id"].IsString() ||
+ !serverAddedJson.HasMember("serverAuthToken") || !serverAddedJson["serverAuthToken"].IsString())
+ {
+ spdlog::error("Failed reading masterserver response: malformed json object");
+ goto REQUEST_END_CLEANUP;
+ }
+
+ strncpy_s(
+ g_pMasterServerManager->m_sOwnServerId,
+ sizeof(g_pMasterServerManager->m_sOwnServerId),
+ serverAddedJson["id"].GetString(),
+ sizeof(g_pMasterServerManager->m_sOwnServerId) - 1);
+
+ strncpy_s(
+ g_pMasterServerManager->m_sOwnServerAuthToken,
+ sizeof(g_pMasterServerManager->m_sOwnServerAuthToken),
+ serverAddedJson["serverAuthToken"].GetString(),
+ sizeof(g_pMasterServerManager->m_sOwnServerAuthToken) - 1);
+ }
+ else
+ {
+ spdlog::error("Failed adding self to server list: error {}", curl_easy_strerror(result));
+ g_pMasterServerManager->m_bSuccessfullyConnected = false;
+ }
+
+ REQUEST_END_CLEANUP:
+ m_bShouldTryRegisterServer = false;
+
+ REQUEST_END_CLEANUP_RETRY:
+ m_bHasAddServerRequest = false;
+
+ curl_easy_cleanup(curl);
+ curl_mime_free(mime);
+ });
+
+ m_bHasAddServerRequest = true;
+ addServerThread.detach();
+ }
+ }
+ else
+ {
+ // update server
+ std::thread updateServerThread(
+ [threadedPresence]
+ {
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+
+ std::string readBuffer;
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
+
+ // send all registration info so we have all necessary info to reregister our server if masterserver goes down,
+ // without a restart this isn't threadsafe :terror:
+ {
+ char* nameEscaped = curl_easy_escape(curl, threadedPresence.m_sServerName.c_str(), NULL);
+ char* descEscaped = curl_easy_escape(curl, threadedPresence.m_sServerDesc.c_str(), NULL);
+ char* mapEscaped = curl_easy_escape(curl, threadedPresence.m_MapName, NULL);
+ char* playlistEscaped = curl_easy_escape(curl, threadedPresence.m_PlaylistName, NULL);
+ char* passwordEscaped = curl_easy_escape(curl, threadedPresence.m_Password, NULL);
+
+ curl_easy_setopt(
+ curl,
+ CURLOPT_URL,
+ fmt::format(
+ "{}/server/"
+ "update_values?id={}&port={}&authPort={}&name={}&description={}&map={}&playlist={}&playerCount={}&"
+ "maxPlayers={}&password={}",
+ Cvar_ns_masterserver_hostname->GetString(),
+ g_pMasterServerManager->m_sOwnServerId,
+ threadedPresence.m_iPort,
+ threadedPresence.m_iAuthPort,
+ nameEscaped,
+ descEscaped,
+ mapEscaped,
+ playlistEscaped,
+ threadedPresence.m_iPlayerCount,
+ threadedPresence.m_iMaxPlayers,
+ passwordEscaped)
+ .c_str());
+
+ curl_free(nameEscaped);
+ curl_free(descEscaped);
+ curl_free(mapEscaped);
+ curl_free(playlistEscaped);
+ curl_free(passwordEscaped);
+ }
+
+ curl_mime* mime = curl_mime_init(curl);
+ curl_mimepart* part = curl_mime_addpart(mime);
+
+ curl_mime_data(
+ part, g_pMasterServerManager->m_sOwnModInfoJson.c_str(), g_pMasterServerManager->m_sOwnModInfoJson.size());
+ curl_mime_name(part, "modinfo");
+ curl_mime_filename(part, "modinfo.json");
+ curl_mime_type(part, "application/json");
+
+ curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ {
+ rapidjson_document serverAddedJson;
+ serverAddedJson.Parse(readBuffer.c_str());
+
+ if (!serverAddedJson.HasParseError() && serverAddedJson.IsObject())
+ {
+ if (serverAddedJson.HasMember("id") && serverAddedJson["id"].IsString())
+ {
+ strncpy_s(
+ g_pMasterServerManager->m_sOwnServerId,
+ sizeof(g_pMasterServerManager->m_sOwnServerId),
+ serverAddedJson["id"].GetString(),
+ sizeof(g_pMasterServerManager->m_sOwnServerId) - 1);
+ }
+
+ if (serverAddedJson.HasMember("serverAuthToken") && serverAddedJson["serverAuthToken"].IsString())
+ {
+
+ strncpy_s(
+ g_pMasterServerManager->m_sOwnServerAuthToken,
+ sizeof(g_pMasterServerManager->m_sOwnServerAuthToken),
+ serverAddedJson["serverAuthToken"].GetString(),
+ sizeof(g_pMasterServerManager->m_sOwnServerAuthToken) - 1);
+ }
+ }
+ }
+ else
+ spdlog::warn("Heartbeat failed with error {}", curl_easy_strerror(result));
+
+ curl_easy_cleanup(curl);
+ });
+ updateServerThread.detach();
+ }
+ }
+
+ void DestroyPresence(const ServerPresence* pServerPresence) override
+ {
+ // dont call this if we don't have a server id
+ if (!*g_pMasterServerManager->m_sOwnServerId)
+ return;
+
+ std::thread requestThread(
+ [this]
+ {
+ CURL* curl = curl_easy_init();
+ SetCommonHttpClientOptions(curl);
+
+ std::string readBuffer;
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+ curl_easy_setopt(
+ curl,
+ CURLOPT_URL,
+ fmt::format(
+ "{}/server/remove_server?id={}", Cvar_ns_masterserver_hostname->GetString(), g_pMasterServerManager->m_sOwnServerId)
+ .c_str());
+
+ *g_pMasterServerManager->m_sOwnServerId = 0;
+ CURLcode result = curl_easy_perform(curl);
+
+ if (result == CURLcode::CURLE_OK)
+ g_pMasterServerManager->m_bSuccessfullyConnected = true;
+ else
+ g_pMasterServerManager->m_bSuccessfullyConnected = false;
+
+ curl_easy_cleanup(curl);
+ });
+
+ requestThread.detach();
+ }
+};
+
+void ConCommand_ns_fetchservers(const CCommand& args)
+{
+ g_pMasterServerManager->RequestServerList();
+}
+
+MasterServerManager::MasterServerManager() : m_pendingConnectionInfo {}, m_sOwnServerId {""}, m_sOwnClientAuthToken {""} {}
+
+ON_DLL_LOAD_RELIESON("engine.dll", MasterServer, (ConCommand, ServerPresence), (CModule module))
+{
+ g_pMasterServerManager = new MasterServerManager;
+
+ Cvar_ns_masterserver_hostname = new ConVar("ns_masterserver_hostname", "127.0.0.1", FCVAR_NONE, "");
+ Cvar_ns_curl_log_enable = new ConVar("ns_curl_log_enable", "0", FCVAR_NONE, "Whether curl should log to the console");
+
+ RegisterConCommand("ns_fetchservers", ConCommand_ns_fetchservers, "Fetch all servers from the masterserver", FCVAR_CLIENTDLL);
+
+ MasterServerPresenceReporter* presenceReporter = new MasterServerPresenceReporter;
+ g_pServerPresence->AddPresenceReporter(presenceReporter);
+}
diff --git a/NorthstarDLL/masterserver.h b/NorthstarDLL/masterserver.h
new file mode 100644
index 00000000..5a4e2a91
--- /dev/null
+++ b/NorthstarDLL/masterserver.h
@@ -0,0 +1,126 @@
+#pragma once
+#include "convar.h"
+#include "serverpresence.h"
+#include <winsock2.h>
+#include <string>
+#include <cstring>
+
+extern ConVar* Cvar_ns_masterserver_hostname;
+extern ConVar* Cvar_ns_curl_log_enable;
+
+struct RemoteModInfo
+{
+ public:
+ std::string Name;
+ std::string Version;
+};
+
+class RemoteServerInfo
+{
+ public:
+ char id[33]; // 32 bytes + nullterminator
+
+ // server info
+ char name[64];
+ std::string description;
+ char map[32];
+ char playlist[16];
+ std::vector<RemoteModInfo> requiredMods;
+
+ int playerCount;
+ int maxPlayers;
+
+ // connection stuff
+ bool requiresPassword;
+
+ public:
+ RemoteServerInfo(
+ const char* newId,
+ const char* newName,
+ const char* newDescription,
+ const char* newMap,
+ const char* newPlaylist,
+ int newPlayerCount,
+ int newMaxPlayers,
+ bool newRequiresPassword);
+};
+
+struct RemoteServerConnectionInfo
+{
+ public:
+ char authToken[32];
+
+ in_addr ip;
+ unsigned short port;
+};
+
+struct MainMenuPromoData
+{
+ public:
+ std::string newInfoTitle1;
+ std::string newInfoTitle2;
+ std::string newInfoTitle3;
+
+ std::string largeButtonTitle;
+ std::string largeButtonText;
+ std::string largeButtonUrl;
+ int largeButtonImageIndex;
+
+ std::string smallButton1Title;
+ std::string smallButton1Url;
+ int smallButton1ImageIndex;
+
+ std::string smallButton2Title;
+ std::string smallButton2Url;
+ int smallButton2ImageIndex;
+};
+
+class MasterServerManager
+{
+ private:
+ bool m_bRequestingServerList = false;
+ bool m_bAuthenticatingWithGameServer = false;
+
+ public:
+ char m_sOwnServerId[33];
+ char m_sOwnServerAuthToken[33];
+ char m_sOwnClientAuthToken[33];
+
+ std::string m_sOwnModInfoJson;
+
+ bool m_bOriginAuthWithMasterServerDone = false;
+ bool m_bOriginAuthWithMasterServerInProgress = false;
+
+ bool m_bRequireClientAuth = false;
+ bool m_bSavingPersistentData = false;
+
+ bool m_bScriptRequestingServerList = false;
+ bool m_bSuccessfullyConnected = true;
+
+ bool m_bNewgameAfterSelfAuth = false;
+ bool m_bScriptAuthenticatingWithGameServer = false;
+ bool m_bSuccessfullyAuthenticatedWithGameServer = false;
+ std::string m_sAuthFailureReason {};
+
+ bool m_bHasPendingConnectionInfo = false;
+ RemoteServerConnectionInfo m_pendingConnectionInfo;
+
+ std::vector<RemoteServerInfo> m_vRemoteServers;
+
+ bool m_bHasMainMenuPromoData = false;
+ MainMenuPromoData m_sMainMenuPromoData;
+
+ public:
+ MasterServerManager();
+
+ void ClearServerList();
+ void RequestServerList();
+ void RequestMainMenuPromos();
+ void AuthenticateOriginWithMasterServer(const char* uid, const char* originToken);
+ void AuthenticateWithOwnServer(const char* uid, const char* playerToken);
+ void AuthenticateWithServer(const char* uid, const char* playerToken, const char* serverId, const char* password);
+ void WritePlayerPersistentData(const char* playerId, const char* pdata, size_t pdataSize);
+};
+
+extern MasterServerManager* g_pMasterServerManager;
+extern ConVar* Cvar_ns_masterserver_hostname;
diff --git a/NorthstarDLL/maxplayers.cpp b/NorthstarDLL/maxplayers.cpp
new file mode 100644
index 00000000..ece8d14b
--- /dev/null
+++ b/NorthstarDLL/maxplayers.cpp
@@ -0,0 +1,645 @@
+#include "pch.h"
+#include "tier0.h"
+#include "maxplayers.h"
+
+AUTOHOOK_INIT()
+
+// never set this to anything below 32
+#define NEW_MAX_PLAYERS 64
+// dg note: the theoretical limit is actually 100, 76 works without entity issues, and 64 works without clientside prediction issues.
+
+#define PAD_NUMBER(number, boundary) (((number) + ((boundary)-1)) / (boundary)) * (boundary)
+
+// this is horrible
+constexpr int PlayerResource_Name_Start = 0; // Start of modded allocated space.
+constexpr int PlayerResource_Name_Size = ((NEW_MAX_PLAYERS + 1) * 8); // const char* m_szName[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_Ping_Start = PlayerResource_Name_Start + PlayerResource_Name_Size;
+constexpr int PlayerResource_Ping_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iPing[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_Team_Start = PlayerResource_Ping_Start + PlayerResource_Ping_Size;
+constexpr int PlayerResource_Team_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iTeam[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_PRHealth_Start = PlayerResource_Team_Start + PlayerResource_Team_Size;
+constexpr int PlayerResource_PRHealth_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iPRHealth[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_Connected_Start = PlayerResource_PRHealth_Start + PlayerResource_PRHealth_Size;
+constexpr int PlayerResource_Connected_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool) m_bConnected[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_Alive_Start = PlayerResource_Connected_Start + PlayerResource_Connected_Size;
+constexpr int PlayerResource_Alive_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool) m_bAlive[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_BoolStats_Start = PlayerResource_Alive_Start + PlayerResource_Alive_Size;
+constexpr int PlayerResource_BoolStats_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool idk) m_boolStats[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_KillStats_Start = PlayerResource_BoolStats_Start + PlayerResource_BoolStats_Size;
+constexpr int PlayerResource_KillStats_Length = PAD_NUMBER((NEW_MAX_PLAYERS + 1) * 6, 4);
+constexpr int PlayerResource_KillStats_Size = (PlayerResource_KillStats_Length * 6); // int m_killStats[MAX_PLAYERS + 1][6];
+
+constexpr int PlayerResource_ScoreStats_Start = PlayerResource_KillStats_Start + PlayerResource_KillStats_Size;
+constexpr int PlayerResource_ScoreStats_Length = PAD_NUMBER((NEW_MAX_PLAYERS + 1) * 5, 4);
+constexpr int PlayerResource_ScoreStats_Size = (PlayerResource_ScoreStats_Length * 4); // int m_scoreStats[MAX_PLAYERS + 1][5];
+
+// must be the usage of the last field to account for any possible paddings
+constexpr int PlayerResource_TotalSize = PlayerResource_ScoreStats_Start + PlayerResource_ScoreStats_Size;
+
+constexpr int Team_PlayerArray_AddedLength = NEW_MAX_PLAYERS - 32;
+constexpr int Team_PlayerArray_AddedSize = PAD_NUMBER(Team_PlayerArray_AddedLength * 8, 4);
+constexpr int Team_AddedSize = Team_PlayerArray_AddedSize;
+
+bool MaxPlayersIncreaseEnabled()
+{
+ static bool bMaxPlayersIncreaseEnabled = Tier0::CommandLine()->CheckParm("-experimentalmaxplayersincrease");
+ return bMaxPlayersIncreaseEnabled;
+}
+
+// should we use R2 for this? not sure
+namespace R2 // use R2 namespace for game funcs
+{
+ int GetMaxPlayers()
+ {
+ if (MaxPlayersIncreaseEnabled())
+ return NEW_MAX_PLAYERS;
+
+ return 32;
+ }
+} // namespace R2
+
+template <class T> void ChangeOffset(MemoryAddress addr, unsigned int offset)
+{
+ addr.Patch((BYTE*)&offset, sizeof(T));
+}
+
+// clang-format off
+AUTOHOOK(StringTables_CreateStringTable, engine.dll + 0x22E220,
+void*,, (void* thisptr, const char* name, int maxentries, int userdatafixedsize, int userdatanetworkbits, int flags))
+// clang-format on
+{
+ // Change the amount of entries to account for a bigger player amount
+ if (!strcmp(name, "userinfo"))
+ {
+ int maxPlayersPowerOf2 = 1;
+ while (maxPlayersPowerOf2 < NEW_MAX_PLAYERS)
+ maxPlayersPowerOf2 <<= 1;
+
+ maxentries = maxPlayersPowerOf2;
+ }
+
+ return StringTables_CreateStringTable(thisptr, name, maxentries, userdatafixedsize, userdatanetworkbits, flags);
+}
+
+ON_DLL_LOAD("engine.dll", MaxPlayersOverride_Engine, (CModule module))
+{
+ if (!MaxPlayersIncreaseEnabled())
+ return;
+
+ AUTOHOOK_DISPATCH_MODULE(engine.dll)
+
+ // patch GetPlayerLimits to ignore the boundary limit
+ module.Offset(0x116458).Patch("0xEB"); // jle => jmp
+
+ // patch ED_Alloc to change nFirstIndex
+ ChangeOffset<int>(module.Offset(0x18F46C + 1), NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1)
+
+ // patch CGameServer::SpawnServer to change GetMaxClients inline
+ ChangeOffset<int>(module.Offset(0x119543 + 2), NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1)
+
+ // patch CGameServer::SpawnServer to change for loop
+ ChangeOffset<unsigned char>(module.Offset(0x11957F + 2), NEW_MAX_PLAYERS); // original: 32
+
+ // patch CGameServer::SpawnServer to change for loop (there are two)
+ ChangeOffset<unsigned char>(module.Offset(0x119586 + 2), NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1)
+
+ // patch max players somewhere in CClientState
+ ChangeOffset<unsigned char>(module.Offset(0x1A162C + 2), NEW_MAX_PLAYERS - 1); // original: 31 (32 - 1)
+
+ // patch max players in userinfo stringtable creation
+ /*{
+ int maxPlayersPowerOf2 = 1;
+ while (maxPlayersPowerOf2 < NEW_MAX_PLAYERS)
+ maxPlayersPowerOf2 <<= 1;
+ ChangeOffset<unsigned char>((char*)baseAddress + 0x114B79 + 3, maxPlayersPowerOf2); // original: 32
+ }*/
+ // this is not supposed to work at all but it does on 64 players (how)
+ // proper fix below
+
+ // patch max players in userinfo stringtable creation loop
+ ChangeOffset<unsigned char>(module.Offset(0x114C48 + 2), NEW_MAX_PLAYERS); // original: 32
+
+ // do not load prebaked SendTable message list
+ module.Offset(0x75859).Patch("EB"); // jnz -> jmp
+}
+
+typedef void (*RunUserCmds_Type)(bool a1, float a2);
+RunUserCmds_Type RunUserCmds_Original;
+
+HMODULE serverBase = 0;
+auto RandomIntZeroMax = (__int64(__fastcall*)())0;
+
+// lazy rebuild
+// clang-format off
+AUTOHOOK(RunUserCmds, server.dll + 0x483D10,
+void,, (bool a1, float a2))
+// clang-format on
+{
+ unsigned char v3; // bl
+ int v5; // er14
+ int i; // edi
+ __int64 v7; // rax
+ DWORD* v8; // rbx
+ int v9; // edi
+ __int64* v10; // rsi
+ __int64 v11; // rax
+ int v12; // er12
+ __int64 v13; // rdi
+ int v14; // ebx
+ int v15; // eax
+ __int64 v16; // r8
+ int v17; // edx
+ char v18; // r15
+ char v19; // bp
+ int v20; // esi
+ __int64* v21; // rdi
+ __int64 v22; // rcx
+ bool v23; // al
+ __int64 v24; // rax
+ __int64 v25[NEW_MAX_PLAYERS]; // [rsp+20h] [rbp-138h] BYREF
+
+ uintptr_t base = (__int64)serverBase;
+ auto g_pGlobals = *(__int64*)(base + 0xBFBE08);
+ __int64 globals = g_pGlobals;
+
+ auto g_pEngineServer = *(__int64*)(base + 0xBFBD98);
+
+ auto qword_1814D9648 = *(__int64*)(base + 0x14D9648);
+ auto qword_1814DA408 = *(__int64*)(base + 0x14DA408);
+ auto qword_1812107E8 = *(__int64*)(base + 0x12107E8);
+ auto qword_1812105A8 = *(__int64*)(base + 0x12105A8);
+
+ auto UTIL_PlayerByIndex = (__int64(__fastcall*)(int index))(base + 0x26AA10);
+ auto sub_180485590 = (void(__fastcall*)(__int64))(base + 0x485590);
+ auto sub_18058CD80 = (void(__fastcall*)(__int64))(base + 0x58CD80);
+ auto sub_1805A6D90 = (void(__fastcall*)(__int64))(base + 0x5A6D90);
+ auto sub_1805A6E50 = (bool(__fastcall*)(__int64, int, char))(base + 0x5A6E50);
+ auto sub_1805A6C20 = (void(__fastcall*)(__int64))(base + 0x5A6C20);
+
+ v3 = *(unsigned char*)(g_pGlobals + 73);
+ if (*(DWORD*)(qword_1814D9648 + 92) &&
+ ((*(unsigned __int8(__fastcall**)(__int64))(*(__int64*)g_pEngineServer + 32))(g_pEngineServer) ||
+ !*(DWORD*)(qword_1814DA408 + 92)) &&
+ v3)
+ {
+ globals = g_pGlobals;
+ v5 = 1;
+ for (i = 1; i <= *(DWORD*)(g_pGlobals + 52); ++i)
+ {
+ v7 = UTIL_PlayerByIndex(i);
+ v8 = (DWORD*)v7;
+ if (v7)
+ {
+ *(__int64*)(base + 0x1210420) = v7;
+ *(float*)(g_pGlobals + 16) = a2;
+ if (!a1)
+ sub_18058CD80(v7);
+ sub_1805A6D90((__int64)v8);
+ }
+ globals = g_pGlobals;
+ }
+ memset(v25, 0, sizeof(v25));
+ v9 = 0;
+ if (*(int*)(globals + 52) > 0)
+ {
+ v10 = v25;
+ do
+ {
+ v11 = UTIL_PlayerByIndex(++v9);
+ globals = g_pGlobals;
+ *v10++ = v11;
+ } while (v9 < *(DWORD*)(globals + 52));
+ }
+ v12 = *(DWORD*)(qword_1812107E8 + 92);
+ if (*(DWORD*)(qword_1812105A8 + 92))
+ {
+ v13 = *(DWORD*)(globals + 52) - 1;
+ if (v13 >= 1)
+ {
+ v14 = *(DWORD*)(globals + 52);
+ do
+ {
+ v15 = RandomIntZeroMax();
+ v16 = v25[v13--];
+ v17 = v15 % v14--;
+ v25[v13 + 1] = v25[v17];
+ v25[v17] = v16;
+ } while (v13 >= 1);
+ globals = g_pGlobals;
+ }
+ }
+ v18 = 1;
+ do
+ {
+ v19 = 0;
+ v20 = 0;
+ if (*(int*)(globals + 52) > 0)
+ {
+ v21 = v25;
+ do
+ {
+ v22 = *v21;
+ if (*v21)
+ {
+ *(__int64*)(base + 0x1210420) = *v21;
+ *(float*)(globals + 16) = a2;
+ v23 = sub_1805A6E50(v22, v12, v18);
+ globals = g_pGlobals;
+ if (v23)
+ v19 = 1;
+ else
+ *v21 = 0;
+ }
+ ++v20;
+ ++v21;
+ } while (v20 < *(DWORD*)(globals + 52));
+ }
+ v18 = 0;
+ } while (v19);
+ if (*(int*)(globals + 52) >= 1)
+ {
+ do
+ {
+ v24 = UTIL_PlayerByIndex(v5);
+ if (v24)
+ {
+ *(__int64*)(base + 0x1210420) = v24;
+ *(float*)(g_pGlobals + 16) = a2;
+ sub_1805A6C20(v24);
+ }
+ ++v5;
+ } while (v5 <= *(DWORD*)(g_pGlobals + 52));
+ }
+ sub_180485590(*(__int64*)(base + 0xB7B2D8));
+ }
+}
+
+// clang-format off
+AUTOHOOK(SendPropArray2, server.dll + 0x12B130,
+__int64, __fastcall, (__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn, unsigned char unk1))
+// clang-format on
+{
+ // Change the amount of elements to account for a bigger player amount
+ if (!strcmp(name, "\"player_array\""))
+ elements = NEW_MAX_PLAYERS;
+
+ return SendPropArray2(recvProp, elements, flags, name, proxyFn, unk1);
+}
+
+ON_DLL_LOAD("server.dll", MaxPlayersOverride_Server, (CModule module))
+{
+ if (!MaxPlayersIncreaseEnabled())
+ return;
+
+ AUTOHOOK_DISPATCH_MODULE(server.dll)
+
+ // get required data
+ serverBase = (HMODULE)module.m_nAddress;
+ RandomIntZeroMax = (decltype(RandomIntZeroMax))(GetProcAddress(GetModuleHandleA("vstdlib.dll"), "RandomIntZeroMax"));
+
+ // patch max players amount
+ ChangeOffset<unsigned char>(module.Offset(0x9A44D + 3), NEW_MAX_PLAYERS); // 0x20 (32) => 0x80 (128)
+
+ // patch SpawnGlobalNonRewinding to change forced edict index
+ ChangeOffset<unsigned char>(module.Offset(0x2BC403 + 2), NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1)
+
+ constexpr int CPlayerResource_OriginalSize = 4776;
+ constexpr int CPlayerResource_AddedSize = PlayerResource_TotalSize;
+ constexpr int CPlayerResource_ModifiedSize = CPlayerResource_OriginalSize + CPlayerResource_AddedSize;
+
+ // CPlayerResource class allocation function - allocate a bigger amount to fit all new max player data
+ ChangeOffset<unsigned int>(module.Offset(0x5C560A + 1), CPlayerResource_ModifiedSize);
+
+ // DT_PlayerResource::m_iPing SendProp
+ ChangeOffset<unsigned int>(module.Offset(0x5C5059 + 2), CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C50A8 + 2), CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C50E2 + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iPing DataMap
+ ChangeOffset<unsigned int>(module.Offset(0xB94598), CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xB9459C), NEW_MAX_PLAYERS + 1);
+ ChangeOffset<unsigned short>(module.Offset(0xB945C0), PlayerResource_Ping_Size);
+
+ // DT_PlayerResource::m_iTeam SendProp
+ ChangeOffset<unsigned int>(module.Offset(0x5C5110 + 2), CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C519C + 2), CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C517E + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iTeam DataMap
+ ChangeOffset<unsigned int>(module.Offset(0xB94600), CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xB94604), NEW_MAX_PLAYERS + 1);
+ ChangeOffset<unsigned short>(module.Offset(0xB94628), PlayerResource_Team_Size);
+
+ // DT_PlayerResource::m_iPRHealth SendProp
+ ChangeOffset<unsigned int>(module.Offset(0x5C51C0 + 2), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C5204 + 2), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C523E + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iPRHealth DataMap
+ ChangeOffset<unsigned int>(module.Offset(0xB94668), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xB9466C), NEW_MAX_PLAYERS + 1);
+ ChangeOffset<unsigned short>(module.Offset(0xB94690), PlayerResource_PRHealth_Size);
+
+ // DT_PlayerResource::m_bConnected SendProp
+ ChangeOffset<unsigned int>(module.Offset(0x5C526C + 2), CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C52B4 + 2), CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C52EE + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_bConnected DataMap
+ ChangeOffset<unsigned int>(module.Offset(0xB946D0), CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xB946D4), NEW_MAX_PLAYERS + 1);
+ ChangeOffset<unsigned short>(module.Offset(0xB946F8), PlayerResource_Connected_Size);
+
+ // DT_PlayerResource::m_bAlive SendProp
+ ChangeOffset<unsigned int>(module.Offset(0x5C5321 + 2), CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C5364 + 2), CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C539E + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_bAlive DataMap
+ ChangeOffset<unsigned int>(module.Offset(0xB94738), CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xB9473C), NEW_MAX_PLAYERS + 1);
+ ChangeOffset<unsigned short>(module.Offset(0xB94760), PlayerResource_Alive_Size);
+
+ // DT_PlayerResource::m_boolStats SendProp
+ ChangeOffset<unsigned int>(module.Offset(0x5C53CC + 2), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C5414 + 2), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C544E + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_boolStats DataMap
+ ChangeOffset<unsigned int>(module.Offset(0xB947A0), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xB947A4), NEW_MAX_PLAYERS + 1);
+ ChangeOffset<unsigned short>(module.Offset(0xB947C8), PlayerResource_BoolStats_Size);
+
+ // DT_PlayerResource::m_killStats SendProp
+ ChangeOffset<unsigned int>(module.Offset(0x5C547C + 2), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C54E2 + 2), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C54FE + 4), PlayerResource_KillStats_Length);
+
+ // DT_PlayerResource::m_killStats DataMap
+ ChangeOffset<unsigned int>(module.Offset(0xB94808), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xB9480C), PlayerResource_KillStats_Length);
+ ChangeOffset<unsigned short>(module.Offset(0xB94830), PlayerResource_KillStats_Size);
+
+ // DT_PlayerResource::m_scoreStats SendProp
+ ChangeOffset<unsigned int>(module.Offset(0x5C5528 + 2), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C5576 + 2), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C5584 + 4), PlayerResource_ScoreStats_Length);
+
+ // DT_PlayerResource::m_scoreStats DataMap
+ ChangeOffset<unsigned int>(module.Offset(0xB94870), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xB94874), PlayerResource_ScoreStats_Length);
+ ChangeOffset<unsigned short>(module.Offset(0xB94898), PlayerResource_ScoreStats_Size);
+
+ // CPlayerResource::UpdatePlayerData - m_bConnected
+ ChangeOffset<unsigned int>(module.Offset(0x5C66EE + 4), CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C672E + 4), CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_iPing
+ ChangeOffset<unsigned int>(module.Offset(0x5C6394 + 4), CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C63DB + 4), CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_iTeam
+ ChangeOffset<unsigned int>(module.Offset(0x5C63FD + 4), CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C6442 + 4), CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_iPRHealth
+ ChangeOffset<unsigned int>(module.Offset(0x5C645B + 4), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C64A0 + 4), CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_bConnected
+ ChangeOffset<unsigned int>(module.Offset(0x5C64AA + 4), CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C64F0 + 4), CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_bAlive
+ ChangeOffset<unsigned int>(module.Offset(0x5C650A + 4), CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C654F + 4), CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_boolStats
+ ChangeOffset<unsigned int>(module.Offset(0x5C6557 + 4), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C65A5 + 4), CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_scoreStats
+ ChangeOffset<unsigned int>(module.Offset(0x5C65C2 + 3), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C65E3 + 4), CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_killStats
+ ChangeOffset<unsigned int>(module.Offset(0x5C6654 + 3), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x5C665B + 3), CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+
+ *module.Offset(0x14E7390).As<DWORD*>() = 0;
+ auto DT_PlayerResource_Construct = module.Offset(0x5C4FE0).As<__int64(__fastcall*)()>();
+ DT_PlayerResource_Construct();
+
+ constexpr int CTeam_OriginalSize = 3336;
+ constexpr int CTeam_AddedSize = Team_AddedSize;
+ constexpr int CTeam_ModifiedSize = CTeam_OriginalSize + CTeam_AddedSize;
+
+ // CTeam class allocation function - allocate a bigger amount to fit all new team player data
+ ChangeOffset<unsigned int>(module.Offset(0x23924A + 1), CTeam_ModifiedSize);
+
+ // CTeam::CTeam - increase memset length to clean newly allocated data
+ ChangeOffset<unsigned int>(module.Offset(0x2395AE + 2), 256 + CTeam_AddedSize);
+
+ *module.Offset(0xC945A0).As<DWORD*>() = 0;
+ auto DT_Team_Construct = module.Offset(0x238F50).As<__int64(__fastcall*)()>();
+ DT_Team_Construct();
+}
+
+// clang-format off
+AUTOHOOK(RecvPropArray2, client.dll + 0x1CEDA0,
+__int64, __fastcall, (__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn))
+// clang-format on
+{
+ // Change the amount of elements to account for a bigger player amount
+ if (!strcmp(name, "\"player_array\""))
+ elements = NEW_MAX_PLAYERS;
+
+ return RecvPropArray2(recvProp, elements, flags, name, proxyFn);
+}
+
+ON_DLL_LOAD("client.dll", MaxPlayersOverride_Client, (CModule module))
+{
+ if (!MaxPlayersIncreaseEnabled())
+ return;
+
+ AUTOHOOK_DISPATCH_MODULE(client.dll)
+
+ constexpr int C_PlayerResource_OriginalSize = 5768;
+ constexpr int C_PlayerResource_AddedSize = PlayerResource_TotalSize;
+ constexpr int C_PlayerResource_ModifiedSize = C_PlayerResource_OriginalSize + C_PlayerResource_AddedSize;
+
+ // C_PlayerResource class allocation function - allocate a bigger amount to fit all new max player data
+ ChangeOffset<unsigned int>(module.Offset(0x164C41 + 1), C_PlayerResource_ModifiedSize);
+
+ // C_PlayerResource::C_PlayerResource - change loop end value
+ ChangeOffset<unsigned char>(module.Offset(0x1640C4 + 2), NEW_MAX_PLAYERS - 32);
+
+ // C_PlayerResource::C_PlayerResource - change m_szName address
+ ChangeOffset<unsigned int>(
+ module.Offset(0x1640D0 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class
+
+ // C_PlayerResource::C_PlayerResource - change m_szName address
+ ChangeOffset<unsigned int>(
+ module.Offset(0x1640D0 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class
+
+ // C_PlayerResource::C_PlayerResource - increase memset length to clean newly allocated data
+ ChangeOffset<unsigned int>(module.Offset(0x1640D0 + 3), 2244 + C_PlayerResource_AddedSize);
+
+ // C_PlayerResource::UpdatePlayerName - change m_szName address
+ ChangeOffset<unsigned int>(module.Offset(0x16431F + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName - change m_szName address 1
+ ChangeOffset<unsigned int>(module.Offset(0x1645B1 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName - change m_szName address 2
+ ChangeOffset<unsigned int>(module.Offset(0x1645C0 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName - change m_szName address 3
+ ChangeOffset<unsigned int>(module.Offset(0x1645DD + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName address 1
+ ChangeOffset<unsigned int>(module.Offset(0x164B71 + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName address 2
+ ChangeOffset<unsigned int>(module.Offset(0x164B9B + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 1
+ ChangeOffset<unsigned int>(module.Offset(0x164641 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 2
+ ChangeOffset<unsigned int>(module.Offset(0x164650 + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 3
+ ChangeOffset<unsigned int>(module.Offset(0x16466D + 3), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 1
+ ChangeOffset<unsigned int>(module.Offset(0x164BA3 + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 2
+ ChangeOffset<unsigned int>(module.Offset(0x164BCE + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 3
+ ChangeOffset<unsigned int>(module.Offset(0x164BE7 + 4), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::m_szName
+ ChangeOffset<unsigned int>(module.Offset(0xc350f8), C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc350f8 + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource size
+ ChangeOffset<unsigned int>(module.Offset(0x163415 + 6), C_PlayerResource_ModifiedSize);
+
+ // DT_PlayerResource::m_iPing RecvProp
+ ChangeOffset<unsigned int>(module.Offset(0x163492 + 2), C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x1634D6 + 2), C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163515 + 5), NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_iPing
+ ChangeOffset<unsigned int>(module.Offset(0xc35170), C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc35170 + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iTeam RecvProp
+ ChangeOffset<unsigned int>(module.Offset(0x163549 + 2), C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x1635C8 + 2), C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x1635AD + 5), NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_iTeam
+ ChangeOffset<unsigned int>(module.Offset(0xc351e8), C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc351e8 + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iPRHealth RecvProp
+ ChangeOffset<unsigned int>(module.Offset(0x1635F9 + 2), C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163625 + 2), C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163675 + 5), NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_iPRHealth
+ ChangeOffset<unsigned int>(module.Offset(0xc35260), C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc35260 + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_bConnected RecvProp
+ ChangeOffset<unsigned int>(module.Offset(0x1636A9 + 2), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x1636D5 + 2), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163725 + 5), NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_bConnected
+ ChangeOffset<unsigned int>(module.Offset(0xc352d8), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc352d8 + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_bAlive RecvProp
+ ChangeOffset<unsigned int>(module.Offset(0x163759 + 2), C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163785 + 2), C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x1637D5 + 5), NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_bAlive
+ ChangeOffset<unsigned int>(module.Offset(0xc35350), C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc35350 + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_boolStats RecvProp
+ ChangeOffset<unsigned int>(module.Offset(0x163809 + 2), C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163835 + 2), C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163885 + 5), NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_boolStats
+ ChangeOffset<unsigned int>(module.Offset(0xc353c8), C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc353c8 + 4), NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_killStats RecvProp
+ ChangeOffset<unsigned int>(module.Offset(0x1638B3 + 2), C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x1638E5 + 2), C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163935 + 5), PlayerResource_KillStats_Length);
+
+ // C_PlayerResource::m_killStats
+ ChangeOffset<unsigned int>(module.Offset(0xc35440), C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc35440 + 4), PlayerResource_KillStats_Length);
+
+ // DT_PlayerResource::m_scoreStats RecvProp
+ ChangeOffset<unsigned int>(module.Offset(0x163969 + 2), C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x163995 + 2), C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset<unsigned int>(module.Offset(0x1639E5 + 5), PlayerResource_ScoreStats_Length);
+
+ // C_PlayerResource::m_scoreStats
+ ChangeOffset<unsigned int>(module.Offset(0xc354b8), C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset<unsigned short>(module.Offset(0xc354b8 + 4), PlayerResource_ScoreStats_Length);
+
+ // C_PlayerResource::GetPlayerName - change m_bConnected address
+ ChangeOffset<unsigned int>(module.Offset(0x164599 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // C_PlayerResource::GetPlayerName2 (?) - change m_bConnected address
+ ChangeOffset<unsigned int>(module.Offset(0x164629 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_bConnected address
+ ChangeOffset<unsigned int>(module.Offset(0x164B13 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // Some other get name func (that seems to be unused) - change m_bConnected address
+ ChangeOffset<unsigned int>(module.Offset(0x164860 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // Some other get name func 2 (that seems to be unused too) - change m_bConnected address
+ ChangeOffset<unsigned int>(module.Offset(0x164834 + 3), C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ *module.Offset(0xC35068).As<DWORD*>() = 0;
+ auto DT_PlayerResource_Construct = module.Offset(0x163400).As<__int64(__fastcall*)()>();
+ DT_PlayerResource_Construct();
+
+ constexpr int C_Team_OriginalSize = 3200;
+ constexpr int C_Team_AddedSize = Team_AddedSize;
+ constexpr int C_Team_ModifiedSize = C_Team_OriginalSize + C_Team_AddedSize;
+
+ // C_Team class allocation function - allocate a bigger amount to fit all new team player data
+ ChangeOffset<unsigned int>(module.Offset(0x182321 + 1), C_Team_ModifiedSize);
+
+ // C_Team::C_Team - increase memset length to clean newly allocated data
+ ChangeOffset<unsigned int>(module.Offset(0x1804A2 + 2), 256 + C_Team_AddedSize);
+
+ // DT_Team size
+ ChangeOffset<unsigned int>(module.Offset(0xC3AA0C), C_Team_ModifiedSize);
+
+ *module.Offset(0xC3AFF8).As<DWORD*>() = 0;
+ auto DT_Team_Construct = module.Offset(0x17F950).As<__int64(__fastcall*)()>();
+ DT_Team_Construct();
+}
diff --git a/NorthstarDLL/maxplayers.h b/NorthstarDLL/maxplayers.h
new file mode 100644
index 00000000..b251f6a6
--- /dev/null
+++ b/NorthstarDLL/maxplayers.h
@@ -0,0 +1,7 @@
+#pragma once
+
+// should we use R2 for this? not sure
+namespace R2 // use R2 namespace for game funcs
+{
+ int GetMaxPlayers();
+} // namespace R2
diff --git a/NorthstarDedicatedTest/memalloc.cpp b/NorthstarDLL/memalloc.cpp
index 4ba54c73..8c0fafc8 100644
--- a/NorthstarDedicatedTest/memalloc.cpp
+++ b/NorthstarDLL/memalloc.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "memalloc.h"
-#include "gameutils.h"
+#include "tier0.h"
+
+using namespace Tier0;
// TODO: rename to malloc and free after removing statically compiled .libs
@@ -8,9 +10,8 @@ extern "C" void* _malloc_base(size_t n)
{
// allocate into static buffer if g_pMemAllocSingleton isn't initialised
if (!g_pMemAllocSingleton)
- {
- InitialiseTier0GameUtilFunctions(GetModuleHandleA("tier0.dll"));
- }
+ TryCreateGlobalMemAlloc();
+
return g_pMemAllocSingleton->m_vtable->Alloc(g_pMemAllocSingleton, n);
}
@@ -22,19 +23,16 @@ extern "C" void* _malloc_base(size_t n)
extern "C" void _free_base(void* p)
{
if (!g_pMemAllocSingleton)
- {
- spdlog::warn("Trying to free something before g_pMemAllocSingleton was ready, this should never happen");
- InitialiseTier0GameUtilFunctions(GetModuleHandleA("tier0.dll"));
- }
+ TryCreateGlobalMemAlloc();
+
g_pMemAllocSingleton->m_vtable->Free(g_pMemAllocSingleton, p);
}
extern "C" void* _realloc_base(void* oldPtr, size_t size)
{
if (!g_pMemAllocSingleton)
- {
- InitialiseTier0GameUtilFunctions(GetModuleHandleA("tier0.dll"));
- }
+ TryCreateGlobalMemAlloc();
+
return g_pMemAllocSingleton->m_vtable->Realloc(g_pMemAllocSingleton, oldPtr, size);
}
@@ -70,7 +68,7 @@ void* operator new(size_t n)
return _malloc_base(n);
}
-void operator delete(void* p)
+void operator delete(void* p) noexcept
{
_free_base(p);
-} // /FORCE:MULTIPLE \ No newline at end of file
+} // /FORCE:MULTIPLE
diff --git a/NorthstarDedicatedTest/memalloc.h b/NorthstarDLL/memalloc.h
index a1b16ad4..fdd6474b 100644
--- a/NorthstarDedicatedTest/memalloc.h
+++ b/NorthstarDLL/memalloc.h
@@ -11,7 +11,7 @@ extern "C" void _free_base(void* const block);
extern "C" char* _strdup_base(const char* src);
void* operator new(size_t n);
-void operator delete(void* p);
+void operator delete(void* p) noexcept;
// void* malloc(size_t n);
diff --git a/NorthstarDLL/memory.cpp b/NorthstarDLL/memory.cpp
new file mode 100644
index 00000000..2e994fb2
--- /dev/null
+++ b/NorthstarDLL/memory.cpp
@@ -0,0 +1,348 @@
+#include "pch.h"
+#include "memory.h"
+
+MemoryAddress::MemoryAddress() : m_nAddress(0) {}
+MemoryAddress::MemoryAddress(const uintptr_t nAddress) : m_nAddress(nAddress) {}
+MemoryAddress::MemoryAddress(const void* pAddress) : m_nAddress(reinterpret_cast<uintptr_t>(pAddress)) {}
+
+// operators
+MemoryAddress::operator uintptr_t() const
+{
+ return m_nAddress;
+}
+
+MemoryAddress::operator void*() const
+{
+ return reinterpret_cast<void*>(m_nAddress);
+}
+
+MemoryAddress::operator bool() const
+{
+ return m_nAddress != 0;
+}
+
+bool MemoryAddress::operator==(const MemoryAddress& other) const
+{
+ return m_nAddress == other.m_nAddress;
+}
+
+bool MemoryAddress::operator!=(const MemoryAddress& other) const
+{
+ return m_nAddress != other.m_nAddress;
+}
+
+bool MemoryAddress::operator==(const uintptr_t& addr) const
+{
+ return m_nAddress == addr;
+}
+
+bool MemoryAddress::operator!=(const uintptr_t& addr) const
+{
+ return m_nAddress != addr;
+}
+
+MemoryAddress MemoryAddress::operator+(const MemoryAddress& other) const
+{
+ return Offset(other.m_nAddress);
+}
+
+MemoryAddress MemoryAddress::operator-(const MemoryAddress& other) const
+{
+ return MemoryAddress(m_nAddress - other.m_nAddress);
+}
+
+MemoryAddress MemoryAddress::operator+(const uintptr_t& addr) const
+{
+ return Offset(addr);
+}
+
+MemoryAddress MemoryAddress::operator-(const uintptr_t& addr) const
+{
+ return MemoryAddress(m_nAddress - addr);
+}
+
+MemoryAddress MemoryAddress::operator*() const
+{
+ return Deref();
+}
+
+// traversal
+MemoryAddress MemoryAddress::Offset(const uintptr_t nOffset) const
+{
+ return MemoryAddress(m_nAddress + nOffset);
+}
+
+MemoryAddress MemoryAddress::Deref(const int nNumDerefs) const
+{
+ uintptr_t ret = m_nAddress;
+ for (int i = 0; i < nNumDerefs; i++)
+ ret = *reinterpret_cast<uintptr_t*>(ret);
+
+ return MemoryAddress(ret);
+}
+
+// patching
+void MemoryAddress::Patch(const uint8_t* pBytes, const size_t nSize)
+{
+ if (nSize)
+ WriteProcessMemory(GetCurrentProcess(), reinterpret_cast<LPVOID>(m_nAddress), pBytes, nSize, NULL);
+}
+
+void MemoryAddress::Patch(const std::initializer_list<uint8_t> bytes)
+{
+ uint8_t* pBytes = new uint8_t[bytes.size()];
+
+ int i = 0;
+ for (const uint8_t& byte : bytes)
+ pBytes[i++] = byte;
+
+ Patch(pBytes, bytes.size());
+ delete[] pBytes;
+}
+
+inline std::vector<uint8_t> HexBytesToString(const char* pHexString)
+{
+ std::vector<uint8_t> ret;
+
+ int size = strlen(pHexString);
+ for (int i = 0; i < size; i++)
+ {
+ // If this is a space character, ignore it
+ if (isspace(pHexString[i]))
+ continue;
+
+ if (i < size - 1)
+ {
+ BYTE result = 0;
+ for (int j = 0; j < 2; j++)
+ {
+ int val = 0;
+ char c = *(pHexString + i + j);
+ if (c >= 'a')
+ {
+ val = c - 'a' + 0xA;
+ }
+ else if (c >= 'A')
+ {
+ val = c - 'A' + 0xA;
+ }
+ else if (isdigit(c))
+ {
+ val = c - '0';
+ }
+ else
+ {
+ assert(false, "Failed to parse invalid hex string.");
+ val = -1;
+ }
+
+ result += (j == 0) ? val * 16 : val;
+ }
+ ret.push_back(result);
+ }
+
+ i++;
+ }
+
+ return ret;
+}
+
+void MemoryAddress::Patch(const char* pBytes)
+{
+ std::vector<uint8_t> vBytes = HexBytesToString(pBytes);
+ Patch(vBytes.data(), vBytes.size());
+}
+
+void MemoryAddress::NOP(const size_t nSize)
+{
+ uint8_t* pBytes = new uint8_t[nSize];
+
+ memset(pBytes, 0x90, nSize);
+ Patch(pBytes, nSize);
+
+ delete[] pBytes;
+}
+
+bool MemoryAddress::IsMemoryReadable(const size_t nSize)
+{
+ static SYSTEM_INFO sysInfo;
+ if (!sysInfo.dwPageSize)
+ GetSystemInfo(&sysInfo);
+
+ MEMORY_BASIC_INFORMATION memInfo;
+ if (!VirtualQuery(reinterpret_cast<LPCVOID>(m_nAddress), &memInfo, sizeof(memInfo)))
+ return false;
+
+ return memInfo.RegionSize >= nSize && memInfo.State & MEM_COMMIT && !(memInfo.Protect & PAGE_NOACCESS);
+}
+
+CModule::CModule(const HMODULE pModule)
+{
+ MODULEINFO mInfo {0};
+
+ if (pModule && pModule != INVALID_HANDLE_VALUE)
+ GetModuleInformation(GetCurrentProcess(), pModule, &mInfo, sizeof(MODULEINFO));
+
+ m_nModuleSize = static_cast<size_t>(mInfo.SizeOfImage);
+ m_pModuleBase = reinterpret_cast<uintptr_t>(mInfo.lpBaseOfDll);
+ m_nAddress = m_pModuleBase;
+
+ if (!m_nModuleSize || !m_pModuleBase)
+ return;
+
+ m_pDOSHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(m_pModuleBase);
+ m_pNTHeaders = reinterpret_cast<IMAGE_NT_HEADERS64*>(m_pModuleBase + m_pDOSHeader->e_lfanew);
+
+ const IMAGE_SECTION_HEADER* hSection = IMAGE_FIRST_SECTION(m_pNTHeaders); // Get first image section.
+
+ for (WORD i = 0; i < m_pNTHeaders->FileHeader.NumberOfSections; i++) // Loop through the sections.
+ {
+ const IMAGE_SECTION_HEADER& hCurrentSection = hSection[i]; // Get current section.
+
+ ModuleSections_t moduleSection = ModuleSections_t(
+ std::string(reinterpret_cast<const char*>(hCurrentSection.Name)),
+ static_cast<uintptr_t>(m_pModuleBase + hCurrentSection.VirtualAddress),
+ hCurrentSection.SizeOfRawData);
+
+ if (!strcmp((const char*)hCurrentSection.Name, ".text"))
+ m_ExecutableCode = moduleSection;
+ else if (!strcmp((const char*)hCurrentSection.Name, ".pdata"))
+ m_ExceptionTable = moduleSection;
+ else if (!strcmp((const char*)hCurrentSection.Name, ".data"))
+ m_RunTimeData = moduleSection;
+ else if (!strcmp((const char*)hCurrentSection.Name, ".rdata"))
+ m_ReadOnlyData = moduleSection;
+
+ m_vModuleSections.push_back(moduleSection); // Push back a struct with the section data.
+ }
+}
+
+CModule::CModule(const char* pModuleName) : CModule(GetModuleHandleA(pModuleName)) {}
+
+MemoryAddress CModule::GetExport(const char* pExportName)
+{
+ return MemoryAddress(reinterpret_cast<uintptr_t>(GetProcAddress(reinterpret_cast<HMODULE>(m_nAddress), pExportName)));
+}
+
+MemoryAddress CModule::FindPattern(const uint8_t* pPattern, const char* pMask)
+{
+ if (!m_ExecutableCode.IsSectionValid())
+ return MemoryAddress();
+
+ uint64_t nBase = static_cast<uint64_t>(m_ExecutableCode.m_pSectionBase);
+ uint64_t nSize = static_cast<uint64_t>(m_ExecutableCode.m_nSectionSize);
+
+ const uint8_t* pData = reinterpret_cast<uint8_t*>(nBase);
+ const uint8_t* pEnd = pData + static_cast<uint32_t>(nSize) - strlen(pMask);
+
+ int nMasks[64]; // 64*16 = enough masks for 1024 bytes.
+ int iNumMasks = static_cast<int>(ceil(static_cast<float>(strlen(pMask)) / 16.f));
+
+ memset(nMasks, '\0', iNumMasks * sizeof(int));
+ for (intptr_t i = 0; i < iNumMasks; ++i)
+ {
+ for (intptr_t j = strnlen(pMask + i * 16, 16) - 1; j >= 0; --j)
+ {
+ if (pMask[i * 16 + j] == 'x')
+ {
+ _bittestandset(reinterpret_cast<LONG*>(&nMasks[i]), j);
+ }
+ }
+ }
+ __m128i xmm1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pPattern));
+ __m128i xmm2, xmm3, msks;
+ for (; pData != pEnd; _mm_prefetch(reinterpret_cast<const char*>(++pData + 64), _MM_HINT_NTA))
+ {
+ if (pPattern[0] == pData[0])
+ {
+ xmm2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pData));
+ msks = _mm_cmpeq_epi8(xmm1, xmm2);
+ if ((_mm_movemask_epi8(msks) & nMasks[0]) == nMasks[0])
+ {
+ for (uintptr_t i = 1; i < static_cast<uintptr_t>(iNumMasks); ++i)
+ {
+ xmm2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((pData + i * 16)));
+ xmm3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((pPattern + i * 16)));
+ msks = _mm_cmpeq_epi8(xmm2, xmm3);
+ if ((_mm_movemask_epi8(msks) & nMasks[i]) == nMasks[i])
+ {
+ if ((i + 1) == iNumMasks)
+ {
+ return MemoryAddress(const_cast<uint8_t*>(pData));
+ }
+ }
+ else
+ goto CONTINUE;
+ }
+
+ return MemoryAddress((&*(const_cast<uint8_t*>(pData))));
+ }
+ }
+
+ CONTINUE:;
+ }
+
+ return MemoryAddress();
+}
+
+inline std::pair<std::vector<uint8_t>, std::string> MaskedBytesFromPattern(const char* pPatternString)
+{
+ std::vector<uint8_t> vRet;
+ std::string sMask;
+
+ int size = strlen(pPatternString);
+ for (int i = 0; i < size; i++)
+ {
+ // If this is a space character, ignore it
+ if (isspace(pPatternString[i]))
+ continue;
+
+ if (pPatternString[i] == '?')
+ {
+ // Add a wildcard
+ vRet.push_back(0);
+ sMask.append("?");
+ }
+ else if (i < size - 1)
+ {
+ BYTE result = 0;
+ for (int j = 0; j < 2; j++)
+ {
+ int val = 0;
+ char c = *(pPatternString + i + j);
+ if (c >= 'a')
+ {
+ val = c - 'a' + 0xA;
+ }
+ else if (c >= 'A')
+ {
+ val = c - 'A' + 0xA;
+ }
+ else if (isdigit(c))
+ {
+ val = c - '0';
+ }
+ else
+ {
+ assert(false, "Failed to parse invalid pattern string.");
+ val = -1;
+ }
+
+ result += (j == 0) ? val * 16 : val;
+ }
+
+ vRet.push_back(result);
+ sMask.append("x");
+ }
+
+ i++;
+ }
+
+ return std::make_pair(vRet, sMask);
+}
+
+MemoryAddress CModule::FindPattern(const char* pPattern)
+{
+ const auto pattern = MaskedBytesFromPattern(pPattern);
+ return FindPattern(pattern.first.data(), pattern.second.c_str());
+}
diff --git a/NorthstarDLL/memory.h b/NorthstarDLL/memory.h
new file mode 100644
index 00000000..38c76cb3
--- /dev/null
+++ b/NorthstarDLL/memory.h
@@ -0,0 +1,90 @@
+#pragma once
+
+class MemoryAddress
+{
+ public:
+ uintptr_t m_nAddress;
+
+ public:
+ MemoryAddress();
+ MemoryAddress(const uintptr_t nAddress);
+ MemoryAddress(const void* pAddress);
+
+ // operators
+ operator uintptr_t() const;
+ operator void*() const;
+ operator bool() const;
+
+ bool operator==(const MemoryAddress& other) const;
+ bool operator!=(const MemoryAddress& other) const;
+ bool operator==(const uintptr_t& addr) const;
+ bool operator!=(const uintptr_t& addr) const;
+
+ MemoryAddress operator+(const MemoryAddress& other) const;
+ MemoryAddress operator-(const MemoryAddress& other) const;
+ MemoryAddress operator+(const uintptr_t& other) const;
+ MemoryAddress operator-(const uintptr_t& other) const;
+ MemoryAddress operator*() const;
+
+ template <typename T> T As()
+ {
+ return reinterpret_cast<T>(m_nAddress);
+ }
+
+ // traversal
+ MemoryAddress Offset(const uintptr_t nOffset) const;
+ MemoryAddress Deref(const int nNumDerefs = 1) const;
+
+ // patching
+ void Patch(const uint8_t* pBytes, const size_t nSize);
+ void Patch(const std::initializer_list<uint8_t> bytes);
+ void Patch(const char* pBytes);
+ void NOP(const size_t nSize);
+
+ bool IsMemoryReadable(const size_t nSize);
+};
+
+// based on https://github.com/Mauler125/r5sdk/blob/master/r5dev/public/include/module.h
+class CModule : public MemoryAddress
+{
+ public:
+ struct ModuleSections_t
+ {
+ ModuleSections_t(void) = default;
+ ModuleSections_t(const std::string& svSectionName, uintptr_t pSectionBase, size_t nSectionSize)
+ : m_svSectionName(svSectionName), m_pSectionBase(pSectionBase), m_nSectionSize(nSectionSize)
+ {
+ }
+
+ bool IsSectionValid(void) const
+ {
+ return m_nSectionSize != 0;
+ }
+
+ std::string m_svSectionName; // Name of section.
+ uintptr_t m_pSectionBase {}; // Start address of section.
+ size_t m_nSectionSize {}; // Size of section.
+ };
+
+ ModuleSections_t m_ExecutableCode;
+ ModuleSections_t m_ExceptionTable;
+ ModuleSections_t m_RunTimeData;
+ ModuleSections_t m_ReadOnlyData;
+
+ private:
+ std::string m_svModuleName;
+ uintptr_t m_pModuleBase {};
+ DWORD m_nModuleSize {};
+ IMAGE_NT_HEADERS64* m_pNTHeaders = nullptr;
+ IMAGE_DOS_HEADER* m_pDOSHeader = nullptr;
+ std::vector<ModuleSections_t> m_vModuleSections;
+
+ public:
+ CModule() = delete; // no default, we need a module name
+ CModule(const HMODULE pModule);
+ CModule(const char* pModuleName);
+
+ MemoryAddress GetExport(const char* pExportName);
+ MemoryAddress FindPattern(const uint8_t* pPattern, const char* pMask);
+ MemoryAddress FindPattern(const char* pPattern);
+};
diff --git a/NorthstarDLL/misccommands.cpp b/NorthstarDLL/misccommands.cpp
new file mode 100644
index 00000000..572d5620
--- /dev/null
+++ b/NorthstarDLL/misccommands.cpp
@@ -0,0 +1,65 @@
+#include "pch.h"
+#include "misccommands.h"
+#include "concommand.h"
+#include "playlist.h"
+#include "r2engine.h"
+#include "r2client.h"
+#include "hoststate.h"
+#include "masterserver.h"
+#include "serverauthentication.h"
+#include "squirrel.h"
+
+void ConCommand_force_newgame(const CCommand& arg)
+{
+ if (arg.ArgC() < 2)
+ return;
+
+ R2::g_pHostState->m_iNextState = R2::HostState_t::HS_NEW_GAME;
+ strncpy(R2::g_pHostState->m_levelName, arg.Arg(1), sizeof(R2::g_pHostState->m_levelName));
+}
+
+void ConCommand_ns_start_reauth_and_leave_to_lobby(const CCommand& arg)
+{
+ // hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect
+ g_pMasterServerManager->m_bNewgameAfterSelfAuth = true;
+ g_pMasterServerManager->AuthenticateWithOwnServer(R2::g_pLocalPlayerUserID, g_pMasterServerManager->m_sOwnClientAuthToken);
+}
+
+void ConCommand_ns_end_reauth_and_leave_to_lobby(const CCommand& arg)
+{
+ R2::Cbuf_AddText(
+ R2::Cbuf_GetCurrentPlayer(),
+ fmt::format("serverfilter {}", g_pServerAuthentication->m_RemoteAuthenticationData.begin()->first).c_str(),
+ R2::cmd_source_t::kCommandSrcCode);
+ R2::Cbuf_Execute();
+
+ // weird way of checking, but check if client script vm is initialised, mainly just to allow players to cancel this
+ if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM)
+ {
+ g_pServerAuthentication->m_bNeedLocalAuthForNewgame = true;
+
+ // this won't set playlist correctly on remote clients, don't think they can set playlist until they've left which sorta
+ // fucks things should maybe set this in HostState_NewGame?
+ R2::SetCurrentPlaylist("tdm");
+ strcpy(R2::g_pHostState->m_levelName, "mp_lobby");
+ R2::g_pHostState->m_iNextState = R2::HostState_t::HS_NEW_GAME;
+ }
+}
+
+void AddMiscConCommands()
+{
+ RegisterConCommand(
+ "force_newgame",
+ ConCommand_force_newgame,
+ "forces a map load through directly setting g_pHostState->m_iNextState to HS_NEW_GAME",
+ FCVAR_NONE);
+
+ RegisterConCommand(
+ "ns_start_reauth_and_leave_to_lobby",
+ ConCommand_ns_start_reauth_and_leave_to_lobby,
+ "called by the server, used to reauth and return the player to lobby when leaving a game",
+ FCVAR_SERVER_CAN_EXECUTE);
+
+ // this is a concommand because we make a deferred call to it from another thread
+ RegisterConCommand("ns_end_reauth_and_leave_to_lobby", ConCommand_ns_end_reauth_and_leave_to_lobby, "", FCVAR_NONE);
+}
diff --git a/NorthstarDLL/misccommands.h b/NorthstarDLL/misccommands.h
new file mode 100644
index 00000000..fbd41b32
--- /dev/null
+++ b/NorthstarDLL/misccommands.h
@@ -0,0 +1,2 @@
+#pragma once
+void AddMiscConCommands();
diff --git a/NorthstarDLL/miscserverfixes.cpp b/NorthstarDLL/miscserverfixes.cpp
new file mode 100644
index 00000000..4feca505
--- /dev/null
+++ b/NorthstarDLL/miscserverfixes.cpp
@@ -0,0 +1,7 @@
+#include "pch.h"
+
+ON_DLL_LOAD("server.dll", MiscServerFixes, (CModule module))
+{
+ // nop out call to VGUI shutdown since it crashes the game when quitting from the console
+ module.Offset(0x154A96).NOP(5);
+}
diff --git a/NorthstarDLL/miscserverscript.cpp b/NorthstarDLL/miscserverscript.cpp
new file mode 100644
index 00000000..7ae8047f
--- /dev/null
+++ b/NorthstarDLL/miscserverscript.cpp
@@ -0,0 +1,65 @@
+#include "pch.h"
+#include "squirrel.h"
+#include "masterserver.h"
+#include "serverauthentication.h"
+#include "dedicated.h"
+#include "r2client.h"
+#include "r2server.h"
+
+#include <filesystem>
+
+// void function NSEarlyWritePlayerIndexPersistenceForLeave( int playerIndex )
+SQRESULT SQ_EarlyWritePlayerIndexPersistenceForLeave(HSquirrelVM* sqvm)
+{
+ int playerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 1);
+ R2::CBaseClient* player = &R2::g_pClientArray[playerIndex];
+
+ if (!g_pServerAuthentication->m_PlayerAuthenticationData.count(player))
+ {
+ g_pSquirrel<ScriptContext::SERVER>->raiseerror(sqvm, fmt::format("Invalid playerindex {}", playerIndex).c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pServerAuthentication->m_PlayerAuthenticationData[player].needPersistenceWriteOnLeave = false;
+ g_pServerAuthentication->WritePersistentData(player);
+ return SQRESULT_NULL;
+}
+
+// bool function NSIsWritingPlayerPersistence()
+SQRESULT SQ_IsWritingPlayerPersistence(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::SERVER>->pushbool(sqvm, g_pMasterServerManager->m_bSavingPersistentData);
+ return SQRESULT_NOTNULL;
+}
+
+// bool function NSIsPlayerIndexLocalPlayer( int playerIndex )
+SQRESULT SQ_IsPlayerIndexLocalPlayer(HSquirrelVM* sqvm)
+{
+ int playerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 1);
+ R2::CBaseClient* player = &R2::g_pClientArray[playerIndex];
+ if (!g_pServerAuthentication->m_PlayerAuthenticationData.count(player))
+ {
+ g_pSquirrel<ScriptContext::SERVER>->raiseerror(sqvm, fmt::format("Invalid playerindex {}", playerIndex).c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::SERVER>->pushbool(sqvm, !strcmp(R2::g_pLocalPlayerUserID, player->m_UID));
+ return SQRESULT_NOTNULL;
+}
+
+// bool function NSIsDedicated()
+SQRESULT SQ_IsDedicated(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::SERVER>->pushbool(sqvm, IsDedicatedServer());
+ return SQRESULT_NOTNULL;
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", MiscServerScriptCommands, ServerSquirrel, (CModule module))
+{
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration(
+ "void", "NSEarlyWritePlayerIndexPersistenceForLeave", "int playerIndex", "", SQ_EarlyWritePlayerIndexPersistenceForLeave);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration("bool", "NSIsWritingPlayerPersistence", "", "", SQ_IsWritingPlayerPersistence);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration(
+ "bool", "NSIsPlayerIndexLocalPlayer", "int playerIndex", "", SQ_IsPlayerIndexLocalPlayer);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration("bool", "NSIsDedicated", "", "", SQ_IsDedicated);
+}
diff --git a/NorthstarDLL/modlocalisation.cpp b/NorthstarDLL/modlocalisation.cpp
new file mode 100644
index 00000000..b12f0a40
--- /dev/null
+++ b/NorthstarDLL/modlocalisation.cpp
@@ -0,0 +1,35 @@
+#include "pch.h"
+#include "modmanager.h"
+
+AUTOHOOK_INIT()
+
+// clang-format off
+AUTOHOOK(AddLocalisationFile, localize.dll + 0x6D80,
+bool, __fastcall, (void* pVguiLocalize, const char* path, const char* pathId, char unknown))
+// clang-format on
+{
+ static bool bLoadModLocalisationFiles = true;
+ bool ret = AddLocalisationFile(pVguiLocalize, path, pathId, unknown);
+
+ if (ret)
+ spdlog::info("Loaded localisation file {} successfully", path);
+
+ if (!bLoadModLocalisationFiles)
+ return ret;
+
+ bLoadModLocalisationFiles = false;
+
+ for (Mod mod : g_pModManager->m_LoadedMods)
+ if (mod.m_bEnabled)
+ for (std::string& localisationFile : mod.LocalisationFiles)
+ AddLocalisationFile(pVguiLocalize, localisationFile.c_str(), pathId, unknown);
+
+ bLoadModLocalisationFiles = true;
+
+ return ret;
+}
+
+ON_DLL_LOAD_CLIENT("localize.dll", Localize, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+}
diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDLL/modmanager.cpp
index 50c7b371..05060902 100644
--- a/NorthstarDedicatedTest/modmanager.cpp
+++ b/NorthstarDLL/modmanager.cpp
@@ -4,6 +4,10 @@
#include "concommand.h"
#include "audio.h"
#include "masterserver.h"
+#include "filesystem.h"
+#include "rpakfilesystem.h"
+#include "nsprefix.h"
+
#include "rapidjson/error/en.h"
#include "rapidjson/document.h"
#include "rapidjson/ostreamwrapper.h"
@@ -13,17 +17,14 @@
#include <string>
#include <sstream>
#include <vector>
-#include "filesystem.h"
-#include "rpakfilesystem.h"
-#include "configurables.h"
-ModManager* g_ModManager;
+ModManager* g_pModManager;
Mod::Mod(fs::path modDir, char* jsonBuf)
{
- wasReadSuccessfully = false;
+ m_bWasReadSuccessfully = false;
- ModDirectory = modDir;
+ m_ModDirectory = modDir;
rapidjson_document modJson;
modJson.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>(jsonBuf);
@@ -106,11 +107,55 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
else
convar->HelpString = "";
- // todo: could possibly parse FCVAR names here instead, would be easier
+ convar->Flags = FCVAR_NONE;
+
if (convarObj.HasMember("Flags"))
- convar->Flags = convarObj["Flags"].GetInt();
- else
- convar->Flags = FCVAR_NONE;
+ {
+ // read raw integer flags
+ if (convarObj["Flags"].IsInt())
+ convar->Flags = convarObj["Flags"].GetInt();
+ else if (convarObj["Flags"].IsString())
+ {
+ // parse cvar flags from string
+ // example string: ARCHIVE_PLAYERPROFILE | GAMEDLL
+
+ std::string sFlags = convarObj["Flags"].GetString();
+ sFlags += '|'; // add additional | so we register the last flag
+ std::string sCurrentFlag;
+
+ for (int i = 0; i < sFlags.length(); i++)
+ {
+ if (isspace(sFlags[i]))
+ continue;
+
+ // if we encounter a |, add current string as a flag
+ if (sFlags[i] == '|')
+ {
+ bool bHasFlags = false;
+ int iCurrentFlags;
+
+ for (auto& flagPair : g_PrintCommandFlags)
+ {
+ if (!sCurrentFlag.compare(flagPair.second))
+ {
+ iCurrentFlags = flagPair.first;
+ bHasFlags = true;
+ break;
+ }
+ }
+
+ if (bHasFlags)
+ convar->Flags |= iCurrentFlags;
+ else
+ spdlog::warn("Mod ConVar {} has unknown flag {}", convar->Name, sCurrentFlag);
+
+ sCurrentFlag = "";
+ }
+ else
+ sCurrentFlag += sFlags[i];
+ }
+ }
+ }
ConVars.push_back(convar);
}
@@ -127,7 +172,7 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
ModScript script;
script.Path = scriptObj["Path"].GetString();
- script.RsonRunOn = scriptObj["RunOn"].GetString();
+ script.RunOn = scriptObj["RunOn"].GetString();
if (scriptObj.HasMember("ServerCallback") && scriptObj["ServerCallback"].IsObject())
{
@@ -186,7 +231,27 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
}
}
- wasReadSuccessfully = true;
+ if (modJson.HasMember("Dependencies") && modJson["Dependencies"].IsObject())
+ {
+ for (auto v = modJson["Dependencies"].MemberBegin(); v != modJson["Dependencies"].MemberEnd(); v++)
+ {
+ if (!v->name.IsString() || !v->value.IsString())
+ continue;
+
+ spdlog::info("Constant {} defined by {} for mod {}", v->name.GetString(), Name, v->value.GetString());
+ if (DependencyConstants.find(v->name.GetString()) != DependencyConstants.end() &&
+ v->value.GetString() != DependencyConstants[v->name.GetString()])
+ {
+ spdlog::error("A dependency constant with the same name already exists for another mod. Change the constant name.");
+ return;
+ }
+
+ if (DependencyConstants.find(v->name.GetString()) == DependencyConstants.end())
+ DependencyConstants.emplace(v->name.GetString(), v->value.GetString());
+ }
+ }
+
+ m_bWasReadSuccessfully = true;
}
ModManager::ModManager()
@@ -203,7 +268,7 @@ ModManager::ModManager()
void ModManager::LoadMods()
{
- if (m_hasLoadedMods)
+ if (m_bHasLoadedMods)
UnloadMods();
std::vector<fs::path> modDirs;
@@ -212,6 +277,8 @@ void ModManager::LoadMods()
fs::remove_all(GetCompiledAssetsPath());
fs::create_directories(GetModFolderPath());
+ m_DependencyConstants.clear();
+
// read enabled mods cfg
std::ifstream enabledModsStream(GetNorthstarPrefix() + "/enabledmods.json");
std::stringstream enabledModsStringStream;
@@ -222,10 +289,10 @@ void ModManager::LoadMods()
enabledModsStringStream << (char)enabledModsStream.get();
enabledModsStream.close();
- m_enabledModsCfg.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>(
+ m_EnabledModsCfg.Parse<rapidjson::ParseFlag::kParseCommentsFlag | rapidjson::ParseFlag::kParseTrailingCommasFlag>(
enabledModsStringStream.str().c_str());
- m_hasEnabledModsCfg = m_enabledModsCfg.IsObject();
+ m_bHasEnabledModsCfg = m_EnabledModsCfg.IsObject();
}
// get mod directories
@@ -253,31 +320,43 @@ void ModManager::LoadMods()
Mod mod(modDir, (char*)jsonStringStream.str().c_str());
- if (m_hasEnabledModsCfg && m_enabledModsCfg.HasMember(mod.Name.c_str()))
- mod.Enabled = m_enabledModsCfg[mod.Name.c_str()].IsTrue();
+ for (auto& pair : mod.DependencyConstants)
+ {
+ if (m_DependencyConstants.find(pair.first) != m_DependencyConstants.end() && m_DependencyConstants[pair.first] != pair.second)
+ {
+ spdlog::error("Constant {} in mod {} already exists in another mod.", pair.first, mod.Name);
+ mod.m_bWasReadSuccessfully = false;
+ break;
+ }
+ if (m_DependencyConstants.find(pair.first) == m_DependencyConstants.end())
+ m_DependencyConstants.emplace(pair);
+ }
+
+ if (m_bHasEnabledModsCfg && m_EnabledModsCfg.HasMember(mod.Name.c_str()))
+ mod.m_bEnabled = m_EnabledModsCfg[mod.Name.c_str()].IsTrue();
else
- mod.Enabled = true;
+ mod.m_bEnabled = true;
- if (mod.wasReadSuccessfully)
+ if (mod.m_bWasReadSuccessfully)
{
spdlog::info("Loaded mod {} successfully", mod.Name);
- if (mod.Enabled)
+ if (mod.m_bEnabled)
spdlog::info("Mod {} is enabled", mod.Name);
else
spdlog::info("Mod {} is disabled", mod.Name);
- m_loadedMods.push_back(mod);
+ m_LoadedMods.push_back(mod);
}
else
spdlog::warn("Skipping loading mod file {}", (modDir / "mod.json").string());
}
// sort by load prio, lowest-highest
- std::sort(m_loadedMods.begin(), m_loadedMods.end(), [](Mod& a, Mod& b) { return a.LoadPriority < b.LoadPriority; });
+ std::sort(m_LoadedMods.begin(), m_LoadedMods.end(), [](Mod& a, Mod& b) { return a.LoadPriority < b.LoadPriority; });
- for (Mod& mod : m_loadedMods)
+ for (Mod& mod : m_LoadedMods)
{
- if (!mod.Enabled)
+ if (!mod.m_bEnabled)
continue;
// register convars
@@ -285,15 +364,15 @@ void ModManager::LoadMods()
// preexisting convars note: we don't delete convars if they already exist because they're used for script stuff, unfortunately this
// causes us to leak memory on reload, but not much, potentially find a way to not do this at some point
for (ModConVar* convar : mod.ConVars)
- if (!g_pCVar->FindVar(convar->Name.c_str())) // make sure convar isn't registered yet, unsure if necessary but idk what
- // behaviour is for defining same convar multiple times
+ if (!R2::g_pCVar->FindVar(convar->Name.c_str())) // make sure convar isn't registered yet, unsure if necessary but idk what
+ // behaviour is for defining same convar multiple times
new ConVar(convar->Name.c_str(), convar->DefaultValue.c_str(), convar->Flags, convar->HelpString.c_str());
// read vpk paths
- if (fs::exists(mod.ModDirectory / "vpk"))
+ if (fs::exists(mod.m_ModDirectory / "vpk"))
{
// read vpk cfg
- std::ifstream vpkJsonStream(mod.ModDirectory / "vpk/vpk.json");
+ std::ifstream vpkJsonStream(mod.m_ModDirectory / "vpk/vpk.json");
std::stringstream vpkJsonStringStream;
bool bUseVPKJson = false;
@@ -311,7 +390,7 @@ void ModManager::LoadMods()
bUseVPKJson = !dVpkJson.HasParseError() && dVpkJson.IsObject();
}
- for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "vpk"))
+ for (fs::directory_entry file : fs::directory_iterator(mod.m_ModDirectory / "vpk"))
{
// a bunch of checks to make sure we're only adding dir vpks and their paths are good
// note: the game will literally only load vpks with the english prefix
@@ -322,25 +401,24 @@ void ModManager::LoadMods()
std::string formattedPath = file.path().filename().string();
// this really fucking sucks but it'll work
- std::string vpkName =
- (file.path().parent_path() / formattedPath.substr(strlen("english"), formattedPath.find(".bsp") - 3)).string();
+ std::string vpkName = formattedPath.substr(strlen("english"), formattedPath.find(".bsp") - 3);
ModVPKEntry& modVpk = mod.Vpks.emplace_back();
modVpk.m_bAutoLoad = !bUseVPKJson || (dVpkJson.HasMember("Preload") && dVpkJson["Preload"].IsObject() &&
dVpkJson["Preload"].HasMember(vpkName) && dVpkJson["Preload"][vpkName].IsTrue());
- modVpk.m_sVpkPath = vpkName;
+ modVpk.m_sVpkPath = (file.path().parent_path() / vpkName).string();
- if (m_hasLoadedMods && modVpk.m_bAutoLoad)
- (*g_Filesystem)->m_vtable->MountVPK(*g_Filesystem, vpkName.c_str());
+ if (m_bHasLoadedMods && modVpk.m_bAutoLoad)
+ (*R2::g_pFilesystem)->m_vtable->MountVPK(*R2::g_pFilesystem, vpkName.c_str());
}
}
}
// read rpak paths
- if (fs::exists(mod.ModDirectory / "paks"))
+ if (fs::exists(mod.m_ModDirectory / "paks"))
{
// read rpak cfg
- std::ifstream rpakJsonStream(mod.ModDirectory / "paks/rpak.json");
+ std::ifstream rpakJsonStream(mod.m_ModDirectory / "paks/rpak.json");
std::stringstream rpakJsonStringStream;
bool bUseRpakJson = false;
@@ -372,7 +450,7 @@ void ModManager::LoadMods()
}
}
- for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "paks"))
+ for (fs::directory_entry file : fs::directory_iterator(mod.m_ModDirectory / "paks"))
{
// ensure we're only loading rpaks
if (fs::is_regular_file(file) && file.path().extension() == ".rpak")
@@ -383,32 +461,39 @@ void ModManager::LoadMods()
modPak.m_bAutoLoad =
!bUseRpakJson || (dRpakJson.HasMember("Preload") && dRpakJson["Preload"].IsObject() &&
dRpakJson["Preload"].HasMember(pakName) && dRpakJson["Preload"][pakName].IsTrue());
+
+ // postload things
+ if (!bUseRpakJson ||
+ (dRpakJson.HasMember("Postload") && dRpakJson["Postload"].IsObject() && dRpakJson["Postload"].HasMember(pakName)))
+ modPak.m_sLoadAfterPak = dRpakJson["Postload"][pakName].GetString();
+
modPak.m_sPakName = pakName;
// not using atm because we need to resolve path to rpak
// if (m_hasLoadedMods && modPak.m_bAutoLoad)
- // g_PakLoadManager->LoadPakAsync(pakName.c_str());
+ // g_pPakLoadManager->LoadPakAsync(pakName.c_str());
}
}
}
// read keyvalues paths
- if (fs::exists(mod.ModDirectory / "keyvalues"))
+ if (fs::exists(mod.m_ModDirectory / "keyvalues"))
{
- for (fs::directory_entry file : fs::recursive_directory_iterator(mod.ModDirectory / "keyvalues"))
+ for (fs::directory_entry file : fs::recursive_directory_iterator(mod.m_ModDirectory / "keyvalues"))
{
if (fs::is_regular_file(file))
{
- std::string kvStr = file.path().lexically_relative(mod.ModDirectory / "keyvalues").lexically_normal().string();
+ std::string kvStr =
+ g_pModManager->NormaliseModFilePath(file.path().lexically_relative(mod.m_ModDirectory / "keyvalues"));
mod.KeyValues.emplace(STR_HASH(kvStr), kvStr);
}
}
}
// read pdiff
- if (fs::exists(mod.ModDirectory / "mod.pdiff"))
+ if (fs::exists(mod.m_ModDirectory / "mod.pdiff"))
{
- std::ifstream pdiffStream(mod.ModDirectory / "mod.pdiff");
+ std::ifstream pdiffStream(mod.m_ModDirectory / "mod.pdiff");
if (!pdiffStream.fail())
{
@@ -423,17 +508,17 @@ void ModManager::LoadMods()
}
// read bink video paths
- if (fs::exists(mod.ModDirectory / "media"))
+ if (fs::exists(mod.m_ModDirectory / "media"))
{
- for (fs::directory_entry file : fs::recursive_directory_iterator(mod.ModDirectory / "media"))
+ for (fs::directory_entry file : fs::recursive_directory_iterator(mod.m_ModDirectory / "media"))
if (fs::is_regular_file(file) && file.path().extension() == ".bik")
mod.BinkVideos.push_back(file.path().filename().string());
}
// try to load audio
- if (fs::exists(mod.ModDirectory / "audio"))
+ if (fs::exists(mod.m_ModDirectory / "audio"))
{
- for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "audio"))
+ for (fs::directory_entry file : fs::directory_iterator(mod.m_ModDirectory / "audio"))
{
if (fs::is_regular_file(file) && file.path().extension().string() == ".json")
{
@@ -448,23 +533,23 @@ void ModManager::LoadMods()
}
// in a seperate loop because we register mod files in reverse order, since mods loaded later should have their files prioritised
- for (int64_t i = m_loadedMods.size() - 1; i > -1; i--)
+ for (int64_t i = m_LoadedMods.size() - 1; i > -1; i--)
{
- if (!m_loadedMods[i].Enabled)
+ if (!m_LoadedMods[i].m_bEnabled)
continue;
- if (fs::exists(m_loadedMods[i].ModDirectory / MOD_OVERRIDE_DIR))
+ if (fs::exists(m_LoadedMods[i].m_ModDirectory / MOD_OVERRIDE_DIR))
{
- for (fs::directory_entry file : fs::recursive_directory_iterator(m_loadedMods[i].ModDirectory / MOD_OVERRIDE_DIR))
+ for (fs::directory_entry file : fs::recursive_directory_iterator(m_LoadedMods[i].m_ModDirectory / MOD_OVERRIDE_DIR))
{
- fs::path path = file.path().lexically_relative(m_loadedMods[i].ModDirectory / MOD_OVERRIDE_DIR).lexically_normal();
-
- if (file.is_regular_file() && m_modFiles.find(path.string()) == m_modFiles.end())
+ std::string path =
+ g_pModManager->NormaliseModFilePath(file.path().lexically_relative(m_LoadedMods[i].m_ModDirectory / MOD_OVERRIDE_DIR));
+ if (file.is_regular_file() && m_ModFiles.find(path) == m_ModFiles.end())
{
ModOverrideFile modFile;
- modFile.owningMod = &m_loadedMods[i];
- modFile.path = path;
- m_modFiles.insert(std::make_pair(path.string(), modFile));
+ modFile.m_pOwningMod = &m_LoadedMods[i];
+ modFile.m_Path = path;
+ m_ModFiles.insert(std::make_pair(path, modFile));
}
}
}
@@ -476,9 +561,9 @@ void ModManager::LoadMods()
modinfoDoc.AddMember("Mods", rapidjson_document::GenericValue(rapidjson::kArrayType), modinfoDoc.GetAllocator());
int currentModIndex = 0;
- for (Mod& mod : m_loadedMods)
+ for (Mod& mod : m_LoadedMods)
{
- if (!mod.Enabled || (!mod.RequiredOnClient && !mod.Pdiff.size()))
+ if (!mod.m_bEnabled || (!mod.RequiredOnClient && !mod.Pdiff.size()))
continue;
modinfoDoc["Mods"].PushBack(rapidjson_document::GenericValue(rapidjson::kObjectType), modinfoDoc.GetAllocator());
@@ -494,27 +579,27 @@ void ModManager::LoadMods()
buffer.Clear();
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
modinfoDoc.Accept(writer);
- g_MasterServerManager->m_ownModInfoJson = std::string(buffer.GetString());
+ g_pMasterServerManager->m_sOwnModInfoJson = std::string(buffer.GetString());
- m_hasLoadedMods = true;
+ m_bHasLoadedMods = true;
}
void ModManager::UnloadMods()
{
// clean up stuff from mods before we unload
- m_modFiles.clear();
+ m_ModFiles.clear();
fs::remove_all(GetCompiledAssetsPath());
g_CustomAudioManager.ClearAudioOverrides();
- if (!m_hasEnabledModsCfg)
- m_enabledModsCfg.SetObject();
+ if (!m_bHasEnabledModsCfg)
+ m_EnabledModsCfg.SetObject();
- for (Mod& mod : m_loadedMods)
+ for (Mod& mod : m_LoadedMods)
{
// remove all built kvs
for (std::pair<size_t, std::string> kvPaths : mod.KeyValues)
- fs::remove(GetCompiledAssetsPath() / fs::path(kvPaths.second).lexically_relative(mod.ModDirectory));
+ fs::remove(GetCompiledAssetsPath() / fs::path(kvPaths.second).lexically_relative(mod.m_ModDirectory));
mod.KeyValues.clear();
@@ -522,27 +607,39 @@ void ModManager::UnloadMods()
// should we be doing this here or should scripts be doing this manually?
// main issue with doing this here is when we reload mods for connecting to a server, we write enabled mods, which isn't necessarily
// what we wanna do
- if (!m_enabledModsCfg.HasMember(mod.Name.c_str()))
- m_enabledModsCfg.AddMember(
+ if (!m_EnabledModsCfg.HasMember(mod.Name.c_str()))
+ m_EnabledModsCfg.AddMember(
rapidjson_document::StringRefType(mod.Name.c_str()),
rapidjson_document::GenericValue(false),
- m_enabledModsCfg.GetAllocator());
+ m_EnabledModsCfg.GetAllocator());
- m_enabledModsCfg[mod.Name.c_str()].SetBool(mod.Enabled);
+ m_EnabledModsCfg[mod.Name.c_str()].SetBool(mod.m_bEnabled);
}
std::ofstream writeStream(GetNorthstarPrefix() + "/enabledmods.json");
rapidjson::OStreamWrapper writeStreamWrapper(writeStream);
rapidjson::Writer<rapidjson::OStreamWrapper> writer(writeStreamWrapper);
- m_enabledModsCfg.Accept(writer);
+ m_EnabledModsCfg.Accept(writer);
// do we need to dealloc individual entries in m_loadedMods? idk, rework
- m_loadedMods.clear();
+ m_LoadedMods.clear();
+}
+
+std::string ModManager::NormaliseModFilePath(const fs::path path)
+{
+ std::string str = path.lexically_normal().string();
+
+ // force to lowercase
+ for (char& c : str)
+ if (c <= 'Z' && c >= 'A')
+ c = c - ('Z' - 'z');
+
+ return str;
}
void ModManager::CompileAssetsForFile(const char* filename)
{
- size_t fileHash = STR_HASH(fs::path(filename).lexically_normal().string());
+ size_t fileHash = STR_HASH(NormaliseModFilePath(fs::path(filename)));
if (fileHash == m_hScriptsRsonHash)
BuildScriptsRson();
@@ -551,9 +648,9 @@ void ModManager::CompileAssetsForFile(const char* filename)
else
{
// check if we should build keyvalues, depending on whether any of our mods have patch kvs for this file
- for (Mod& mod : m_loadedMods)
+ for (Mod& mod : m_LoadedMods)
{
- if (!mod.Enabled)
+ if (!mod.m_bEnabled)
continue;
if (mod.KeyValues.find(fileHash) != mod.KeyValues.end())
@@ -565,16 +662,9 @@ void ModManager::CompileAssetsForFile(const char* filename)
}
}
-void ReloadModsCommand(const CCommand& args)
-{
- g_ModManager->LoadMods();
-}
-
-void InitialiseModManager(HMODULE baseAddress)
+void ConCommand_reload_mods(const CCommand& args)
{
- g_ModManager = new ModManager;
-
- RegisterConCommand("reload_mods", ReloadModsCommand, "idk", FCVAR_NONE);
+ g_pModManager->LoadMods();
}
fs::path GetModFolderPath()
@@ -584,4 +674,11 @@ fs::path GetModFolderPath()
fs::path GetCompiledAssetsPath()
{
return fs::path(GetNorthstarPrefix() + COMPILED_ASSETS_SUFFIX);
-} \ No newline at end of file
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", ModManager, (ConCommand, MasterServer), (CModule module))
+{
+ g_pModManager = new ModManager;
+
+ RegisterConCommand("reload_mods", ConCommand_reload_mods, "reloads mods", FCVAR_NONE);
+}
diff --git a/NorthstarDedicatedTest/modmanager.h b/NorthstarDLL/modmanager.h
index 798c2306..f622c675 100644
--- a/NorthstarDedicatedTest/modmanager.h
+++ b/NorthstarDLL/modmanager.h
@@ -1,14 +1,15 @@
#pragma once
#include "convar.h"
+#include "memalloc.h"
+#include "squirrel.h"
+
+#include "rapidjson/document.h"
#include <string>
#include <vector>
#include <filesystem>
-#include "rapidjson/document.h"
-#include "memalloc.h"
-
-namespace fs = std::filesystem;
const std::string MOD_FOLDER_SUFFIX = "/mods";
+const std::string REMOTE_MOD_FOLDER_SUFFIX = "/runtime/remote/mods";
const fs::path MOD_OVERRIDE_DIR = "mod";
const std::string COMPILED_ASSETS_SUFFIX = "/runtime/compiled";
@@ -24,9 +25,6 @@ struct ModConVar
struct ModScriptCallback
{
public:
- // would've liked to make it possible to hook arbitrary codecallbacks, but couldn't find a function that calls some ui ones
- // std::string HookedCodeCallback;
-
ScriptContext Context;
// called before the codecallback is executed
@@ -39,7 +37,7 @@ struct ModScript
{
public:
std::string Path;
- std::string RsonRunOn;
+ std::string RunOn;
std::vector<ModScriptCallback> Callbacks;
};
@@ -57,14 +55,17 @@ struct ModRpakEntry
public:
bool m_bAutoLoad;
std::string m_sPakName;
+ std::string m_sLoadAfterPak;
};
class Mod
{
public:
// runtime stuff
- fs::path ModDirectory;
- bool Enabled = true;
+ bool m_bEnabled = true;
+ bool m_bWasReadSuccessfully = false;
+ fs::path m_ModDirectory;
+ // bool m_bIsRemote;
// mod.json stuff:
@@ -100,9 +101,7 @@ class Mod
std::unordered_map<std::string, std::string>
RpakAliases; // paks we alias to other rpaks, e.g. to load sp_crashsite paks on the map mp_crashsite
- // other stuff
-
- bool wasReadSuccessfully = false;
+ std::unordered_map<std::string, std::string> DependencyConstants;
public:
Mod(fs::path modPath, char* jsonBuf);
@@ -111,39 +110,40 @@ class Mod
struct ModOverrideFile
{
public:
- Mod* owningMod;
- fs::path path;
+ Mod* m_pOwningMod;
+ fs::path m_Path;
};
class ModManager
{
private:
- bool m_hasLoadedMods = false;
- bool m_hasEnabledModsCfg;
- rapidjson_document m_enabledModsCfg;
+ bool m_bHasLoadedMods = false;
+ bool m_bHasEnabledModsCfg;
+ rapidjson_document m_EnabledModsCfg;
// precalculated hashes
size_t m_hScriptsRsonHash;
size_t m_hPdefHash;
public:
- std::vector<Mod> m_loadedMods;
- std::unordered_map<std::string, ModOverrideFile> m_modFiles;
+ std::vector<Mod> m_LoadedMods;
+ std::unordered_map<std::string, ModOverrideFile> m_ModFiles;
+ std::unordered_map<std::string, std::string> m_DependencyConstants;
public:
ModManager();
void LoadMods();
void UnloadMods();
+ std::string NormaliseModFilePath(const fs::path path);
void CompileAssetsForFile(const char* filename);
- // compile asset type stuff, these are done in files under Mods/Compiled/
+ // compile asset type stuff, these are done in files under runtime/compiled/
void BuildScriptsRson();
void TryBuildKeyValues(const char* filename);
void BuildPdef();
};
-void InitialiseModManager(HMODULE baseAddress);
fs::path GetModFolderPath();
fs::path GetCompiledAssetsPath();
-extern ModManager* g_ModManager; \ No newline at end of file
+extern ModManager* g_pModManager;
diff --git a/NorthstarDedicatedTest/ns_version.h b/NorthstarDLL/ns_version.h
index d30594fb..d30594fb 100644
--- a/NorthstarDedicatedTest/ns_version.h
+++ b/NorthstarDLL/ns_version.h
diff --git a/NorthstarDedicatedTest/configurables.cpp b/NorthstarDLL/nsprefix.cpp
index 389e6e0b..64a9d1f1 100644
--- a/NorthstarDedicatedTest/configurables.cpp
+++ b/NorthstarDLL/nsprefix.cpp
@@ -1,13 +1,13 @@
-#include <string>
#include "pch.h"
-#include "configurables.h"
+#include "nsprefix.h"
+#include <string>
std::string GetNorthstarPrefix()
{
return NORTHSTAR_FOLDER_PREFIX;
}
-void parseConfigurables()
+void InitialiseNorthstarPrefix()
{
char* clachar = strstr(GetCommandLineA(), "-profile=");
if (clachar)
diff --git a/NorthstarDedicatedTest/configurables.h b/NorthstarDLL/nsprefix.h
index cc98e15e..9f3087fb 100644
--- a/NorthstarDedicatedTest/configurables.h
+++ b/NorthstarDLL/nsprefix.h
@@ -3,5 +3,5 @@
static std::string NORTHSTAR_FOLDER_PREFIX;
+void InitialiseNorthstarPrefix();
std::string GetNorthstarPrefix();
-void parseConfigurables();
diff --git a/NorthstarDedicatedTest/pch.cpp b/NorthstarDLL/pch.cpp
index 64b7eef6..64b7eef6 100644
--- a/NorthstarDedicatedTest/pch.cpp
+++ b/NorthstarDLL/pch.cpp
diff --git a/NorthstarDedicatedTest/pch.h b/NorthstarDLL/pch.h
index 1955071c..e23d6a9b 100644
--- a/NorthstarDedicatedTest/pch.h
+++ b/NorthstarDLL/pch.h
@@ -8,23 +8,24 @@
#define _WINSOCK_DEPRECATED_NO_WARNINGS // temp because i'm very lazy and want to use inet_addr, remove later
#define RAPIDJSON_HAS_STDSTRING 1
-// httplib ssl
-
// add headers that you want to pre-compile here
#include "memalloc.h"
-#include <Windows.h>
-#include <Psapi.h>
+#include <windows.h>
+#include <psapi.h>
#include <set>
#include <map>
#include <filesystem>
#include <sstream>
+namespace fs = std::filesystem;
+
#include "logging.h"
-#include "include/MinHook.h"
+#include "MinHook.h"
#include "spdlog/spdlog.h"
#include "libcurl/include/curl/curl.h"
-#include "hookutils.h"
+#include "hooks.h"
+#include "memory.h"
template <typename ReturnType, typename... Args> ReturnType CallVFunc(int index, void* thisPtr, Args... args)
{
@@ -45,4 +46,4 @@ template <typename T, size_t index, typename... Args> constexpr T CallVFunc_Alt(
return CallVFunc_Alt<returnType, index> argsRaw; \
}
-#endif \ No newline at end of file
+#endif
diff --git a/NorthstarDedicatedTest/pdef.cpp b/NorthstarDLL/pdef.cpp
index 86642874..05fba710 100644
--- a/NorthstarDedicatedTest/pdef.cpp
+++ b/NorthstarDLL/pdef.cpp
@@ -1,8 +1,8 @@
#include "pch.h"
#include "modmanager.h"
#include "filesystem.h"
-#include "hookutils.h"
#include "pdef.h"
+
#include <map>
#include <sstream>
#include <fstream>
@@ -14,11 +14,11 @@ void ModManager::BuildPdef()
fs::path MOD_PDEF_PATH = fs::path(GetCompiledAssetsPath() / MOD_PDEF_SUFFIX);
fs::remove(MOD_PDEF_PATH);
- std::string pdef = ReadVPKOriginalFile(VPK_PDEF_PATH);
+ std::string pdef = R2::ReadVPKOriginalFile(VPK_PDEF_PATH);
- for (Mod& mod : m_loadedMods)
+ for (Mod& mod : m_LoadedMods)
{
- if (!mod.Enabled || !mod.Pdiff.size())
+ if (!mod.m_bEnabled || !mod.Pdiff.size())
continue;
// this code probably isn't going to be pretty lol
@@ -107,11 +107,11 @@ void ModManager::BuildPdef()
writeStream.close();
ModOverrideFile overrideFile;
- overrideFile.owningMod = nullptr;
- overrideFile.path = VPK_PDEF_PATH;
+ overrideFile.m_pOwningMod = nullptr;
+ overrideFile.m_Path = VPK_PDEF_PATH;
- if (m_modFiles.find(VPK_PDEF_PATH) == m_modFiles.end())
- m_modFiles.insert(std::make_pair(VPK_PDEF_PATH, overrideFile));
+ if (m_ModFiles.find(VPK_PDEF_PATH) == m_ModFiles.end())
+ m_ModFiles.insert(std::make_pair(VPK_PDEF_PATH, overrideFile));
else
- m_modFiles[VPK_PDEF_PATH] = overrideFile;
-} \ No newline at end of file
+ m_ModFiles[VPK_PDEF_PATH] = overrideFile;
+}
diff --git a/NorthstarDedicatedTest/pdef.h b/NorthstarDLL/pdef.h
index a6bffbe4..379e76da 100644
--- a/NorthstarDedicatedTest/pdef.h
+++ b/NorthstarDLL/pdef.h
@@ -1,4 +1,4 @@
#pragma once
const fs::path MOD_PDEF_SUFFIX = "cfg/server/persistent_player_data_version_231.pdef";
-const char* VPK_PDEF_PATH = "cfg/server/persistent_player_data_version_231.pdef"; \ No newline at end of file
+const char* VPK_PDEF_PATH = "cfg/server/persistent_player_data_version_231.pdef";
diff --git a/NorthstarDLL/playlist.cpp b/NorthstarDLL/playlist.cpp
new file mode 100644
index 00000000..4f34dbb1
--- /dev/null
+++ b/NorthstarDLL/playlist.cpp
@@ -0,0 +1,130 @@
+#include "pch.h"
+#include "playlist.h"
+#include "concommand.h"
+#include "convar.h"
+#include "squirrel.h"
+#include "hoststate.h"
+#include "serverpresence.h"
+
+AUTOHOOK_INIT()
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ const char* (*GetCurrentPlaylistName)();
+ void (*SetCurrentPlaylist)(const char* pPlaylistName);
+ void (*SetPlaylistVarOverride)(const char* pVarName, const char* pValue);
+ const char* (*GetCurrentPlaylistVar)(const char* pVarName, bool bUseOverrides);
+} // namespace R2
+
+ConVar* Cvar_ns_use_clc_SetPlaylistVarOverride;
+
+// clang-format off
+AUTOHOOK(clc_SetPlaylistVarOverride__Process, engine.dll + 0x222180,
+char, __fastcall, (void* a1, void* a2))
+// clang-format on
+{
+ // the private_match playlist on mp_lobby is the only situation where there should be any legitimate sending of this netmessage
+ if (!Cvar_ns_use_clc_SetPlaylistVarOverride->GetBool() || strcmp(R2::GetCurrentPlaylistName(), "private_match") ||
+ strcmp(R2::g_pHostState->m_levelName, "mp_lobby"))
+ return 1;
+
+ return clc_SetPlaylistVarOverride__Process(a1, a2);
+}
+
+// clang-format off
+AUTOHOOK(SetCurrentPlaylist, engine.dll + 0x18EB20,
+bool, __fastcall, (const char* pPlaylistName))
+// clang-format on
+{
+ bool bSuccess = SetCurrentPlaylist(pPlaylistName);
+
+ if (bSuccess)
+ {
+ spdlog::info("Set playlist to {}", R2::GetCurrentPlaylistName());
+ g_pServerPresence->SetPlaylist(R2::GetCurrentPlaylistName());
+ }
+
+ return bSuccess;
+}
+
+// clang-format off
+AUTOHOOK(SetPlaylistVarOverride, engine.dll + 0x18ED00,
+void, __fastcall, (const char* pVarName, const char* pValue))
+// clang-format on
+{
+ if (strlen(pValue) >= 64)
+ return;
+
+ SetPlaylistVarOverride(pVarName, pValue);
+}
+
+// clang-format off
+AUTOHOOK(GetCurrentPlaylistVar, engine.dll + 0x18C680,
+const char*, __fastcall, (const char* pVarName, bool bUseOverrides))
+// clang-format on
+{
+ if (!bUseOverrides && !strcmp(pVarName, "max_players"))
+ bUseOverrides = true;
+
+ return GetCurrentPlaylistVar(pVarName, bUseOverrides);
+}
+
+// clang-format off
+AUTOHOOK(GetCurrentGamemodeMaxPlayers, engine.dll + 0x18C430,
+int, __fastcall, ())
+// clang-format on
+{
+ const char* pMaxPlayers = R2::GetCurrentPlaylistVar("max_players", 0);
+ if (!pMaxPlayers)
+ return GetCurrentGamemodeMaxPlayers();
+
+ int iMaxPlayers = atoi(pMaxPlayers);
+ return iMaxPlayers;
+}
+
+void ConCommand_playlist(const CCommand& args)
+{
+ if (args.ArgC() < 2)
+ return;
+
+ R2::SetCurrentPlaylist(args.Arg(1));
+}
+
+void ConCommand_setplaylistvaroverride(const CCommand& args)
+{
+ if (args.ArgC() < 3)
+ return;
+
+ for (int i = 1; i < args.ArgC(); i += 2)
+ R2::SetPlaylistVarOverride(args.Arg(i), args.Arg(i + 1));
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", PlaylistHooks, (ConCommand, ConVar), (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ R2::GetCurrentPlaylistName = module.Offset(0x18C640).As<const char* (*)()>();
+ R2::SetCurrentPlaylist = module.Offset(0x18EB20).As<void (*)(const char*)>();
+ R2::SetPlaylistVarOverride = module.Offset(0x18ED00).As<void (*)(const char*, const char*)>();
+ R2::GetCurrentPlaylistVar = module.Offset(0x18C680).As<const char* (*)(const char*, bool)>();
+
+ // playlist is the name of the command on respawn servers, but we already use setplaylist so can't get rid of it
+ RegisterConCommand("playlist", ConCommand_playlist, "Sets the current playlist", FCVAR_NONE);
+ RegisterConCommand("setplaylist", ConCommand_playlist, "Sets the current playlist", FCVAR_NONE);
+ RegisterConCommand("setplaylistvaroverrides", ConCommand_setplaylistvaroverride, "sets a playlist var override", FCVAR_NONE);
+
+ // note: clc_SetPlaylistVarOverride is pretty insecure, since it allows for entirely arbitrary playlist var overrides to be sent to the
+ // server, this is somewhat restricted on custom servers to prevent it being done outside of private matches, but ideally it should be
+ // disabled altogether, since the custom menus won't use it anyway this should only really be accepted if you want vanilla client
+ // compatibility
+ Cvar_ns_use_clc_SetPlaylistVarOverride = new ConVar(
+ "ns_use_clc_SetPlaylistVarOverride", "0", FCVAR_GAMEDLL, "Whether the server should accept clc_SetPlaylistVarOverride messages");
+
+ // patch to prevent clc_SetPlaylistVarOverride from being able to crash servers if we reach max overrides due to a call to Error (why is
+ // this possible respawn, wtf) todo: add a warning for this
+ module.Offset(0x18ED8D).Patch("C3");
+
+ // patch to allow setplaylistvaroverride to be called before map init on dedicated and private match launched through the game
+ module.Offset(0x18ED17).NOP(6);
+}
diff --git a/NorthstarDLL/playlist.h b/NorthstarDLL/playlist.h
new file mode 100644
index 00000000..c77b37d9
--- /dev/null
+++ b/NorthstarDLL/playlist.h
@@ -0,0 +1,10 @@
+#pragma once
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ extern const char* (*GetCurrentPlaylistName)();
+ extern void (*SetCurrentPlaylist)(const char* pPlaylistName);
+ extern void (*SetPlaylistVarOverride)(const char* pVarName, const char* pValue);
+ extern const char* (*GetCurrentPlaylistVar)(const char* pVarName, bool bUseOverrides);
+} // namespace R2
diff --git a/NorthstarDedicatedTest/plugin_abi.h b/NorthstarDLL/plugin_abi.h
index 698c33ab..4b176a32 100644
--- a/NorthstarDedicatedTest/plugin_abi.h
+++ b/NorthstarDLL/plugin_abi.h
@@ -65,4 +65,4 @@ struct PlayerInfo
int (*getPlayerInfoChar)(char* out_buf, size_t out_buf_len, PlayerInfoType var);
int (*getPlayerInfoInt)(int* out_ptr, PlayerInfoType var);
int (*getPlayerInfoBool)(bool* out_ptr, PlayerInfoType var);
-}; \ No newline at end of file
+};
diff --git a/NorthstarDedicatedTest/plugins.cpp b/NorthstarDLL/plugins.cpp
index 70535a32..790439d1 100644
--- a/NorthstarDedicatedTest/plugins.cpp
+++ b/NorthstarDLL/plugins.cpp
@@ -1,9 +1,11 @@
#include "pch.h"
#include "squirrel.h"
#include "plugins.h"
-#include <chrono>
#include "masterserver.h"
#include "convar.h"
+#include "serverpresence.h"
+
+#include <chrono>
#include <windows.h>
/// <summary>
@@ -109,31 +111,31 @@ void initGameState()
}
// string gamemode, string gamemodeName, string map, string mapName, bool connected, bool loading
-SQRESULT SQ_UpdateGameStateUI(void* sqvm)
+SQRESULT SQ_UpdateGameStateUI(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&gameStateLock);
- gameState.map = ClientSq_getstring(sqvm, 1);
- gameState.mapDisplayName = ClientSq_getstring(sqvm, 2);
- gameState.playlist = ClientSq_getstring(sqvm, 3);
- gameState.playlistDisplayName = ClientSq_getstring(sqvm, 4);
- gameState.connected = ClientSq_getbool(sqvm, 5);
- gameState.loading = ClientSq_getbool(sqvm, 6);
+ gameState.map = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+ gameState.mapDisplayName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 2);
+ gameState.playlist = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 3);
+ gameState.playlistDisplayName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 4);
+ gameState.connected = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 5);
+ gameState.loading = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 6);
ReleaseSRWLockExclusive(&gameStateLock);
return SQRESULT_NOTNULL;
}
// int playerCount, int outScore, int secondHighestScore, int highestScore, bool roundBased, int scoreLimit
-SQRESULT SQ_UpdateGameStateClient(void* sqvm)
+SQRESULT SQ_UpdateGameStateClient(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&gameStateLock);
AcquireSRWLockExclusive(&serverInfoLock);
- gameState.players = ClientSq_getinteger(sqvm, 1);
- serverInfo.maxPlayers = ClientSq_getinteger(sqvm, 2);
- gameState.ourScore = ClientSq_getinteger(sqvm, 3);
- gameState.secondHighestScore = ClientSq_getinteger(sqvm, 4);
- gameState.highestScore = ClientSq_getinteger(sqvm, 5);
- serverInfo.roundBased = ClientSq_getbool(sqvm, 6);
- serverInfo.scoreLimit = ClientSq_getbool(sqvm, 7);
+ gameState.players = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 1);
+ serverInfo.maxPlayers = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 2);
+ gameState.ourScore = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 3);
+ gameState.secondHighestScore = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 4);
+ gameState.highestScore = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 5);
+ serverInfo.roundBased = g_pSquirrel<ScriptContext::CLIENT>->getbool(sqvm, 6);
+ serverInfo.scoreLimit = g_pSquirrel<ScriptContext::CLIENT>->getbool(sqvm, 7);
ReleaseSRWLockExclusive(&gameStateLock);
ReleaseSRWLockExclusive(&serverInfoLock);
return SQRESULT_NOTNULL;
@@ -141,59 +143,59 @@ SQRESULT SQ_UpdateGameStateClient(void* sqvm)
// string id, string name, string password, int players, int maxPlayers, string map, string mapDisplayName, string playlist, string
// playlistDisplayName
-SQRESULT SQ_UpdateServerInfo(void* sqvm)
+SQRESULT SQ_UpdateServerInfo(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&gameStateLock);
AcquireSRWLockExclusive(&serverInfoLock);
- serverInfo.id = ClientSq_getstring(sqvm, 1);
- serverInfo.name = ClientSq_getstring(sqvm, 2);
- serverInfo.password = ClientSq_getstring(sqvm, 3);
- gameState.players = ClientSq_getinteger(sqvm, 4);
- serverInfo.maxPlayers = ClientSq_getinteger(sqvm, 5);
- gameState.map = ClientSq_getstring(sqvm, 6);
- gameState.mapDisplayName = ClientSq_getstring(sqvm, 7);
- gameState.playlist = ClientSq_getstring(sqvm, 8);
- gameState.playlistDisplayName = ClientSq_getstring(sqvm, 9);
+ serverInfo.id = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+ serverInfo.name = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 2);
+ serverInfo.password = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 3);
+ gameState.players = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 4);
+ serverInfo.maxPlayers = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 5);
+ gameState.map = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 6);
+ gameState.mapDisplayName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 7);
+ gameState.playlist = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 8);
+ gameState.playlistDisplayName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 9);
ReleaseSRWLockExclusive(&gameStateLock);
ReleaseSRWLockExclusive(&serverInfoLock);
return SQRESULT_NOTNULL;
}
// int maxPlayers
-SQRESULT SQ_UpdateServerInfoBetweenRounds(void* sqvm)
+SQRESULT SQ_UpdateServerInfoBetweenRounds(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&serverInfoLock);
- serverInfo.id = ClientSq_getstring(sqvm, 1);
- serverInfo.name = ClientSq_getstring(sqvm, 2);
- serverInfo.password = ClientSq_getstring(sqvm, 3);
- serverInfo.maxPlayers = ClientSq_getinteger(sqvm, 4);
+ serverInfo.id = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 1);
+ serverInfo.name = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 2);
+ serverInfo.password = g_pSquirrel<ScriptContext::CLIENT>->getstring(sqvm, 3);
+ serverInfo.maxPlayers = g_pSquirrel<ScriptContext::CLIENT>->getinteger(sqvm, 4);
ReleaseSRWLockExclusive(&serverInfoLock);
return SQRESULT_NOTNULL;
}
// float timeInFuture
-SQRESULT SQ_UpdateTimeInfo(void* sqvm)
+SQRESULT SQ_UpdateTimeInfo(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&serverInfoLock);
- serverInfo.endTime = ceil(ClientSq_getfloat(sqvm, 1));
+ serverInfo.endTime = ceil(g_pSquirrel<ScriptContext::CLIENT>->getfloat(sqvm, 1));
ReleaseSRWLockExclusive(&serverInfoLock);
return SQRESULT_NOTNULL;
}
// bool loading
-SQRESULT SQ_SetConnected(void* sqvm)
+SQRESULT SQ_SetConnected(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&gameStateLock);
- gameState.loading = ClientSq_getbool(sqvm, 1);
+ gameState.loading = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 1);
ReleaseSRWLockExclusive(&gameStateLock);
return SQRESULT_NOTNULL;
}
-SQRESULT SQ_UpdateListenServer(void* sqvm)
+SQRESULT SQ_UpdateListenServer(HSquirrelVM* sqvm)
{
AcquireSRWLockExclusive(&serverInfoLock);
- serverInfo.id = g_MasterServerManager->m_ownServerId;
- serverInfo.password = Cvar_ns_server_password->GetString();
+ serverInfo.id = g_pMasterServerManager->m_sOwnServerId;
+ serverInfo.password = ""; // g_pServerPresence->Cvar_ns_server_password->GetString(); todo this fr
ReleaseSRWLockExclusive(&serverInfoLock);
return SQRESULT_NOTNULL;
}
@@ -384,26 +386,26 @@ int getPlayerInfoBool(bool* out_ptr, PlayerInfoType var)
return n;
}
-void InitialisePluginCommands(HMODULE baseAddress)
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", PluginCommands, ClientSquirrel, (CModule module))
{
// i swear there's a way to make this not have be run in 2 contexts but i can't figure it out
// some funcs i need are just not available in UI or CLIENT
- if (g_UISquirrelManager && g_ClientSquirrelManager)
+ if (g_pSquirrel<ScriptContext::UI> && g_pSquirrel<ScriptContext::CLIENT>)
{
- g_UISquirrelManager->AddFuncRegistration(
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
"void",
"NSUpdateGameStateUI",
"string gamemode, string gamemodeName, string map, string mapName, bool connected, bool loading",
"",
SQ_UpdateGameStateUI);
- g_ClientSquirrelManager->AddFuncRegistration(
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration(
"void",
"NSUpdateGameStateClient",
"int playerCount, int maxPlayers, int outScore, int secondHighestScore, int highestScore, bool roundBased, int scoreLimit",
"",
SQ_UpdateGameStateClient);
- g_UISquirrelManager->AddFuncRegistration(
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
"void",
"NSUpdateServerInfo",
"string id, string name, string password, int players, int maxPlayers, string map, string mapDisplayName, string playlist, "
@@ -411,10 +413,10 @@ void InitialisePluginCommands(HMODULE baseAddress)
"playlistDisplayName",
"",
SQ_UpdateServerInfo);
- g_ClientSquirrelManager->AddFuncRegistration(
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration(
"void", "NSUpdateServerInfoReload", "int maxPlayers", "", SQ_UpdateServerInfoBetweenRounds);
- g_ClientSquirrelManager->AddFuncRegistration("void", "NSUpdateTimeInfo", "float timeInFuture", "", SQ_UpdateTimeInfo);
- g_UISquirrelManager->AddFuncRegistration("void", "NSSetLoading", "bool loading", "", SQ_SetConnected);
- g_UISquirrelManager->AddFuncRegistration("void", "NSUpdateListenServer", "", "", SQ_UpdateListenServer);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration("void", "NSUpdateTimeInfo", "float timeInFuture", "", SQ_UpdateTimeInfo);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSSetLoading", "bool loading", "", SQ_SetConnected);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSUpdateListenServer", "", "", SQ_UpdateListenServer);
}
}
diff --git a/NorthstarDedicatedTest/plugins.h b/NorthstarDLL/plugins.h
index 27312da9..953801a2 100644
--- a/NorthstarDedicatedTest/plugins.h
+++ b/NorthstarDLL/plugins.h
@@ -15,5 +15,3 @@ int getPlayerInfoBool(bool* out_ptr, PlayerInfoType var);
void initGameState();
void* getPluginObject(PluginObject var);
-
-void InitialisePluginCommands(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDLL/printcommand.h b/NorthstarDLL/printcommand.h
new file mode 100644
index 00000000..6c3ef850
--- /dev/null
+++ b/NorthstarDLL/printcommand.h
@@ -0,0 +1,6 @@
+#pragma once
+#include "concommand.h"
+
+void PrintCommandHelpDialogue(const ConCommandBase* command, const char* name);
+void TryPrintCvarHelpForCommand(const char* pCommand);
+void InitialiseCommandPrint();
diff --git a/NorthstarDLL/printcommands.cpp b/NorthstarDLL/printcommands.cpp
new file mode 100644
index 00000000..90af1575
--- /dev/null
+++ b/NorthstarDLL/printcommands.cpp
@@ -0,0 +1,174 @@
+#include "pch.h"
+#include "printcommand.h"
+#include "convar.h"
+#include "concommand.h"
+
+void PrintCommandHelpDialogue(const ConCommandBase* command, const char* name)
+{
+ if (!command)
+ {
+ spdlog::info("unknown command {}", name);
+ return;
+ }
+
+ // temp because command->IsCommand does not currently work
+ ConVar* cvar = R2::g_pCVar->FindVar(command->m_pszName);
+
+ // build string for flags if not FCVAR_NONE
+ std::string flagString;
+ if (command->GetFlags() != FCVAR_NONE)
+ {
+ flagString = "( ";
+
+ for (auto& flagPair : g_PrintCommandFlags)
+ {
+ if (command->GetFlags() & flagPair.first)
+ {
+ // special case, slightly hacky: PRINTABLEONLY is for commands, GAMEDLL_FOR_REMOTE_CLIENTS is for concommands, both have the
+ // same value
+ if (flagPair.first == FCVAR_PRINTABLEONLY)
+ {
+ if (cvar && !strcmp(flagPair.second, "GAMEDLL_FOR_REMOTE_CLIENTS"))
+ continue;
+
+ if (!cvar && !strcmp(flagPair.second, "PRINTABLEONLY"))
+ continue;
+ }
+
+ flagString += flagPair.second;
+ flagString += " ";
+ }
+ }
+
+ flagString += ") ";
+ }
+
+ if (cvar)
+ spdlog::info("\"{}\" = \"{}\" {}- {}", cvar->GetBaseName(), cvar->GetString(), flagString, cvar->GetHelpText());
+ else
+ spdlog::info("\"{}\" {} - {}", command->m_pszName, flagString, command->GetHelpText());
+}
+
+void TryPrintCvarHelpForCommand(const char* pCommand)
+{
+ // try to display help text for an inputted command string from the console
+ int pCommandLen = strlen(pCommand);
+ char* pCvarStr = new char[pCommandLen];
+ strcpy(pCvarStr, pCommand);
+
+ // trim whitespace from right
+ for (int i = pCommandLen - 1; i; i--)
+ {
+ if (isspace(pCvarStr[i]))
+ pCvarStr[i] = '\0';
+ else
+ break;
+ }
+
+ // check if we're inputting a cvar, but not setting it at all
+ ConVar* cvar = R2::g_pCVar->FindVar(pCvarStr);
+ if (cvar)
+ PrintCommandHelpDialogue(&cvar->m_ConCommandBase, pCvarStr);
+
+ delete[] pCvarStr;
+}
+
+void ConCommand_help(const CCommand& arg)
+{
+ if (arg.ArgC() < 2)
+ {
+ spdlog::info("Usage: help <cvarname>");
+ return;
+ }
+
+ PrintCommandHelpDialogue(R2::g_pCVar->FindCommandBase(arg.Arg(1)), arg.Arg(1));
+}
+
+void ConCommand_find(const CCommand& arg)
+{
+ if (arg.ArgC() < 2)
+ {
+ spdlog::info("Usage: find <string> [<string>...]");
+ return;
+ }
+
+ char pTempName[256];
+ char pTempSearchTerm[256];
+
+ for (auto& map : R2::g_pCVar->DumpToMap())
+ {
+ bool bPrintCommand = true;
+ for (int i = 0; i < arg.ArgC() - 1; i++)
+ {
+ // make lowercase to avoid case sensitivity
+ strncpy_s(pTempName, sizeof(pTempName), map.second->m_pszName, sizeof(pTempName) - 1);
+ strncpy_s(pTempSearchTerm, sizeof(pTempSearchTerm), arg.Arg(i + 1), sizeof(pTempSearchTerm) - 1);
+
+ for (int i = 0; pTempName[i]; i++)
+ pTempName[i] = tolower(pTempName[i]);
+
+ for (int i = 0; pTempSearchTerm[i]; i++)
+ pTempSearchTerm[i] = tolower(pTempSearchTerm[i]);
+
+ if (!strstr(pTempName, pTempSearchTerm))
+ {
+ bPrintCommand = false;
+ break;
+ }
+ }
+
+ if (bPrintCommand)
+ PrintCommandHelpDialogue(map.second, map.second->m_pszName);
+ }
+}
+
+void ConCommand_findflags(const CCommand& arg)
+{
+ if (arg.ArgC() < 2)
+ {
+ spdlog::info("Usage: findflags <string>");
+ for (auto& flagPair : g_PrintCommandFlags)
+ spdlog::info(" - {}", flagPair.second);
+
+ return;
+ }
+
+ // convert input flag to uppercase
+ char* upperFlag = new char[strlen(arg.Arg(1))];
+ strcpy(upperFlag, arg.Arg(1));
+
+ for (int i = 0; upperFlag[i]; i++)
+ upperFlag[i] = toupper(upperFlag[i]);
+
+ // resolve flag name => int flags
+ int resolvedFlag = FCVAR_NONE;
+ for (auto& flagPair : g_PrintCommandFlags)
+ {
+ if (!strcmp(flagPair.second, upperFlag))
+ {
+ resolvedFlag |= flagPair.first;
+ break;
+ }
+ }
+
+ // print cvars
+ for (auto& map : R2::g_pCVar->DumpToMap())
+ {
+ if (map.second->m_nFlags & resolvedFlag)
+ PrintCommandHelpDialogue(map.second, map.second->m_pszName);
+ }
+
+ delete[] upperFlag;
+}
+
+void InitialiseCommandPrint()
+{
+ RegisterConCommand("find", ConCommand_find, "Find concommands with the specified string in their name/help text.", FCVAR_NONE);
+ RegisterConCommand("findflags", ConCommand_findflags, "Find concommands by flags.", FCVAR_NONE);
+
+ // help is already a command, so we need to modify the preexisting command to use our func instead
+ // and clear the flags also
+ ConCommand* helpCommand = R2::g_pCVar->FindCommand("help");
+ helpCommand->m_nFlags = FCVAR_NONE;
+ helpCommand->m_pCommandCallback = ConCommand_help;
+}
diff --git a/NorthstarDLL/printmaps.cpp b/NorthstarDLL/printmaps.cpp
new file mode 100644
index 00000000..c378daad
--- /dev/null
+++ b/NorthstarDLL/printmaps.cpp
@@ -0,0 +1,168 @@
+#include "pch.h"
+#include "printmaps.h"
+#include "convar.h"
+#include "concommand.h"
+#include "modmanager.h"
+#include "tier0.h"
+#include "r2engine.h"
+
+#include <filesystem>
+#include <regex>
+
+AUTOHOOK_INIT()
+
+enum class MapSource_t
+{
+ VPK,
+ GAMEDIR,
+ MOD
+};
+
+const std::unordered_map<MapSource_t, const char*> PrintMapSource = {
+ {MapSource_t::VPK, "VPK"}, {MapSource_t::MOD, "MOD"}, {MapSource_t::GAMEDIR, "R2"}};
+
+struct MapVPKInfo
+{
+ std::string name;
+ std::string parent;
+ MapSource_t source;
+};
+
+// our current list of maps in the game
+std::vector<MapVPKInfo> vMapList;
+
+void RefreshMapList()
+{
+ vMapList.clear();
+
+ // get modded maps
+ // TODO: could probably check mod vpks to get mapnames from there too?
+ for (auto& modFilePair : g_pModManager->m_ModFiles)
+ {
+ ModOverrideFile file = modFilePair.second;
+ if (file.m_Path.extension() == ".bsp" && file.m_Path.parent_path().string() == "maps") // only allow mod maps actually in /maps atm
+ {
+ MapVPKInfo& map = vMapList.emplace_back();
+ map.name = file.m_Path.stem().string();
+ map.parent = file.m_pOwningMod->Name;
+ map.source = MapSource_t::MOD;
+ }
+ }
+
+ // get maps in vpk
+ {
+ const int iNumRetailNonMapVpks = 1;
+ static const char* const ppRetailNonMapVpks[] = {
+ "englishclient_frontend.bsp.pak000_dir.vpk"}; // don't include mp_common here as it contains mp_lobby
+
+ // matches directory vpks, and captures their map name in the first group
+ static const std::regex rVpkMapRegex("englishclient_([a-zA-Z_]+)\\.bsp\\.pak000_dir\\.vpk", std::regex::icase);
+
+ for (fs::directory_entry file : fs::directory_iterator("./vpk"))
+ {
+ std::string pathString = file.path().filename().string();
+
+ bool bIsValidMapVpk = true;
+ for (int i = 0; i < iNumRetailNonMapVpks; i++)
+ {
+ if (!pathString.compare(ppRetailNonMapVpks[i]))
+ {
+ bIsValidMapVpk = false;
+ break;
+ }
+ }
+
+ if (!bIsValidMapVpk)
+ continue;
+
+ // run our map vpk regex on the filename
+ std::smatch match;
+ std::regex_match(pathString, match, rVpkMapRegex);
+
+ if (match.length() < 2)
+ continue;
+
+ std::string mapName = match[1].str();
+ // special case: englishclient_mp_common contains mp_lobby, so hardcode the name here
+ if (mapName == "mp_common")
+ mapName = "mp_lobby";
+
+ MapVPKInfo& map = vMapList.emplace_back();
+ map.name = mapName;
+ map.parent = pathString;
+ map.source = MapSource_t::VPK;
+ }
+ }
+
+ // get maps in game dir
+ for (fs::directory_entry file : fs::directory_iterator(fmt::format("{}/maps", R2::g_pModName)))
+ {
+ if (file.path().extension() == ".bsp")
+ {
+ MapVPKInfo& map = vMapList.emplace_back();
+ map.name = file.path().stem().string();
+ map.parent = "R2";
+ map.source = MapSource_t::GAMEDIR;
+ }
+ }
+}
+
+// clang-format off
+AUTOHOOK(_Host_Map_f_CompletionFunc, engine.dll + 0x161AE0,
+int, __fastcall, (const char const* cmdname, const char const* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]))
+// clang-format on
+{
+ // don't update our map list often from this func, only refresh every 10 seconds so we avoid constantly reading fs
+ static double flLastAutocompleteRefresh = -999;
+
+ if (flLastAutocompleteRefresh + 10.0 < Tier0::Plat_FloatTime())
+ {
+ RefreshMapList();
+ flLastAutocompleteRefresh = Tier0::Plat_FloatTime();
+ }
+
+ // use a custom autocomplete func for all map loading commands
+ const int cmdLength = strlen(cmdname);
+ const char* query = partial + cmdLength;
+ const int queryLength = strlen(query);
+
+ int numMaps = 0;
+ for (int i = 0; i < vMapList.size() && numMaps < COMMAND_COMPLETION_MAXITEMS; i++)
+ {
+ if (!strncmp(query, vMapList[i].name.c_str(), queryLength))
+ {
+ strcpy(commands[numMaps], cmdname);
+ strncpy_s(
+ commands[numMaps++] + cmdLength,
+ COMMAND_COMPLETION_ITEM_LENGTH,
+ &vMapList[i].name[0],
+ COMMAND_COMPLETION_ITEM_LENGTH - cmdLength);
+ }
+ }
+
+ return numMaps;
+}
+
+void ConCommand_maps(const CCommand& args)
+{
+ if (args.ArgC() < 2)
+ {
+ spdlog::info("Usage: maps <substring>");
+ spdlog::info("maps * for full listing");
+ return;
+ }
+
+ RefreshMapList();
+
+ for (MapVPKInfo& map : vMapList) // need to figure out a nice way to include parent path without making the formatting awful
+ if ((*args.Arg(1) == '*' && !args.Arg(1)[1]) || strstr(map.name.c_str(), args.Arg(1)))
+ spdlog::info("({}) {}", PrintMapSource.at(map.source), map.name);
+}
+
+void InitialiseMapsPrint()
+{
+ AUTOHOOK_DISPATCH()
+
+ ConCommand* mapsCommand = R2::g_pCVar->FindCommand("maps");
+ mapsCommand->m_pCommandCallback = ConCommand_maps;
+}
diff --git a/NorthstarDLL/printmaps.h b/NorthstarDLL/printmaps.h
new file mode 100644
index 00000000..b01761c0
--- /dev/null
+++ b/NorthstarDLL/printmaps.h
@@ -0,0 +1,2 @@
+#pragma once
+void InitialiseMapsPrint();
diff --git a/NorthstarDLL/r2client.cpp b/NorthstarDLL/r2client.cpp
new file mode 100644
index 00000000..2e7bd564
--- /dev/null
+++ b/NorthstarDLL/r2client.cpp
@@ -0,0 +1,20 @@
+#include "pch.h"
+#include "r2client.h"
+
+using namespace R2;
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ char* g_pLocalPlayerUserID;
+ char* g_pLocalPlayerOriginToken;
+ GetBaseLocalClientType GetBaseLocalClient;
+} // namespace R2
+
+ON_DLL_LOAD("engine.dll", R2EngineClient, (CModule module))
+{
+ g_pLocalPlayerUserID = module.Offset(0x13F8E688).As<char*>();
+ g_pLocalPlayerOriginToken = module.Offset(0x13979C80).As<char*>();
+
+ GetBaseLocalClient = module.Offset(0x78200).As<GetBaseLocalClientType>();
+}
diff --git a/NorthstarDLL/r2client.h b/NorthstarDLL/r2client.h
new file mode 100644
index 00000000..64ed6c61
--- /dev/null
+++ b/NorthstarDLL/r2client.h
@@ -0,0 +1,11 @@
+#pragma once
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ extern char* g_pLocalPlayerUserID;
+ extern char* g_pLocalPlayerOriginToken;
+
+ typedef void* (*GetBaseLocalClientType)();
+ extern GetBaseLocalClientType GetBaseLocalClient;
+} // namespace R2
diff --git a/NorthstarDLL/r2engine.cpp b/NorthstarDLL/r2engine.cpp
new file mode 100644
index 00000000..11233a2d
--- /dev/null
+++ b/NorthstarDLL/r2engine.cpp
@@ -0,0 +1,36 @@
+#include "pch.h"
+#include "r2engine.h"
+
+using namespace R2;
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer;
+ Cbuf_AddTextType Cbuf_AddText;
+ Cbuf_ExecuteType Cbuf_Execute;
+
+ CEngine* g_pEngine;
+
+ void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
+ CBaseClient* g_pClientArray;
+
+ server_state_t* g_pServerState;
+
+ char* g_pModName =
+ nullptr; // we cant set this up here atm since we dont have an offset to it in engine, instead we store it in IsRespawnMod
+} // namespace R2
+
+ON_DLL_LOAD("engine.dll", R2Engine, (CModule module))
+{
+ Cbuf_GetCurrentPlayer = module.Offset(0x120630).As<Cbuf_GetCurrentPlayerType>();
+ Cbuf_AddText = module.Offset(0x1203B0).As<Cbuf_AddTextType>();
+ Cbuf_Execute = module.Offset(0x1204B0).As<Cbuf_ExecuteType>();
+
+ g_pEngine = module.Offset(0x7D70C8).Deref().As<CEngine*>();
+
+ CBaseClient__Disconnect = module.Offset(0x1012C0).As<void (*)(void*, uint32_t, const char*, ...)>();
+ g_pClientArray = module.Offset(0x12A53F90).As<CBaseClient*>();
+
+ g_pServerState = module.Offset(0x12A53D48).As<server_state_t*>();
+}
diff --git a/NorthstarDLL/r2engine.h b/NorthstarDLL/r2engine.h
new file mode 100644
index 00000000..5566f339
--- /dev/null
+++ b/NorthstarDLL/r2engine.h
@@ -0,0 +1,199 @@
+#pragma once
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ // Cbuf
+ enum class ECommandTarget_t
+ {
+ CBUF_FIRST_PLAYER = 0,
+ CBUF_LAST_PLAYER = 1, // MAX_SPLITSCREEN_CLIENTS - 1, MAX_SPLITSCREEN_CLIENTS = 2
+ CBUF_SERVER = CBUF_LAST_PLAYER + 1,
+
+ CBUF_COUNT,
+ };
+
+ enum class cmd_source_t
+ {
+ // Added to the console buffer by gameplay code. Generally unrestricted.
+ kCommandSrcCode,
+
+ // Sent from code via engine->ClientCmd, which is restricted to commands visible
+ // via FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS.
+ kCommandSrcClientCmd,
+
+ // Typed in at the console or via a user key-bind. Generally unrestricted, although
+ // the client will throttle commands sent to the server this way to 16 per second.
+ kCommandSrcUserInput,
+
+ // Came in over a net connection as a clc_stringcmd
+ // host_client will be valid during this state.
+ //
+ // Restricted to FCVAR_GAMEDLL commands (but not convars) and special non-ConCommand
+ // server commands hardcoded into gameplay code (e.g. "joingame")
+ kCommandSrcNetClient,
+
+ // Received from the server as the client
+ //
+ // Restricted to commands with FCVAR_SERVER_CAN_EXECUTE
+ kCommandSrcNetServer,
+
+ // Being played back from a demo file
+ //
+ // Not currently restricted by convar flag, but some commands manually ignore calls
+ // from this source. FIXME: Should be heavily restricted as demo commands can come
+ // from untrusted sources.
+ kCommandSrcDemoFile,
+
+ // Invalid value used when cleared
+ kCommandSrcInvalid = -1
+ };
+
+ typedef ECommandTarget_t (*Cbuf_GetCurrentPlayerType)();
+ extern Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer;
+
+ typedef void (*Cbuf_AddTextType)(ECommandTarget_t eTarget, const char* text, cmd_source_t source);
+ extern Cbuf_AddTextType Cbuf_AddText;
+
+ typedef void (*Cbuf_ExecuteType)();
+ extern Cbuf_ExecuteType Cbuf_Execute;
+
+ // CEngine
+
+ enum EngineQuitState
+ {
+ QUIT_NOTQUITTING = 0,
+ QUIT_TODESKTOP,
+ QUIT_RESTART
+ };
+
+ enum class EngineState_t
+ {
+ DLL_INACTIVE = 0, // no dll
+ DLL_ACTIVE, // engine is focused
+ DLL_CLOSE, // closing down dll
+ DLL_RESTART, // engine is shutting down but will restart right away
+ DLL_PAUSED, // engine is paused, can become active from this state
+ };
+
+ class CEngine
+ {
+ public:
+ virtual void unknown() {} // unsure if this is where
+ virtual bool Load(bool dedicated, const char* baseDir) {}
+ virtual void Unload() {}
+ virtual void SetNextState(EngineState_t iNextState) {}
+ virtual EngineState_t GetState() {}
+ virtual void Frame() {}
+ virtual double GetFrameTime() {}
+ virtual float GetCurTime() {}
+
+ EngineQuitState m_nQuitting;
+ EngineState_t m_nDllState;
+ EngineState_t m_nNextDllState;
+ double m_flCurrentTime;
+ float m_flFrameTime;
+ double m_flPreviousTime;
+ float m_flFilteredTime;
+ float m_flMinFrameTime; // Expected duration of a frame, or zero if it is unlimited.
+ };
+
+ extern CEngine* g_pEngine;
+
+ extern void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
+
+#pragma once
+ typedef enum
+ {
+ NA_NULL = 0,
+ NA_LOOPBACK,
+ NA_IP,
+ } netadrtype_t;
+
+#pragma pack(push, 1)
+ typedef struct netadr_s
+ {
+ netadrtype_t type;
+ unsigned char ip[16]; // IPv6
+ // IPv4's 127.0.0.1 is [::ffff:127.0.0.1], that is:
+ // 00 00 00 00 00 00 00 00 00 00 FF FF 7F 00 00 01
+ unsigned short port;
+ } netadr_t;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+ typedef struct netpacket_s
+ {
+ netadr_t adr; // sender address
+ // int source; // received source
+ char unk[10];
+ double received_time;
+ unsigned char* data; // pointer to raw packet data
+ void* message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
+ char unk2[16];
+ int size;
+
+ // bf_read message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
+ // int size; // size in bytes
+ // int wiresize; // size in bytes before decompression
+ // bool stream; // was send as stream
+ // struct netpacket_s* pNext; // for internal use, should be NULL in public
+ } netpacket_t;
+#pragma pack(pop)
+
+ const int PERSISTENCE_MAX_SIZE = 0xD000;
+
+ // note: NOT_READY and READY are the only entries we have here that are defined by the vanilla game
+ // entries after this are custom and used to determine the source of persistence, e.g. whether it is local or remote
+ enum class ePersistenceReady : char
+ {
+ NOT_READY,
+ READY = 3,
+ READY_INSECURE = 3,
+ READY_REMOTE
+ };
+
+#pragma pack(push, 1)
+ struct CBaseClient // 0x2D728 bytes
+ {
+ char pad0[0x16];
+
+ // +0x16
+ char m_Name[64];
+ // +0x56
+
+ char pad1[0x44A];
+
+ // +0x4A0
+ ePersistenceReady m_iPersistenceReady;
+ // +0x4A1
+
+ char pad2[0x59];
+
+ // +0x4FA
+ char m_PersistenceBuffer[PERSISTENCE_MAX_SIZE];
+
+ char pad3[0x2006];
+
+ // +0xF500
+ char m_UID[32];
+ // +0xF520
+
+ char pad4[0x1E208];
+ };
+#pragma pack(pop)
+
+ extern CBaseClient* g_pClientArray;
+
+ enum server_state_t
+ {
+ ss_dead = 0, // Dead
+ ss_loading, // Spawning
+ ss_active, // Running
+ ss_paused, // Running, but paused
+ };
+
+ extern server_state_t* g_pServerState;
+
+ extern char* g_pModName;
+} // namespace R2
diff --git a/NorthstarDLL/r2server.cpp b/NorthstarDLL/r2server.cpp
new file mode 100644
index 00000000..50cfa239
--- /dev/null
+++ b/NorthstarDLL/r2server.cpp
@@ -0,0 +1,17 @@
+#include "pch.h"
+#include "r2server.h"
+
+using namespace R2;
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ CBaseEntity* (*Server_GetEntityByIndex)(int index);
+ CBasePlayer*(__fastcall* UTIL_PlayerByIndex)(int playerIndex);
+} // namespace R2
+
+ON_DLL_LOAD("server.dll", R2GameServer, (CModule module))
+{
+ Server_GetEntityByIndex = module.Offset(0xFB820).As<CBaseEntity* (*)(int)>();
+ UTIL_PlayerByIndex = module.Offset(0x26AA10).As<CBasePlayer*(__fastcall*)(int)>();
+}
diff --git a/NorthstarDLL/r2server.h b/NorthstarDLL/r2server.h
new file mode 100644
index 00000000..58b39a05
--- /dev/null
+++ b/NorthstarDLL/r2server.h
@@ -0,0 +1,19 @@
+#pragma once
+
+// use the R2 namespace for game funcs
+namespace R2
+{
+ // server entity stuff
+ class CBaseEntity;
+ extern CBaseEntity* (*Server_GetEntityByIndex)(int index);
+
+#pragma pack(push, 1)
+ struct CBasePlayer
+ {
+ char pad[88];
+ int m_nPlayerIndex;
+ };
+#pragma pack(pop)
+
+ extern CBasePlayer*(__fastcall* UTIL_PlayerByIndex)(int playerIndex);
+} // namespace R2
diff --git a/NorthstarDLL/rpakfilesystem.cpp b/NorthstarDLL/rpakfilesystem.cpp
new file mode 100644
index 00000000..b1363589
--- /dev/null
+++ b/NorthstarDLL/rpakfilesystem.cpp
@@ -0,0 +1,299 @@
+#include "pch.h"
+#include "rpakfilesystem.h"
+#include "modmanager.h"
+#include "dedicated.h"
+#include "tier0.h"
+
+AUTOHOOK_INIT()
+
+// there are more i'm just too lazy to add
+struct PakLoadFuncs
+{
+ void* unk0[3];
+ int (*LoadPakAsync)(const char* pPath, void* unknownSingleton, int flags, void* callback0, void* callback1);
+ void* unk1[2];
+ void* (*UnloadPak)(int iPakHandle, void* callback);
+ void* unk2[6];
+ void* (*LoadFile)(const char* path); // unsure
+ void* unk3[10];
+ void* (*ReadFileAsync)(const char* pPath, void* a2);
+};
+
+PakLoadFuncs* g_pakLoadApi;
+
+PakLoadManager* g_pPakLoadManager;
+void** pUnknownPakLoadSingleton;
+
+int PakLoadManager::LoadPakAsync(const char* pPath, const ePakLoadSource nLoadSource)
+{
+ int nHandle = g_pakLoadApi->LoadPakAsync(pPath, *pUnknownPakLoadSingleton, 2, nullptr, nullptr);
+
+ // set the load source of the pak we just loaded
+ if (nHandle != -1)
+ GetPakInfo(nHandle)->m_nLoadSource = nLoadSource;
+
+ return nHandle;
+}
+
+void PakLoadManager::UnloadPak(const int nPakHandle)
+{
+ g_pakLoadApi->UnloadPak(nPakHandle, nullptr);
+}
+
+void PakLoadManager::UnloadMapPaks()
+{
+ for (auto& pair : m_vLoadedPaks)
+ if (pair.second.m_nLoadSource == ePakLoadSource::MAP)
+ UnloadPak(pair.first);
+}
+
+LoadedPak* PakLoadManager::TrackLoadedPak(ePakLoadSource nLoadSource, int nPakHandle, size_t nPakNameHash)
+{
+ LoadedPak pak;
+ pak.m_nLoadSource = nLoadSource;
+ pak.m_nPakHandle = nPakHandle;
+ pak.m_nPakNameHash = nPakNameHash;
+
+ m_vLoadedPaks.insert(std::make_pair(nPakHandle, pak));
+ return &m_vLoadedPaks.at(nPakHandle);
+}
+
+void PakLoadManager::RemoveLoadedPak(int nPakHandle)
+{
+ m_vLoadedPaks.erase(nPakHandle);
+}
+
+LoadedPak* PakLoadManager::GetPakInfo(const int nPakHandle)
+{
+ return &m_vLoadedPaks.at(nPakHandle);
+}
+
+int PakLoadManager::GetPakHandle(const size_t nPakNameHash)
+{
+ for (auto& pair : m_vLoadedPaks)
+ if (pair.second.m_nPakNameHash == nPakNameHash)
+ return pair.first;
+
+ return -1;
+}
+
+int PakLoadManager::GetPakHandle(const char* pPath)
+{
+ return GetPakHandle(STR_HASH(pPath));
+}
+
+void* PakLoadManager::LoadFile(const char* path)
+{
+ return g_pakLoadApi->LoadFile(path);
+}
+
+void HandlePakAliases(char** map)
+{
+ // convert the pak being loaded to it's aliased one, e.g. aliasing mp_hub_timeshift => sp_hub_timeshift
+ for (int64_t i = g_pModManager->m_LoadedMods.size() - 1; i > -1; i--)
+ {
+ Mod* mod = &g_pModManager->m_LoadedMods[i];
+ if (!mod->m_bEnabled)
+ continue;
+
+ if (mod->RpakAliases.find(*map) != mod->RpakAliases.end())
+ {
+ *map = &mod->RpakAliases[*map][0];
+ return;
+ }
+ }
+}
+
+void LoadPreloadPaks()
+{
+ // note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.m_bEnabled)
+ continue;
+
+ // need to get a relative path of mod to mod folder
+ fs::path modPakPath("./" / mod.m_ModDirectory / "paks");
+
+ for (ModRpakEntry& pak : mod.Rpaks)
+ if (pak.m_bAutoLoad)
+ g_pPakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakName).string().c_str(), ePakLoadSource::CONSTANT);
+ }
+}
+
+void LoadPostloadPaks(const char* pPath)
+{
+ // note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.m_bEnabled)
+ continue;
+
+ // need to get a relative path of mod to mod folder
+ fs::path modPakPath("./" / mod.m_ModDirectory / "paks");
+
+ for (ModRpakEntry& pak : mod.Rpaks)
+ if (pak.m_sLoadAfterPak == pPath)
+ g_pPakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakName).string().c_str(), ePakLoadSource::CONSTANT);
+ }
+}
+
+void LoadCustomMapPaks(char** pakName, bool* bNeedToFreePakName)
+{
+ // whether the vanilla game has this rpak
+ bool bHasOriginalPak = fs::exists(fs::path("r2/paks/Win64/") / *pakName);
+
+ // note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.m_bEnabled)
+ continue;
+
+ // need to get a relative path of mod to mod folder
+ fs::path modPakPath("./" / mod.m_ModDirectory / "paks");
+
+ for (ModRpakEntry& pak : mod.Rpaks)
+ {
+ if (!pak.m_bAutoLoad && !pak.m_sPakName.compare(*pakName))
+ {
+ // if the game doesn't have the original pak, let it handle loading this one as if it was the one it was loading originally
+ if (!bHasOriginalPak)
+ {
+ std::string path = (modPakPath / pak.m_sPakName).string();
+ *pakName = new char[path.size() + 1];
+ strcpy(*pakName, &path[0]);
+ (*pakName)[path.size()] = '\0';
+
+ bHasOriginalPak = true;
+ *bNeedToFreePakName =
+ true; // we can't free this memory until we're done with the pak, so let whatever's calling this deal with it
+ }
+ else
+ g_pPakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakName).string().c_str(), ePakLoadSource::MAP);
+ }
+ }
+ }
+}
+
+// clang-format off
+HOOK(LoadPakAsyncHook, LoadPakAsync,
+int, __fastcall, (char* pPath, void* unknownSingleton, int flags, void* pCallback0, void* pCallback1))
+// clang-format on
+{
+ HandlePakAliases(&pPath);
+
+ // dont load the pak if it's currently loaded already
+ size_t nPathHash = STR_HASH(pPath);
+ if (g_pPakLoadManager->GetPakHandle(nPathHash) != -1)
+ return -1;
+
+ bool bNeedToFreePakName = false;
+
+ static bool bShouldLoadPaks = true;
+ if (bShouldLoadPaks)
+ {
+ // make a copy of the path for comparing to determine whether we should load this pak on dedi, before it could get overwritten by
+ // LoadCustomMapPaks
+ std::string originalPath(pPath);
+
+ // disable preloading while we're doing this
+ bShouldLoadPaks = false;
+
+ LoadPreloadPaks();
+ LoadCustomMapPaks(&pPath, &bNeedToFreePakName);
+
+ bShouldLoadPaks = true;
+
+ // do this after custom paks load and in bShouldLoadPaks so we only ever call this on the root pakload call
+ // todo: could probably add some way to flag custom paks to not be loaded on dedicated servers in rpak.json
+ if (IsDedicatedServer() && (Tier0::CommandLine()->CheckParm("-nopakdedi") ||
+ strncmp(&originalPath[0], "common", 6))) // dedicated only needs common and common_mp
+ {
+ if (bNeedToFreePakName)
+ delete[] pPath;
+
+ spdlog::info("Not loading pak {} for dedicated server", originalPath);
+ return -1;
+ }
+ }
+
+ int iPakHandle = LoadPakAsync(pPath, unknownSingleton, flags, pCallback0, pCallback1);
+ spdlog::info("LoadPakAsync {} {}", pPath, iPakHandle);
+
+ // trak the pak
+ g_pPakLoadManager->TrackLoadedPak(ePakLoadSource::UNTRACKED, iPakHandle, nPathHash);
+ LoadPostloadPaks(pPath);
+
+ if (bNeedToFreePakName)
+ delete[] pPath;
+
+ return iPakHandle;
+}
+
+// clang-format off
+HOOK(UnloadPakHook, UnloadPak,
+void*, __fastcall, (int nPakHandle, void* pCallback))
+// clang-format on
+{
+ // stop tracking the pak
+ g_pPakLoadManager->RemoveLoadedPak(nPakHandle);
+
+ static bool bShouldUnloadPaks = true;
+ if (bShouldUnloadPaks)
+ {
+ bShouldUnloadPaks = false;
+ g_pPakLoadManager->UnloadMapPaks();
+ bShouldUnloadPaks = true;
+ }
+
+ spdlog::info("UnloadPak {}", nPakHandle);
+ return UnloadPak(nPakHandle, pCallback);
+}
+
+// we hook this exclusively for resolving stbsp paths, but seemingly it's also used for other stuff like vpk, rpak, mprj and starpak loads
+// tbh this actually might be for memory mapped files or something, would make sense i think
+// clang-format off
+HOOK(ReadFileAsyncHook, ReadFileAsync,
+void*, __fastcall, (const char* pPath, void* pCallback))
+// clang-format on
+{
+ fs::path path(pPath);
+ char* allocatedNewPath = nullptr;
+
+ if (path.extension() == ".stbsp")
+ {
+ fs::path filename = path.filename();
+ spdlog::info("LoadStreamBsp: {}", filename.string());
+
+ // resolve modded stbsp path so we can load mod stbsps
+ auto modFile = g_pModManager->m_ModFiles.find(g_pModManager->NormaliseModFilePath(fs::path("maps" / filename)));
+ if (modFile != g_pModManager->m_ModFiles.end())
+ {
+ // need to allocate a new string for this
+ std::string newPath = (modFile->second.m_pOwningMod->m_ModDirectory / "mod" / modFile->second.m_Path).string();
+ allocatedNewPath = new char[newPath.size() + 1];
+ strncpy_s(allocatedNewPath, newPath.size() + 1, newPath.c_str(), newPath.size());
+ pPath = allocatedNewPath;
+ }
+ }
+
+ void* ret = ReadFileAsync(pPath, pCallback);
+ if (allocatedNewPath)
+ delete[] allocatedNewPath;
+
+ return ret;
+}
+
+ON_DLL_LOAD("engine.dll", RpakFilesystem, (CModule module))
+{
+ AUTOHOOK_DISPATCH();
+
+ g_pPakLoadManager = new PakLoadManager;
+
+ g_pakLoadApi = module.Offset(0x5BED78).Deref().As<PakLoadFuncs*>();
+ pUnknownPakLoadSingleton = module.Offset(0x7C5E20).As<void**>();
+
+ LoadPakAsyncHook.Dispatch(g_pakLoadApi->LoadPakAsync);
+ UnloadPakHook.Dispatch(g_pakLoadApi->UnloadPak);
+ ReadFileAsyncHook.Dispatch(g_pakLoadApi->ReadFileAsync);
+}
diff --git a/NorthstarDLL/rpakfilesystem.h b/NorthstarDLL/rpakfilesystem.h
new file mode 100644
index 00000000..3f608dba
--- /dev/null
+++ b/NorthstarDLL/rpakfilesystem.h
@@ -0,0 +1,39 @@
+#pragma once
+
+enum class ePakLoadSource
+{
+ UNTRACKED = -1, // not a pak we loaded, we shouldn't touch this one
+
+ CONSTANT, // should be loaded at all times
+ MAP // loaded from a map, should be unloaded when the map is unloaded
+};
+
+struct LoadedPak
+{
+ ePakLoadSource m_nLoadSource;
+ int m_nPakHandle;
+ size_t m_nPakNameHash;
+};
+
+class PakLoadManager
+{
+ private:
+ std::map<int, LoadedPak> m_vLoadedPaks {};
+ std::unordered_map<size_t, int> m_HashToPakHandle {};
+
+ public:
+ int LoadPakAsync(const char* pPath, const ePakLoadSource nLoadSource);
+ void UnloadPak(const int nPakHandle);
+ void UnloadMapPaks();
+ void* LoadFile(const char* path); // this is a guess
+
+ LoadedPak* TrackLoadedPak(ePakLoadSource nLoadSource, int nPakHandle, size_t nPakNameHash);
+ void RemoveLoadedPak(int nPakHandle);
+
+ LoadedPak* GetPakInfo(const int nPakHandle);
+
+ int GetPakHandle(const size_t nPakNameHash);
+ int GetPakHandle(const char* pPath);
+};
+
+extern PakLoadManager* g_pPakLoadManager;
diff --git a/NorthstarDLL/runframe.cpp b/NorthstarDLL/runframe.cpp
new file mode 100644
index 00000000..eb401f51
--- /dev/null
+++ b/NorthstarDLL/runframe.cpp
@@ -0,0 +1,20 @@
+#include "pch.h"
+#include "r2engine.h"
+#include "r2server.h"
+#include "hoststate.h"
+#include "serverpresence.h"
+
+AUTOHOOK_INIT()
+
+// clang-format off
+AUTOHOOK(CEngine__Frame, engine.dll + 0x1C8650,
+void, __fastcall, (R2::CEngine* self))
+// clang-format on
+{
+ CEngine__Frame(self);
+}
+
+ON_DLL_LOAD("engine.dll", RunFrame, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+}
diff --git a/NorthstarDLL/scriptbrowserhooks.cpp b/NorthstarDLL/scriptbrowserhooks.cpp
new file mode 100644
index 00000000..df4014de
--- /dev/null
+++ b/NorthstarDLL/scriptbrowserhooks.cpp
@@ -0,0 +1,25 @@
+#include "pch.h"
+
+AUTOHOOK_INIT()
+
+bool* bIsOriginOverlayEnabled;
+
+// clang-format off
+AUTOHOOK(OpenExternalWebBrowser, engine.dll + 0x184E40,
+void, __fastcall, (char* pUrl, char flags))
+// clang-format on
+{
+ bool bIsOriginOverlayEnabledOriginal = *bIsOriginOverlayEnabled;
+ if (flags & 2 && !strncmp(pUrl, "http", 4)) // custom force external browser flag
+ *bIsOriginOverlayEnabled = false; // if this bool is false, game will use an external browser rather than the origin overlay one
+
+ OpenExternalWebBrowser(pUrl, flags);
+ *bIsOriginOverlayEnabled = bIsOriginOverlayEnabledOriginal;
+}
+
+ON_DLL_LOAD_CLIENT("engine.dll", ScriptExternalBrowserHooks, (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ bIsOriginOverlayEnabled = module.Offset(0x13978255).As<bool*>();
+}
diff --git a/NorthstarDLL/scriptdatatables.cpp b/NorthstarDLL/scriptdatatables.cpp
new file mode 100644
index 00000000..fc2be943
--- /dev/null
+++ b/NorthstarDLL/scriptdatatables.cpp
@@ -0,0 +1,940 @@
+#include "pch.h"
+#include "squirrel.h"
+#include "rpakfilesystem.h"
+#include "convar.h"
+#include "dedicated.h"
+#include "filesystem.h"
+#include "vector.h"
+#include "tier0.h"
+#include "r2engine.h"
+#include <iostream>
+#include <sstream>
+#include <map>
+#include <fstream>
+#include <filesystem>
+
+const uint64_t USERDATA_TYPE_DATATABLE = 0xFFF7FFF700000004;
+const uint64_t USERDATA_TYPE_DATATABLE_CUSTOM = 0xFFFCFFFC12345678;
+
+enum class DatatableType : int
+{
+ BOOL = 0,
+ INT,
+ FLOAT,
+ VECTOR,
+ STRING,
+ ASSET,
+ UNK_STRING // unknown but deffo a string type
+};
+
+struct ColumnInfo
+{
+ char* name;
+ DatatableType type;
+ int offset;
+};
+
+struct Datatable
+{
+ int numColumns;
+ int numRows;
+ ColumnInfo* columnInfo;
+ char* data; // actually data pointer
+ int rowInfo;
+};
+
+ConVar* Cvar_ns_prefer_datatable_from_disk;
+
+template <ScriptContext context> Datatable* (*SQ_GetDatatableInternal)(HSquirrelVM* sqvm);
+
+struct CSVData
+{
+ std::string m_sAssetName;
+ std::string m_sCSVString;
+ char* m_pDataBuf;
+ size_t m_nDataBufSize;
+
+ std::vector<char*> columns;
+ std::vector<std::vector<char*>> dataPointers;
+};
+
+std::unordered_map<std::string, CSVData> CSVCache;
+
+Vector3 StringToVector(char* pString)
+{
+ Vector3 vRet;
+
+ int length = 0;
+ while (pString[length])
+ {
+ if ((pString[length] == '<') || (pString[length] == '>'))
+ pString[length] = '\0';
+ length++;
+ }
+
+ int startOfFloat = 1;
+ int currentIndex = 1;
+
+ while (pString[currentIndex] && (pString[currentIndex] != ','))
+ currentIndex++;
+ pString[currentIndex] = '\0';
+ vRet.x = std::stof(&pString[startOfFloat]);
+ startOfFloat = ++currentIndex;
+
+ while (pString[currentIndex] && (pString[currentIndex] != ','))
+ currentIndex++;
+ pString[currentIndex] = '\0';
+ vRet.y = std::stof(&pString[startOfFloat]);
+ startOfFloat = ++currentIndex;
+
+ while (pString[currentIndex] && (pString[currentIndex] != ','))
+ currentIndex++;
+ pString[currentIndex] = '\0';
+ vRet.z = std::stof(&pString[startOfFloat]);
+ startOfFloat = ++currentIndex;
+
+ return vRet;
+}
+
+// var function GetDataTable( asset path )
+template <ScriptContext context> SQRESULT SQ_GetDatatable(HSquirrelVM* sqvm)
+{
+ const char* pAssetName;
+ g_pSquirrel<context>->getasset(sqvm, 2, &pAssetName);
+
+ if (strncmp(pAssetName, "datatable/", 10))
+ {
+ g_pSquirrel<context>->raiseerror(sqvm, fmt::format("Asset \"{}\" doesn't start with \"datatable/\"", pAssetName).c_str());
+ return SQRESULT_ERROR;
+ }
+ else if (!Cvar_ns_prefer_datatable_from_disk->GetBool() && g_pPakLoadManager->LoadFile(pAssetName))
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTable"](sqvm);
+ // either we prefer disk datatables, or we're loading a datatable that wasn't found in rpak
+ else
+ {
+ std::string sAssetPath(fmt::format("scripts/{}", pAssetName));
+
+ // first, check the cache
+ if (CSVCache.find(pAssetName) != CSVCache.end())
+ {
+ CSVData** pUserdata = g_pSquirrel<context>->createuserdata<CSVData*>(sqvm, sizeof(CSVData*));
+ g_pSquirrel<context>->setuserdatatypeid(sqvm, -1, USERDATA_TYPE_DATATABLE_CUSTOM);
+ *pUserdata = &CSVCache[pAssetName];
+
+ return SQRESULT_NOTNULL;
+ }
+
+ // check files on disk
+ // we don't use .rpak as the extension for on-disk datatables, so we need to replace .rpak with .csv in the filename we're reading
+ fs::path diskAssetPath("scripts");
+ if (fs::path(pAssetName).extension() == ".rpak")
+ diskAssetPath /= fs::path(pAssetName).remove_filename() / (fs::path(pAssetName).stem().string() + ".csv");
+ else
+ diskAssetPath /= fs::path(pAssetName);
+
+ std::string sDiskAssetPath(diskAssetPath.string());
+ if ((*R2::g_pFilesystem)->m_vtable2->FileExists(&(*R2::g_pFilesystem)->m_vtable2, sDiskAssetPath.c_str(), "GAME"))
+ {
+ std::string sTableCSV = R2::ReadVPKFile(sDiskAssetPath.c_str());
+ if (!sTableCSV.size())
+ {
+ g_pSquirrel<context>->raiseerror(sqvm, fmt::format("Datatable \"{}\" is empty", pAssetName).c_str());
+ return SQRESULT_ERROR;
+ }
+
+ // somewhat shit, but ensure we end with a newline to make parsing easier
+ if (sTableCSV[sTableCSV.length() - 1] != '\n')
+ sTableCSV += '\n';
+
+ CSVData csv;
+ csv.m_sAssetName = pAssetName;
+ csv.m_sCSVString = sTableCSV;
+ csv.m_nDataBufSize = sTableCSV.size();
+ csv.m_pDataBuf = new char[csv.m_nDataBufSize];
+ memcpy(csv.m_pDataBuf, &sTableCSV[0], csv.m_nDataBufSize);
+
+ // parse the csv
+ // csvs are essentially comma and newline-deliniated sets of strings for parsing, only thing we need to worry about is quoted
+ // entries when we parse an element of the csv, rather than allocating an entry for it, we just convert that element to a
+ // null-terminated string i.e., store the ptr to the first char of it, then make the comma that delinates it a nullchar
+
+ bool bHasColumns = false;
+ bool bInQuotes = false;
+
+ std::vector<char*> vCurrentRow;
+ char* pElemStart = csv.m_pDataBuf;
+ char* pElemEnd = nullptr;
+
+ for (int i = 0; i < csv.m_nDataBufSize; i++)
+ {
+ if (csv.m_pDataBuf[i] == '\r' && csv.m_pDataBuf[i + 1] == '\n')
+ {
+ if (!pElemEnd)
+ pElemEnd = csv.m_pDataBuf + i;
+
+ continue; // next iteration can handle the \n
+ }
+
+ // newline, end of a row
+ if (csv.m_pDataBuf[i] == '\n')
+ {
+ // shouldn't have newline in string
+ if (bInQuotes)
+ {
+ g_pSquirrel<context>->raiseerror(sqvm, "Unexpected \\n in string");
+ return SQRESULT_ERROR;
+ }
+
+ // push last entry to current row
+ if (pElemEnd)
+ *pElemEnd = '\0';
+ else
+ csv.m_pDataBuf[i] = '\0';
+
+ vCurrentRow.push_back(pElemStart);
+
+ // newline, push last line to csv data and go from there
+ if (!bHasColumns)
+ {
+ bHasColumns = true;
+ csv.columns = vCurrentRow;
+ }
+ else
+ csv.dataPointers.push_back(vCurrentRow);
+
+ vCurrentRow.clear();
+ // put start of current element at char after newline
+ pElemStart = csv.m_pDataBuf + i + 1;
+ pElemEnd = nullptr;
+ }
+ // we're starting or ending a quoted string
+ else if (csv.m_pDataBuf[i] == '"')
+ {
+ // start quoted string
+ if (!bInQuotes)
+ {
+ // shouldn't have quoted strings in column names
+ if (!bHasColumns)
+ {
+ g_pSquirrel<context>->raiseerror(sqvm, "Unexpected \" in column name");
+ return SQRESULT_ERROR;
+ }
+
+ bInQuotes = true;
+ // put start of current element at char after string begin
+ pElemStart = csv.m_pDataBuf + i + 1;
+ }
+ // end quoted string
+ else
+ {
+ pElemEnd = csv.m_pDataBuf + i;
+ bInQuotes = false;
+ }
+ }
+ // don't parse commas in quotes
+ else if (bInQuotes)
+ {
+ continue;
+ }
+ // comma, push new entry to current row
+ else if (csv.m_pDataBuf[i] == ',')
+ {
+ if (pElemEnd)
+ *pElemEnd = '\0';
+ else
+ csv.m_pDataBuf[i] = '\0';
+
+ vCurrentRow.push_back(pElemStart);
+ // put start of next element at char after comma
+ pElemStart = csv.m_pDataBuf + i + 1;
+ pElemEnd = nullptr;
+ }
+ }
+
+ // add to cache and return
+ CSVData** pUserdata = g_pSquirrel<context>->createuserdata<CSVData*>(sqvm, sizeof(CSVData*));
+ g_pSquirrel<context>->setuserdatatypeid(sqvm, -1, USERDATA_TYPE_DATATABLE_CUSTOM);
+ CSVCache[pAssetName] = csv;
+ *pUserdata = &CSVCache[pAssetName];
+
+ return SQRESULT_NOTNULL;
+ }
+ // the file doesn't exist on disk, check rpak if we haven't already
+ else if (Cvar_ns_prefer_datatable_from_disk->GetBool() && g_pPakLoadManager->LoadFile(pAssetName))
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTable"](sqvm);
+ // the file doesn't exist at all, error
+ else
+ {
+ g_pSquirrel<context>->raiseerror(sqvm, fmt::format("Datatable {} not found", pAssetName).c_str());
+ return SQRESULT_ERROR;
+ }
+ }
+}
+
+// int function GetDataTableRowCount( var datatable, string columnName )
+template <ScriptContext context> SQRESULT SQ_GetDataTableColumnByName(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableColumnByName"](sqvm);
+
+ CSVData* csv = *pData;
+ const char* pColumnName = g_pSquirrel<context>->getstring(sqvm, 2);
+
+ for (int i = 0; i < csv->columns.size(); i++)
+ {
+ if (!strcmp(csv->columns[i], pColumnName))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ // column not found
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowCount( var datatable )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowCount(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDatatableRowCount"](sqvm);
+
+ CSVData* csv = *pData;
+ g_pSquirrel<context>->pushinteger(sqvm, csv->dataPointers.size());
+ return SQRESULT_NOTNULL;
+}
+
+// string function GetDataTableString( var datatable, int row, int col )
+template <ScriptContext context> SQRESULT SQ_GetDataTableString(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableString"](sqvm);
+
+ CSVData* csv = *pData;
+ const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
+ {
+ g_pSquirrel<context>->raiseerror(
+ sqvm,
+ fmt::format(
+ "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<context>->pushstring(sqvm, csv->dataPointers[nRow][nCol], -1);
+ return SQRESULT_NOTNULL;
+}
+
+// asset function GetDataTableAsset( var datatable, int row, int col )
+template <ScriptContext context> SQRESULT SQ_GetDataTableAsset(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableAsset"](sqvm);
+
+ CSVData* csv = *pData;
+ const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
+ {
+ g_pSquirrel<context>->raiseerror(
+ sqvm,
+ fmt::format(
+ "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<context>->pushasset(sqvm, csv->dataPointers[nRow][nCol], -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableInt( var datatable, int row, int col )
+template <ScriptContext context> SQRESULT SQ_GetDataTableInt(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableInt"](sqvm);
+
+ CSVData* csv = *pData;
+ const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
+ {
+ g_pSquirrel<context>->raiseerror(
+ sqvm,
+ fmt::format(
+ "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, std::stoi(csv->dataPointers[nRow][nCol]));
+ return SQRESULT_NOTNULL;
+}
+
+// float function GetDataTableFloat( var datatable, int row, int col )
+template <ScriptContext context> SQRESULT SQ_GetDataTableFloat(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableFloat"](sqvm);
+
+ CSVData* csv = *pData;
+ const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
+ {
+ g_pSquirrel<context>->raiseerror(
+ sqvm,
+ fmt::format(
+ "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<context>->pushfloat(sqvm, std::stof(csv->dataPointers[nRow][nCol]));
+ return SQRESULT_NOTNULL;
+}
+
+// bool function GetDataTableBool( var datatable, int row, int col )
+template <ScriptContext context> SQRESULT SQ_GetDataTableBool(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableBool"](sqvm);
+
+ CSVData* csv = *pData;
+ const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
+ {
+ g_pSquirrel<context>->raiseerror(
+ sqvm,
+ fmt::format(
+ "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<context>->pushbool(sqvm, std::stoi(csv->dataPointers[nRow][nCol]));
+ return SQRESULT_NOTNULL;
+}
+
+// vector function GetDataTableVector( var datatable, int row, int col )
+template <ScriptContext context> SQRESULT SQ_GetDataTableVector(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableVector"](sqvm);
+
+ CSVData* csv = *pData;
+ const int nRow = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nCol = g_pSquirrel<context>->getinteger(sqvm, 3);
+ if (nRow >= csv->dataPointers.size() || nCol >= csv->dataPointers[nRow].size())
+ {
+ g_pSquirrel<context>->raiseerror(
+ sqvm,
+ fmt::format(
+ "row {} and col {} are outside of range row {} and col {}", nRow, nCol, csv->dataPointers.size(), csv->columns.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<context>->pushvector(sqvm, StringToVector(csv->dataPointers[nRow][nCol]));
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowMatchingStringValue( var datatable, int col, string value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowMatchingStringValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingStringValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const char* pStringVal = g_pSquirrel<context>->getstring(sqvm, 3);
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (!strcmp(csv->dataPointers[i][nCol], pStringVal))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowMatchingAssetValue( var datatable, int col, asset value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowMatchingAssetValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingAssetValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const char* pStringVal;
+ g_pSquirrel<context>->getasset(sqvm, 3, &pStringVal);
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (!strcmp(csv->dataPointers[i][nCol], pStringVal))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowMatchingFloatValue( var datatable, int col, float value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowMatchingFloatValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingFloatValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const float flFloatVal = g_pSquirrel<context>->getfloat(sqvm, 3);
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (flFloatVal == std::stof(csv->dataPointers[i][nCol]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowMatchingIntValue( var datatable, int col, int value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowMatchingIntValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingIntValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nIntVal = g_pSquirrel<context>->getinteger(sqvm, 3);
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (nIntVal == std::stoi(csv->dataPointers[i][nCol]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowMatchingVectorValue( var datatable, int col, vector value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowMatchingVectorValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowMatchingVectorValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const Vector3 vVectorVal = g_pSquirrel<context>->getvector(sqvm, 3);
+
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (vVectorVal == StringToVector(csv->dataPointers[i][nCol]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowGreaterThanOrEqualToIntValue( var datatable, int col, int value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowGreaterThanOrEqualToIntValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowGreaterThanOrEqualToIntValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nIntVal = g_pSquirrel<context>->getinteger(sqvm, 3);
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (nIntVal >= std::stoi(csv->dataPointers[i][nCol]))
+ {
+ spdlog::info("datatable not loaded");
+ g_pSquirrel<context>->pushinteger(sqvm, 1);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowLessThanOrEqualToIntValue( var datatable, int col, int value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowLessThanOrEqualToIntValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowLessThanOrEqualToIntValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const int nIntVal = g_pSquirrel<context>->getinteger(sqvm, 3);
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (nIntVal <= std::stoi(csv->dataPointers[i][nCol]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowGreaterThanOrEqualToFloatValue( var datatable, int col, float value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowGreaterThanOrEqualToFloatValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowGreaterThanOrEqualToFloatValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const float flFloatVal = g_pSquirrel<context>->getfloat(sqvm, 3);
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (flFloatVal >= std::stof(csv->dataPointers[i][nCol]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+// int function GetDataTableRowLessThanOrEqualToFloatValue( var datatable, int col, float value )
+template <ScriptContext context> SQRESULT SQ_GetDataTableRowLessThanOrEqualToFloatValue(HSquirrelVM* sqvm)
+{
+ CSVData** pData;
+ uint64_t typeId;
+ g_pSquirrel<context>->getuserdata(sqvm, 2, &pData, &typeId);
+
+ if (typeId != USERDATA_TYPE_DATATABLE_CUSTOM)
+ return g_pSquirrel<context>->m_funcOriginals["GetDataTableRowLessThanOrEqualToFloatValue"](sqvm);
+
+ CSVData* csv = *pData;
+ int nCol = g_pSquirrel<context>->getinteger(sqvm, 2);
+ const float flFloatVal = g_pSquirrel<context>->getfloat(sqvm, 3);
+ for (int i = 0; i < csv->dataPointers.size(); i++)
+ {
+ if (flFloatVal <= std::stof(csv->dataPointers[i][nCol]))
+ {
+ g_pSquirrel<context>->pushinteger(sqvm, i);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ g_pSquirrel<context>->pushinteger(sqvm, -1);
+ return SQRESULT_NOTNULL;
+}
+
+std::string DataTableToString(Datatable* datatable)
+{
+ std::string sCSVString;
+
+ // write columns
+ bool bShouldComma = false;
+ for (int i = 0; i < datatable->numColumns; i++)
+ {
+ if (bShouldComma)
+ sCSVString += ',';
+ else
+ bShouldComma = true;
+
+ sCSVString += datatable->columnInfo[i].name;
+ }
+
+ // write rows
+ for (int row = 0; row < datatable->numRows; row++)
+ {
+ sCSVString += '\n';
+
+ bool bShouldComma = false;
+ for (int col = 0; col < datatable->numColumns; col++)
+ {
+ if (bShouldComma)
+ sCSVString += ',';
+ else
+ bShouldComma = true;
+
+ // output typed data
+ ColumnInfo column = datatable->columnInfo[col];
+ const void* pUntypedVal = datatable->data + column.offset + row * datatable->rowInfo;
+ switch (column.type)
+ {
+ case DatatableType::BOOL:
+ {
+ sCSVString += *(bool*)pUntypedVal ? '1' : '0';
+ break;
+ }
+
+ case DatatableType::INT:
+ {
+ sCSVString += std::to_string(*(int*)pUntypedVal);
+ break;
+ }
+
+ case DatatableType::FLOAT:
+ {
+ sCSVString += std::to_string(*(float*)pUntypedVal);
+ break;
+ }
+
+ case DatatableType::VECTOR:
+ {
+ Vector3 pVector((float*)pUntypedVal);
+ sCSVString += fmt::format("<{},{},{}>", pVector.x, pVector.y, pVector.z);
+ break;
+ }
+
+ case DatatableType::STRING:
+ case DatatableType::ASSET:
+ case DatatableType::UNK_STRING:
+ {
+ sCSVString += fmt::format("\"{}\"", *(char**)pUntypedVal);
+ break;
+ }
+ }
+ }
+ }
+
+ return sCSVString;
+}
+
+void DumpDatatable(const char* pDatatablePath)
+{
+ Datatable* pDatatable = (Datatable*)g_pPakLoadManager->LoadFile(pDatatablePath);
+ if (!pDatatable)
+ {
+ spdlog::error("couldn't load datatable {} (rpak containing it may not be loaded?)", pDatatablePath);
+ return;
+ }
+
+ std::string sOutputPath(fmt::format("{}/scripts/datatable/{}.csv", R2::g_pModName, fs::path(pDatatablePath).stem().string()));
+ std::string sDatatableContents(DataTableToString(pDatatable));
+
+ fs::create_directories(fs::path(sOutputPath).remove_filename());
+ std::ofstream outputStream(sOutputPath);
+ outputStream.write(sDatatableContents.c_str(), sDatatableContents.size());
+ outputStream.close();
+
+ spdlog::info("dumped datatable {} {} to {}", pDatatablePath, (void*)pDatatable, sOutputPath);
+}
+
+void ConCommand_dump_datatable(const CCommand& args)
+{
+ if (args.ArgC() < 2)
+ {
+ spdlog::info("usage: dump_datatable datatable/tablename.rpak");
+ return;
+ }
+
+ DumpDatatable(args.Arg(1));
+}
+
+void ConCommand_dump_datatables(const CCommand& args)
+{
+ // likely not a comprehensive list, might be missing a couple?
+ static const std::vector<const char*> VANILLA_DATATABLE_PATHS = {
+ "datatable/burn_meter_rewards.rpak",
+ "datatable/burn_meter_store.rpak",
+ "datatable/calling_cards.rpak",
+ "datatable/callsign_icons.rpak",
+ "datatable/camo_skins.rpak",
+ "datatable/default_pilot_loadouts.rpak",
+ "datatable/default_titan_loadouts.rpak",
+ "datatable/faction_leaders.rpak",
+ "datatable/fd_awards.rpak",
+ "datatable/features_mp.rpak",
+ "datatable/non_loadout_weapons.rpak",
+ "datatable/pilot_abilities.rpak",
+ "datatable/pilot_executions.rpak",
+ "datatable/pilot_passives.rpak",
+ "datatable/pilot_properties.rpak",
+ "datatable/pilot_weapons.rpak",
+ "datatable/pilot_weapon_features.rpak",
+ "datatable/pilot_weapon_mods.rpak",
+ "datatable/pilot_weapon_mods_common.rpak",
+ "datatable/playlist_items.rpak",
+ "datatable/titans_mp.rpak",
+ "datatable/titan_abilities.rpak",
+ "datatable/titan_executions.rpak",
+ "datatable/titan_fd_upgrades.rpak",
+ "datatable/titan_nose_art.rpak",
+ "datatable/titan_passives.rpak",
+ "datatable/titan_primary_mods.rpak",
+ "datatable/titan_primary_mods_common.rpak",
+ "datatable/titan_primary_weapons.rpak",
+ "datatable/titan_properties.rpak",
+ "datatable/titan_skins.rpak",
+ "datatable/titan_voices.rpak",
+ "datatable/unlocks_faction_level.rpak",
+ "datatable/unlocks_fd_titan_level.rpak",
+ "datatable/unlocks_player_level.rpak",
+ "datatable/unlocks_random.rpak",
+ "datatable/unlocks_titan_level.rpak",
+ "datatable/unlocks_weapon_level_pilot.rpak",
+ "datatable/weapon_skins.rpak",
+ "datatable/xp_per_faction_level.rpak",
+ "datatable/xp_per_fd_titan_level.rpak",
+ "datatable/xp_per_player_level.rpak",
+ "datatable/xp_per_titan_level.rpak",
+ "datatable/xp_per_weapon_level.rpak",
+ "datatable/faction_leaders_dropship_anims.rpak",
+ "datatable/score_events.rpak",
+ "datatable/startpoints.rpak",
+ "datatable/sp_levels.rpak",
+ "datatable/community_entries.rpak",
+ "datatable/spotlight_images.rpak",
+ "datatable/death_hints_mp.rpak",
+ "datatable/flightpath_assets.rpak",
+ "datatable/earn_meter_mp.rpak",
+ "datatable/battle_chatter_voices.rpak",
+ "datatable/battle_chatter.rpak",
+ "datatable/titan_os_conversations.rpak",
+ "datatable/faction_dialogue.rpak",
+ "datatable/grunt_chatter_mp.rpak",
+ "datatable/spectre_chatter_mp.rpak",
+ "datatable/pain_death_sounds.rpak",
+ "datatable/caller_ids_mp.rpak"};
+
+ for (const char* datatable : VANILLA_DATATABLE_PATHS)
+ DumpDatatable(datatable);
+}
+
+template <ScriptContext context> void RegisterDataTableFunctions()
+{
+ g_pSquirrel<context>->AddFuncOverride("GetDataTable", SQ_GetDatatable<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableColumnByName", SQ_GetDataTableColumnByName<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDatatableRowCount", SQ_GetDataTableRowCount<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableString", SQ_GetDataTableString<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableInt", SQ_GetDataTableInt<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableFloat", SQ_GetDataTableFloat<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableBool", SQ_GetDataTableBool<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableAsset", SQ_GetDataTableAsset<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableVector", SQ_GetDataTableVector<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingStringValue", SQ_GetDataTableRowMatchingStringValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingAssetValue", SQ_GetDataTableRowMatchingAssetValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingFloatValue", SQ_GetDataTableRowMatchingFloatValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingIntValue", SQ_GetDataTableRowMatchingIntValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowMatchingVectorValue", SQ_GetDataTableRowMatchingVectorValue<context>);
+ g_pSquirrel<context>->AddFuncOverride(
+ "GetDataTableRowLessThanOrEqualToFloatValue", SQ_GetDataTableRowLessThanOrEqualToFloatValue<context>);
+ g_pSquirrel<context>->AddFuncOverride(
+ "GetDataTableRowGreaterThanOrEqualToFloatValue", SQ_GetDataTableRowGreaterThanOrEqualToFloatValue<context>);
+ g_pSquirrel<context>->AddFuncOverride("GetDataTableRowLessThanOrEqualToIntValue", SQ_GetDataTableRowLessThanOrEqualToIntValue<context>);
+ g_pSquirrel<context>->AddFuncOverride(
+ "GetDataTableRowGreaterThanOrEqualToFloatValue", SQ_GetDataTableRowGreaterThanOrEqualToIntValue<context>);
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerScriptDatatables, ServerSquirrel, (CModule module))
+{
+ RegisterDataTableFunctions<ScriptContext::SERVER>();
+
+ SQ_GetDatatableInternal<ScriptContext::SERVER> = module.Offset(0x1250f0).As<Datatable* (*)(HSquirrelVM*)>();
+}
+
+ON_DLL_LOAD_RELIESON("client.dll", ClientScriptDatatables, ClientSquirrel, (CModule module))
+{
+ RegisterDataTableFunctions<ScriptContext::CLIENT>();
+ RegisterDataTableFunctions<ScriptContext::UI>();
+
+ SQ_GetDatatableInternal<ScriptContext::CLIENT> = module.Offset(0x1C9070).As<Datatable* (*)(HSquirrelVM*)>();
+ SQ_GetDatatableInternal<ScriptContext::UI> = SQ_GetDatatableInternal<ScriptContext::CLIENT>;
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", SharedScriptDataTables, ConVar, (CModule module))
+{
+ Cvar_ns_prefer_datatable_from_disk = new ConVar(
+ "ns_prefer_datatable_from_disk",
+ IsDedicatedServer() && Tier0::CommandLine()->CheckParm("-nopakdedi") ? "1" : "0",
+ FCVAR_NONE,
+ "whether to prefer loading datatables from disk, rather than rpak");
+
+ RegisterConCommand("dump_datatables", ConCommand_dump_datatables, "dumps all datatables from a hardcoded list", FCVAR_NONE);
+ RegisterConCommand("dump_datatable", ConCommand_dump_datatable, "dump a datatable", FCVAR_NONE);
+}
diff --git a/NorthstarDLL/scriptjson.cpp b/NorthstarDLL/scriptjson.cpp
new file mode 100644
index 00000000..a9767615
--- /dev/null
+++ b/NorthstarDLL/scriptjson.cpp
@@ -0,0 +1,282 @@
+#include "pch.h"
+#include "squirrel.h"
+
+#include "rapidjson/error/en.h"
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+#include "rapidjson/stringbuffer.h"
+
+#ifdef _MSC_VER
+#undef GetObject // fuck microsoft developers
+#endif
+
+template <ScriptContext context> void
+DecodeJsonArray(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* arr)
+{
+ g_pSquirrel<context>->newarray(sqvm, 0);
+
+ for (auto& itr : arr->GetArray())
+ {
+ switch (itr.GetType())
+ {
+ case rapidjson::kObjectType:
+ DecodeJsonTable<context>(sqvm, &itr);
+ g_pSquirrel<context>->arrayappend(sqvm, -2);
+ break;
+ case rapidjson::kArrayType:
+ DecodeJsonArray<context>(sqvm, &itr);
+ g_pSquirrel<context>->arrayappend(sqvm, -2);
+ break;
+ case rapidjson::kStringType:
+ g_pSquirrel<context>->pushstring(sqvm, itr.GetString(), -1);
+ g_pSquirrel<context>->arrayappend(sqvm, -2);
+ break;
+ case rapidjson::kTrueType:
+ case rapidjson::kFalseType:
+ g_pSquirrel<context>->pushbool(sqvm, itr.GetBool());
+ g_pSquirrel<context>->arrayappend(sqvm, -2);
+ break;
+ case rapidjson::kNumberType:
+ if (itr.IsDouble() || itr.IsFloat())
+ g_pSquirrel<context>->pushfloat(sqvm, itr.GetFloat());
+ else
+ g_pSquirrel<context>->pushinteger(sqvm, itr.GetInt());
+ g_pSquirrel<context>->arrayappend(sqvm, -2);
+ break;
+ }
+ }
+}
+
+template <ScriptContext context> void
+DecodeJsonTable(HSquirrelVM* sqvm, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj)
+{
+ g_pSquirrel<context>->newtable(sqvm);
+
+ for (auto itr = obj->MemberBegin(); itr != obj->MemberEnd(); itr++)
+ {
+ switch (itr->value.GetType())
+ {
+ case rapidjson::kObjectType:
+ g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
+ DecodeJsonTable<context>(
+ sqvm, (rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>*)&itr->value);
+ g_pSquirrel<context>->newslot(sqvm, -3, false);
+ break;
+ case rapidjson::kArrayType:
+ g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
+ DecodeJsonArray<context>(
+ sqvm, (rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>*)&itr->value);
+ g_pSquirrel<context>->newslot(sqvm, -3, false);
+ break;
+ case rapidjson::kStringType:
+ g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
+ g_pSquirrel<context>->pushstring(sqvm, itr->value.GetString(), -1);
+
+ g_pSquirrel<context>->newslot(sqvm, -3, false);
+ break;
+ case rapidjson::kTrueType:
+ case rapidjson::kFalseType:
+ g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
+ g_pSquirrel<context>->pushbool(sqvm, itr->value.GetBool());
+ g_pSquirrel<context>->newslot(sqvm, -3, false);
+ break;
+ case rapidjson::kNumberType:
+ if (itr->value.IsDouble() || itr->value.IsFloat())
+ {
+ g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
+ g_pSquirrel<context>->pushfloat(sqvm, itr->value.GetFloat());
+ }
+ else
+ {
+ g_pSquirrel<context>->pushstring(sqvm, itr->name.GetString(), -1);
+ g_pSquirrel<context>->pushinteger(sqvm, itr->value.GetInt());
+ }
+ g_pSquirrel<context>->newslot(sqvm, -3, false);
+ break;
+ }
+ }
+}
+
+template <ScriptContext context> void EncodeJSONTable(
+ SQTable* table,
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj,
+ rapidjson::MemoryPoolAllocator<SourceAllocator>& allocator)
+{
+ for (int i = 0; i < table->_numOfNodes; i++)
+ {
+ tableNode* node = &table->_nodes[i];
+ if (node->key._Type == OT_STRING)
+ {
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>> newObj(rapidjson::kObjectType);
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>> newArray(rapidjson::kArrayType);
+
+ switch (node->val._Type)
+ {
+ case OT_STRING:
+ obj->AddMember(
+ rapidjson::StringRef(node->key._VAL.asString->_val), rapidjson::StringRef(node->val._VAL.asString->_val), allocator);
+ break;
+ case OT_INTEGER:
+ obj->AddMember(
+ rapidjson::StringRef(node->key._VAL.asString->_val),
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>(
+ (int)node->val._VAL.asInteger),
+ allocator);
+ break;
+ case OT_FLOAT:
+ obj->AddMember(
+ rapidjson::StringRef(node->key._VAL.asString->_val),
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>(node->val._VAL.asFloat),
+ allocator);
+ break;
+ case OT_BOOL:
+ if (node->val._VAL.asInteger)
+ {
+ obj->AddMember(
+ rapidjson::StringRef(node->key._VAL.asString->_val),
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>(true),
+ allocator);
+ }
+ else
+ {
+ obj->AddMember(
+ rapidjson::StringRef(node->key._VAL.asString->_val),
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>(false),
+ allocator);
+ }
+ break;
+ case OT_TABLE:
+ EncodeJSONTable<context>(node->val._VAL.asTable, &newObj, allocator);
+ obj->AddMember(rapidjson::StringRef(node->key._VAL.asString->_val), newObj, allocator);
+ break;
+ case OT_ARRAY:
+ EncodeJSONArray<context>(node->val._VAL.asArray, &newArray, allocator);
+ obj->AddMember(rapidjson::StringRef(node->key._VAL.asString->_val), newArray, allocator);
+ break;
+ default:
+ spdlog::warn("SQ_EncodeJSON: squirrel type {} not supported", SQTypeNameFromID(node->val._Type));
+ break;
+ }
+ }
+ }
+}
+
+template <ScriptContext context> void EncodeJSONArray(
+ SQArray* arr,
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>* obj,
+ rapidjson::MemoryPoolAllocator<SourceAllocator>& allocator)
+{
+ for (int i = 0; i < arr->_usedSlots; i++)
+ {
+ SQObject* node = &arr->_values[i];
+
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>> newObj(rapidjson::kObjectType);
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>> newArray(rapidjson::kArrayType);
+
+ switch (node->_Type)
+ {
+ case OT_STRING:
+ obj->PushBack(rapidjson::StringRef(node->_VAL.asString->_val), allocator);
+ break;
+ case OT_INTEGER:
+ obj->PushBack(
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>((int)node->_VAL.asInteger),
+ allocator);
+ break;
+ case OT_FLOAT:
+ obj->PushBack(
+ rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>(node->_VAL.asFloat),
+ allocator);
+ break;
+ case OT_BOOL:
+ if (node->_VAL.asInteger)
+ obj->PushBack(rapidjson::StringRef("true"), allocator);
+ else
+ obj->PushBack(rapidjson::StringRef("false"), allocator);
+ break;
+ case OT_TABLE:
+ EncodeJSONTable<context>(node->_VAL.asTable, &newObj, allocator);
+ obj->PushBack(newObj, allocator);
+ break;
+ case OT_ARRAY:
+ EncodeJSONArray<context>(node->_VAL.asArray, &newArray, allocator);
+ obj->PushBack(newArray, allocator);
+ break;
+ default:
+ spdlog::info("SQ encode Json type {} not supported", SQTypeNameFromID(node->_Type));
+ }
+ }
+}
+
+// table function DecodeJSON( string json, bool fatalParseErrors = false )
+template <ScriptContext context> SQRESULT SQ_DecodeJSON(HSquirrelVM* sqvm)
+{
+ const char* pJson = g_pSquirrel<context>->getstring(sqvm, 1);
+ const bool bFatalParseErrors = g_pSquirrel<context>->getbool(sqvm, 2);
+
+ rapidjson_document doc;
+ doc.Parse(pJson);
+ if (doc.HasParseError())
+ {
+ g_pSquirrel<context>->newtable(sqvm);
+
+ std::string sErrorString = fmt::format(
+ "Failed parsing json file: encountered parse error \"{}\" at offset {}",
+ GetParseError_En(doc.GetParseError()),
+ doc.GetErrorOffset());
+
+ if (bFatalParseErrors)
+ g_pSquirrel<context>->raiseerror(sqvm, sErrorString.c_str());
+ else
+ spdlog::warn(sErrorString);
+
+ return SQRESULT_NOTNULL;
+ }
+
+ DecodeJsonTable<context>(sqvm, (rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<SourceAllocator>>*)&doc);
+}
+
+// string function EncodeJSON( table data )
+template <ScriptContext context> SQRESULT SQ_EncodeJSON(HSquirrelVM* sqvm)
+{
+ rapidjson_document doc;
+ doc.SetObject();
+
+ // temp until this is just the func parameter type
+ HSquirrelVM* vm = (HSquirrelVM*)sqvm;
+ SQTable* table = vm->_stackOfCurrentFunction[1]._VAL.asTable;
+ EncodeJSONTable<context>(table, &doc, doc.GetAllocator());
+
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ doc.Accept(writer);
+ const char* pJsonString = buffer.GetString();
+
+ g_pSquirrel<context>->pushstring(sqvm, pJsonString, -1);
+ return SQRESULT_NOTNULL;
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientScriptJSON, ClientSquirrel, (CModule module))
+{
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration(
+ "table",
+ "DecodeJSON",
+ "string json, bool fatalParseErrors = false",
+ "converts a json string to a squirrel table",
+ SQ_DecodeJSON<ScriptContext::CLIENT>);
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration(
+ "string", "EncodeJSON", "table data", "converts a squirrel table to a json string", SQ_EncodeJSON<ScriptContext::CLIENT>);
+
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "table", "DecodeJSON", "string json", "converts a json string to a squirrel table", SQ_DecodeJSON<ScriptContext::UI>);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "string", "EncodeJSON", "table data", "converts a squirrel table to a json string", SQ_EncodeJSON<ScriptContext::UI>);
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerScriptJSON, ServerSquirrel, (CModule module))
+{
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration(
+ "table", "DecodeJSON", "string json", "converts a json string to a squirrel table", SQ_DecodeJSON<ScriptContext::SERVER>);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration(
+ "string", "EncodeJSON", "table data", "converts a squirrel table to a json string", SQ_EncodeJSON<ScriptContext::SERVER>);
+}
diff --git a/NorthstarDLL/scriptmainmenupromos.cpp b/NorthstarDLL/scriptmainmenupromos.cpp
new file mode 100644
index 00000000..a1277235
--- /dev/null
+++ b/NorthstarDLL/scriptmainmenupromos.cpp
@@ -0,0 +1,136 @@
+#include "pch.h"
+#include "squirrel.h"
+#include "masterserver.h"
+
+// mirror this in script
+enum eMainMenuPromoDataProperty
+{
+ newInfoTitle1,
+ newInfoTitle2,
+ newInfoTitle3,
+
+ largeButtonTitle,
+ largeButtonText,
+ largeButtonUrl,
+ largeButtonImageIndex,
+
+ smallButton1Title,
+ smallButton1Url,
+ smallButton1ImageIndex,
+
+ smallButton2Title,
+ smallButton2Url,
+ smallButton2ImageIndex
+};
+
+// void function NSRequestCustomMainMenuPromos()
+SQRESULT SQ_RequestCustomMainMenuPromos(HSquirrelVM* sqvm)
+{
+ g_pMasterServerManager->RequestMainMenuPromos();
+ return SQRESULT_NULL;
+}
+
+// bool function NSHasCustomMainMenuPromoData()
+SQRESULT SQ_HasCustomMainMenuPromoData(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bHasMainMenuPromoData);
+ return SQRESULT_NOTNULL;
+}
+
+// var function NSGetCustomMainMenuPromoData( int promoDataKey )
+SQRESULT SQ_GetCustomMainMenuPromoData(HSquirrelVM* sqvm)
+{
+ if (!g_pMasterServerManager->m_bHasMainMenuPromoData)
+ return SQRESULT_NULL;
+
+ switch (g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1))
+ {
+ case eMainMenuPromoDataProperty::newInfoTitle1:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle1.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::newInfoTitle2:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle2.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::newInfoTitle3:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle3.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::largeButtonTitle:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonTitle.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::largeButtonText:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonText.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::largeButtonUrl:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonUrl.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::largeButtonImageIndex:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonImageIndex);
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::smallButton1Title:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1Title.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::smallButton1Url:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1Url.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::smallButton1ImageIndex:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1ImageIndex);
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::smallButton2Title:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2Title.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::smallButton2Url:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2Url.c_str());
+ break;
+ }
+
+ case eMainMenuPromoDataProperty::smallButton2ImageIndex:
+ {
+ g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2ImageIndex);
+ break;
+ }
+ }
+
+ return SQRESULT_NOTNULL;
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptMainMenuPromos, ClientSquirrel, (CModule module))
+{
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSRequestCustomMainMenuPromos", "", "", SQ_RequestCustomMainMenuPromos);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("bool", "NSHasCustomMainMenuPromoData", "", "", SQ_HasCustomMainMenuPromoData);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "var", "NSGetCustomMainMenuPromoData", "int promoDataKey", "", SQ_GetCustomMainMenuPromoData);
+}
diff --git a/NorthstarDLL/scriptmodmenu.cpp b/NorthstarDLL/scriptmodmenu.cpp
new file mode 100644
index 00000000..d2f35285
--- /dev/null
+++ b/NorthstarDLL/scriptmodmenu.cpp
@@ -0,0 +1,203 @@
+#include "pch.h"
+#include "modmanager.h"
+#include "squirrel.h"
+
+// array<string> function NSGetModNames()
+SQRESULT SQ_GetModNames(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->newarray(sqvm, 0);
+
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, mod.Name.c_str());
+ g_pSquirrel<ScriptContext::UI>->arrayappend(sqvm, -2);
+ }
+
+ return SQRESULT_NOTNULL;
+}
+
+// bool function NSIsModEnabled(string modName)
+SQRESULT SQ_IsModEnabled(HSquirrelVM* sqvm)
+{
+ const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, mod.m_bEnabled);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ return SQRESULT_NULL;
+}
+
+// void function NSSetModEnabled(string modName, bool enabled)
+SQRESULT SQ_SetModEnabled(HSquirrelVM* sqvm)
+{
+ const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+ const SQBool enabled = g_pSquirrel<ScriptContext::UI>->getbool(sqvm, 2);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ mod.m_bEnabled = enabled;
+ return SQRESULT_NULL;
+ }
+ }
+
+ return SQRESULT_NULL;
+}
+
+// string function NSGetModDescriptionByModName(string modName)
+SQRESULT SQ_GetModDescription(HSquirrelVM* sqvm)
+{
+ const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, mod.Description.c_str());
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ return SQRESULT_NULL;
+}
+
+// string function NSGetModVersionByModName(string modName)
+SQRESULT SQ_GetModVersion(HSquirrelVM* sqvm)
+{
+ const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, mod.Version.c_str());
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ return SQRESULT_NULL;
+}
+
+// string function NSGetModDownloadLinkByModName(string modName)
+SQRESULT SQ_GetModDownloadLink(HSquirrelVM* sqvm)
+{
+ const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, mod.DownloadLink.c_str());
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ return SQRESULT_NULL;
+}
+
+// int function NSGetModLoadPriority(string modName)
+SQRESULT SQ_GetModLoadPriority(HSquirrelVM* sqvm)
+{
+ const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, mod.LoadPriority);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ return SQRESULT_NULL;
+}
+
+// bool function NSIsModRequiredOnClient(string modName)
+SQRESULT SQ_IsModRequiredOnClient(HSquirrelVM* sqvm)
+{
+ const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, mod.RequiredOnClient);
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ return SQRESULT_NULL;
+}
+
+// array<string> function NSGetModConvarsByModName(string modName)
+SQRESULT SQ_GetModConvars(HSquirrelVM* sqvm)
+{
+ const SQChar* modName = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 1);
+ g_pSquirrel<ScriptContext::UI>->newarray(sqvm, 0);
+
+ // manual lookup, not super performant but eh not a big deal
+ for (Mod& mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.Name.compare(modName))
+ {
+ for (ModConVar* cvar : mod.ConVars)
+ {
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, cvar->Name.c_str());
+ g_pSquirrel<ScriptContext::UI>->arrayappend(sqvm, -2);
+ }
+
+ return SQRESULT_NOTNULL;
+ }
+ }
+
+ return SQRESULT_NOTNULL; // return empty array
+}
+
+// void function NSReloadMods()
+SQRESULT SQ_ReloadMods(HSquirrelVM* sqvm)
+{
+ g_pModManager->LoadMods();
+ return SQRESULT_NULL;
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptModMenu, ClientSquirrel, (CModule module))
+{
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "array<string>", "NSGetModNames", "", "Returns the names of all loaded mods", SQ_GetModNames);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "bool", "NSIsModEnabled", "string modName", "Returns whether a given mod is enabled", SQ_IsModEnabled);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "void", "NSSetModEnabled", "string modName, bool enabled", "Sets whether a given mod is enabled", SQ_SetModEnabled);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "string", "NSGetModDescriptionByModName", "string modName", "Returns a given mod's description", SQ_GetModDescription);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "string", "NSGetModVersionByModName", "string modName", "Returns a given mod's version", SQ_GetModVersion);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "string", "NSGetModDownloadLinkByModName", "string modName", "Returns a given mod's download link", SQ_GetModDownloadLink);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "bool",
+ "NSIsModRequiredOnClient",
+ "string modName",
+ "Returns whether a given mod is required on connecting clients",
+ SQ_IsModRequiredOnClient);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "int", "NSGetModLoadPriority", "string modName", "Returns a given mod's load priority", SQ_GetModLoadPriority);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "array<string>", "NSGetModConvarsByModName", "string modName", "Returns the names of all a given mod's cvars", SQ_GetModConvars);
+
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSReloadMods", "", "Reloads mods", SQ_ReloadMods);
+}
diff --git a/NorthstarDLL/scriptserverbrowser.cpp b/NorthstarDLL/scriptserverbrowser.cpp
new file mode 100644
index 00000000..a361aeb8
--- /dev/null
+++ b/NorthstarDLL/scriptserverbrowser.cpp
@@ -0,0 +1,458 @@
+#include "pch.h"
+#include "squirrel.h"
+#include "masterserver.h"
+#include "serverauthentication.h"
+#include "r2engine.h"
+#include "r2client.h"
+
+// functions for viewing server browser
+
+// bool function NSIsMasterServerAuthenticated()
+SQRESULT SQ_IsMasterServerAuthenticated(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bOriginAuthWithMasterServerDone);
+ return SQRESULT_NOTNULL;
+}
+
+// void function NSRequestServerList()
+SQRESULT SQ_RequestServerList(HSquirrelVM* sqvm)
+{
+ g_pMasterServerManager->RequestServerList();
+ return SQRESULT_NULL;
+}
+
+// bool function NSIsRequestingServerList()
+SQRESULT SQ_IsRequestingServerList(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bScriptRequestingServerList);
+ return SQRESULT_NOTNULL;
+}
+
+// bool function NSMasterServerConnectionSuccessful()
+SQRESULT SQ_MasterServerConnectionSuccessful(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bSuccessfullyConnected);
+ return SQRESULT_NOTNULL;
+}
+
+// int function NSGetServerCount()
+SQRESULT SQ_GetServerCount(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers.size());
+ return SQRESULT_NOTNULL;
+}
+
+// string function NSGetServerName( int serverIndex )
+SQRESULT SQ_GetServerName(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get name of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].name);
+ return SQRESULT_NOTNULL;
+}
+
+// string function NSGetServerDescription( int serverIndex )
+SQRESULT SQ_GetServerDescription(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get description of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].description.c_str());
+ return SQRESULT_NOTNULL;
+}
+
+// string function NSGetServerMap( int serverIndex )
+SQRESULT SQ_GetServerMap(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get map of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].map);
+ return SQRESULT_NOTNULL;
+}
+
+// string function NSGetServerPlaylist( int serverIndex )
+SQRESULT SQ_GetServerPlaylist(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get playlist of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].playlist);
+ return SQRESULT_NOTNULL;
+}
+
+// int function NSGetServerPlayerCount( int serverIndex )
+SQRESULT SQ_GetServerPlayerCount(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get playercount of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].playerCount);
+ return SQRESULT_NOTNULL;
+}
+
+// int function NSGetServerMaxPlayerCount( int serverIndex )
+SQRESULT SQ_GetServerMaxPlayerCount(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get max playercount of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].maxPlayers);
+ return SQRESULT_NOTNULL;
+}
+
+// string function NSGetServerID( int serverIndex )
+SQRESULT SQ_GetServerID(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get id of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].id);
+ return SQRESULT_NOTNULL;
+}
+
+// bool function NSServerRequiresPassword( int serverIndex )
+SQRESULT SQ_ServerRequiresPassword(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get hasPassword of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].requiresPassword);
+ return SQRESULT_NOTNULL;
+}
+
+// int function NSGetServerRequiredModsCount( int serverIndex )
+SQRESULT SQ_GetServerRequiredModsCount(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get required mods count of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size());
+ return SQRESULT_NOTNULL;
+}
+
+// string function NSGetServerRequiredModName( int serverIndex, int modIndex )
+SQRESULT SQ_GetServerRequiredModName(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+ SQInteger modIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 2);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get hasPassword of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ if (modIndex >= g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get required mod name of mod index {} when only {} mod are available",
+ modIndex,
+ g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushstring(
+ sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods[modIndex].Name.c_str());
+ return SQRESULT_NOTNULL;
+}
+
+// string function NSGetServerRequiredModVersion( int serverIndex, int modIndex )
+SQRESULT SQ_GetServerRequiredModVersion(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+ SQInteger modIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 2);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get required mod version of server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ if (modIndex >= g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to get required mod version of mod index {} when only {} mod are available",
+ modIndex,
+ g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ g_pSquirrel<ScriptContext::UI>->pushstring(
+ sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods[modIndex].Version.c_str());
+ return SQRESULT_NOTNULL;
+}
+
+// void function NSClearRecievedServerList()
+SQRESULT SQ_ClearRecievedServerList(HSquirrelVM* sqvm)
+{
+ g_pMasterServerManager->ClearServerList();
+ return SQRESULT_NULL;
+}
+
+// functions for authenticating with servers
+
+// void function NSTryAuthWithServer( int serverIndex, string password = "" )
+SQRESULT SQ_TryAuthWithServer(HSquirrelVM* sqvm)
+{
+ SQInteger serverIndex = g_pSquirrel<ScriptContext::UI>->getinteger(sqvm, 1);
+ const SQChar* password = g_pSquirrel<ScriptContext::UI>->getstring(sqvm, 2);
+
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm,
+ fmt::format(
+ "Tried to auth with server index {} when only {} servers are available",
+ serverIndex,
+ g_pMasterServerManager->m_vRemoteServers.size())
+ .c_str());
+ return SQRESULT_ERROR;
+ }
+
+ // send off persistent data first, don't worry about server/client stuff, since m_additionalPlayerData should only have entries when
+ // we're a local server note: this seems like it could create a race condition, test later
+ for (auto& pair : g_pServerAuthentication->m_PlayerAuthenticationData)
+ g_pServerAuthentication->WritePersistentData(pair.first);
+
+ // do auth
+ g_pMasterServerManager->AuthenticateWithServer(
+ R2::g_pLocalPlayerUserID,
+ g_pMasterServerManager->m_sOwnClientAuthToken,
+ g_pMasterServerManager->m_vRemoteServers[serverIndex].id,
+ (char*)password);
+
+ return SQRESULT_NULL;
+}
+
+// bool function NSIsAuthenticatingWithServer()
+SQRESULT SQ_IsAuthComplete(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bScriptAuthenticatingWithGameServer);
+ return SQRESULT_NOTNULL;
+}
+
+// bool function NSWasAuthSuccessful()
+SQRESULT SQ_WasAuthSuccessful(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->pushbool(sqvm, g_pMasterServerManager->m_bSuccessfullyAuthenticatedWithGameServer);
+ return SQRESULT_NOTNULL;
+}
+
+// void function NSConnectToAuthedServer()
+SQRESULT SQ_ConnectToAuthedServer(HSquirrelVM* sqvm)
+{
+ if (!g_pMasterServerManager->m_bHasPendingConnectionInfo)
+ {
+ g_pSquirrel<ScriptContext::UI>->raiseerror(
+ sqvm, fmt::format("Tried to connect to authed server before any pending connection info was available").c_str());
+ return SQRESULT_ERROR;
+ }
+
+ RemoteServerConnectionInfo info = g_pMasterServerManager->m_pendingConnectionInfo;
+
+ // set auth token, then try to connect
+ // i'm honestly not entirely sure how silentconnect works regarding ports and encryption so using connect for now
+ R2::Cbuf_AddText(
+ R2::Cbuf_GetCurrentPlayer(), fmt::format("serverfilter {}", info.authToken).c_str(), R2::cmd_source_t::kCommandSrcCode);
+ R2::Cbuf_AddText(
+ R2::Cbuf_GetCurrentPlayer(),
+ fmt::format(
+ "connect {}.{}.{}.{}:{}",
+ info.ip.S_un.S_un_b.s_b1,
+ info.ip.S_un.S_un_b.s_b2,
+ info.ip.S_un.S_un_b.s_b3,
+ info.ip.S_un.S_un_b.s_b4,
+ info.port)
+ .c_str(),
+ R2::cmd_source_t::kCommandSrcCode);
+
+ g_pMasterServerManager->m_bHasPendingConnectionInfo = false;
+ return SQRESULT_NULL;
+}
+
+// void function NSTryAuthWithLocalServer()
+SQRESULT SQ_TryAuthWithLocalServer(HSquirrelVM* sqvm)
+{
+ // do auth request
+ g_pMasterServerManager->AuthenticateWithOwnServer(R2::g_pLocalPlayerUserID, g_pMasterServerManager->m_sOwnClientAuthToken);
+
+ return SQRESULT_NULL;
+}
+
+// void function NSCompleteAuthWithLocalServer()
+SQRESULT SQ_CompleteAuthWithLocalServer(HSquirrelVM* sqvm)
+{
+ // literally just set serverfilter
+ // note: this assumes we have no authdata other than our own
+ R2::Cbuf_AddText(
+ R2::Cbuf_GetCurrentPlayer(),
+ fmt::format("serverfilter {}", g_pServerAuthentication->m_RemoteAuthenticationData.begin()->first).c_str(),
+ R2::cmd_source_t::kCommandSrcCode);
+
+ return SQRESULT_NULL;
+}
+
+// string function NSGetAuthFailReason()
+SQRESULT SQ_GetAuthFailReason(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<ScriptContext::UI>->pushstring(sqvm, g_pMasterServerManager->m_sAuthFailureReason.c_str(), -1);
+ return SQRESULT_NOTNULL;
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptServerBrowser, ClientSquirrel, (CModule module))
+{
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("bool", "NSIsMasterServerAuthenticated", "", "", SQ_IsMasterServerAuthenticated);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSRequestServerList", "", "", SQ_RequestServerList);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("bool", "NSIsRequestingServerList", "", "", SQ_IsRequestingServerList);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "bool", "NSMasterServerConnectionSuccessful", "", "", SQ_MasterServerConnectionSuccessful);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("int", "NSGetServerCount", "", "", SQ_GetServerCount);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSClearRecievedServerList", "", "", SQ_ClearRecievedServerList);
+
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("string", "NSGetServerName", "int serverIndex", "", SQ_GetServerName);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("string", "NSGetServerDescription", "int serverIndex", "", SQ_GetServerDescription);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("string", "NSGetServerMap", "int serverIndex", "", SQ_GetServerMap);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("string", "NSGetServerPlaylist", "int serverIndex", "", SQ_GetServerPlaylist);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("int", "NSGetServerPlayerCount", "int serverIndex", "", SQ_GetServerPlayerCount);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "int", "NSGetServerMaxPlayerCount", "int serverIndex", "", SQ_GetServerMaxPlayerCount);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("string", "NSGetServerID", "int serverIndex", "", SQ_GetServerID);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "bool", "NSServerRequiresPassword", "int serverIndex", "", SQ_ServerRequiresPassword);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "int", "NSGetServerRequiredModsCount", "int serverIndex", "", SQ_GetServerRequiredModsCount);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "string", "NSGetServerRequiredModName", "int serverIndex, int modIndex", "", SQ_GetServerRequiredModName);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "string", "NSGetServerRequiredModVersion", "int serverIndex, int modIndex", "", SQ_GetServerRequiredModVersion);
+
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "void", "NSTryAuthWithServer", "int serverIndex, string password = \"\"", "", SQ_TryAuthWithServer);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("bool", "NSIsAuthenticatingWithServer", "", "", SQ_IsAuthComplete);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("bool", "NSWasAuthSuccessful", "", "", SQ_WasAuthSuccessful);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSConnectToAuthedServer", "", "", SQ_ConnectToAuthedServer);
+
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSTryAuthWithLocalServer", "", "", SQ_TryAuthWithLocalServer);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("void", "NSCompleteAuthWithLocalServer", "", "", SQ_CompleteAuthWithLocalServer);
+
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration("string", "NSGetAuthFailReason", "", "", SQ_GetAuthFailReason);
+}
diff --git a/NorthstarDLL/scriptservertoclientstringcommand.cpp b/NorthstarDLL/scriptservertoclientstringcommand.cpp
new file mode 100644
index 00000000..5c116973
--- /dev/null
+++ b/NorthstarDLL/scriptservertoclientstringcommand.cpp
@@ -0,0 +1,25 @@
+#include "pch.h"
+#include "squirrel.h"
+#include "convar.h"
+#include "concommand.h"
+
+void ConCommand_ns_script_servertoclientstringcommand(const CCommand& arg)
+{
+ if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM &&
+ g_pSquirrel<ScriptContext::CLIENT>->setupfunc("NSClientCodeCallback_RecievedServerToClientStringCommand") != SQRESULT_ERROR)
+ {
+ g_pSquirrel<ScriptContext::CLIENT>->pushstring(g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm, arg.ArgS());
+ g_pSquirrel<ScriptContext::CLIENT>->call(
+ g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM->sqvm,
+ 1); // todo: doesn't throw or log errors from within this, probably not great behaviour
+ }
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ScriptServerToClientStringCommand, ClientSquirrel, (CModule module))
+{
+ RegisterConCommand(
+ "ns_script_servertoclientstringcommand",
+ ConCommand_ns_script_servertoclientstringcommand,
+ "",
+ FCVAR_CLIENTDLL | FCVAR_SERVER_CAN_EXECUTE);
+}
diff --git a/NorthstarDedicatedTest/scriptsrson.cpp b/NorthstarDLL/scriptsrson.cpp
index 91a12737..1e0ded27 100644
--- a/NorthstarDedicatedTest/scriptsrson.cpp
+++ b/NorthstarDLL/scriptsrson.cpp
@@ -12,15 +12,12 @@ void ModManager::BuildScriptsRson()
fs::path MOD_SCRIPTS_RSON_PATH = fs::path(GetCompiledAssetsPath() / MOD_SCRIPTS_RSON_SUFFIX);
fs::remove(MOD_SCRIPTS_RSON_PATH);
- // not really important since it doesn't affect actual functionality at all, but the rson we output is really weird
- // has a shitload of newlines added, even in places where we don't modify it at all
-
- std::string scriptsRson = ReadVPKOriginalFile(VPK_SCRIPTS_RSON_PATH);
+ std::string scriptsRson = R2::ReadVPKOriginalFile(VPK_SCRIPTS_RSON_PATH);
scriptsRson += "\n\n// START MODDED SCRIPT CONTENT\n\n"; // newline before we start custom stuff
- for (Mod& mod : m_loadedMods)
+ for (Mod& mod : m_LoadedMods)
{
- if (!mod.Enabled)
+ if (!mod.m_bEnabled)
continue;
// this isn't needed at all, just nice to have imo
@@ -38,7 +35,7 @@ void ModManager::BuildScriptsRson()
]*/
scriptsRson += "When: \"";
- scriptsRson += script.RsonRunOn;
+ scriptsRson += script.RunOn;
scriptsRson += "\"\n";
scriptsRson += "Scripts:\n[\n\t";
@@ -54,14 +51,14 @@ void ModManager::BuildScriptsRson()
writeStream.close();
ModOverrideFile overrideFile;
- overrideFile.owningMod = nullptr;
- overrideFile.path = VPK_SCRIPTS_RSON_PATH;
+ overrideFile.m_pOwningMod = nullptr;
+ overrideFile.m_Path = VPK_SCRIPTS_RSON_PATH;
- if (m_modFiles.find(VPK_SCRIPTS_RSON_PATH) == m_modFiles.end())
- m_modFiles.insert(std::make_pair(VPK_SCRIPTS_RSON_PATH, overrideFile));
+ if (m_ModFiles.find(VPK_SCRIPTS_RSON_PATH) == m_ModFiles.end())
+ m_ModFiles.insert(std::make_pair(VPK_SCRIPTS_RSON_PATH, overrideFile));
else
- m_modFiles[VPK_SCRIPTS_RSON_PATH] = overrideFile;
+ m_ModFiles[VPK_SCRIPTS_RSON_PATH] = overrideFile;
// todo: for preventing dupe scripts in scripts.rson, we could actually parse when conditions with the squirrel vm, just need a way to
// get a result out of squirrelmanager.ExecuteCode this would probably be the best way to do this, imo
-} \ No newline at end of file
+}
diff --git a/NorthstarDedicatedTest/scriptsrson.h b/NorthstarDLL/scriptsrson.h
index 140db341..5e1d5684 100644
--- a/NorthstarDedicatedTest/scriptsrson.h
+++ b/NorthstarDLL/scriptsrson.h
@@ -1,4 +1,4 @@
#pragma once
const std::string MOD_SCRIPTS_RSON_SUFFIX = "scripts/vscripts/scripts.rson";
-const char* VPK_SCRIPTS_RSON_PATH = "scripts\\vscripts\\scripts.rson"; \ No newline at end of file
+const char* VPK_SCRIPTS_RSON_PATH = "scripts\\vscripts\\scripts.rson";
diff --git a/NorthstarDLL/scriptutility.cpp b/NorthstarDLL/scriptutility.cpp
new file mode 100644
index 00000000..7a1936cf
--- /dev/null
+++ b/NorthstarDLL/scriptutility.cpp
@@ -0,0 +1,23 @@
+#include "pch.h"
+#include "squirrel.h"
+
+// asset function StringToAsset( string assetName )
+template <ScriptContext context> SQRESULT SQ_StringToAsset(HSquirrelVM* sqvm)
+{
+ g_pSquirrel<context>->pushasset(sqvm, g_pSquirrel<context>->getstring(sqvm, 1), -1);
+ return SQRESULT_NOTNULL;
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientSharedScriptUtility, ClientSquirrel, (CModule module))
+{
+ g_pSquirrel<ScriptContext::CLIENT>->AddFuncRegistration(
+ "asset", "StringToAsset", "string assetName", "converts a given string to an asset", SQ_StringToAsset<ScriptContext::CLIENT>);
+ g_pSquirrel<ScriptContext::UI>->AddFuncRegistration(
+ "asset", "StringToAsset", "string assetName", "converts a given string to an asset", SQ_StringToAsset<ScriptContext::UI>);
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerSharedScriptUtility, ServerSquirrel, (CModule module))
+{
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration(
+ "asset", "StringToAsset", "string assetName", "converts a given string to an asset", SQ_StringToAsset<ScriptContext::SERVER>);
+} \ No newline at end of file
diff --git a/NorthstarDLL/serverauthentication.cpp b/NorthstarDLL/serverauthentication.cpp
new file mode 100644
index 00000000..98054dd7
--- /dev/null
+++ b/NorthstarDLL/serverauthentication.cpp
@@ -0,0 +1,401 @@
+#include "pch.h"
+#include "serverauthentication.h"
+#include "limits.h"
+#include "cvar.h"
+#include "convar.h"
+#include "masterserver.h"
+#include "serverpresence.h"
+#include "hoststate.h"
+#include "maxplayers.h"
+#include "bansystem.h"
+#include "concommand.h"
+#include "dedicated.h"
+#include "nsprefix.h"
+#include "tier0.h"
+#include "r2engine.h"
+#include "r2client.h"
+#include "r2server.h"
+
+#include "httplib.h"
+
+#include <fstream>
+#include <filesystem>
+#include <thread>
+
+AUTOHOOK_INIT()
+
+const char* AUTHSERVER_VERIFY_STRING = "I am a northstar server!";
+
+// global vars
+ServerAuthenticationManager* g_pServerAuthentication;
+
+void ServerAuthenticationManager::StartPlayerAuthServer()
+{
+ if (m_bRunningPlayerAuthThread)
+ {
+ spdlog::warn("ServerAuthenticationManager::StartPlayerAuthServer was called while m_bRunningPlayerAuthThread is true");
+ return;
+ }
+
+ g_pServerPresence->SetAuthPort(Cvar_ns_player_auth_port->GetInt()); // set auth port for presence
+ m_bRunningPlayerAuthThread = true;
+
+ // listen is a blocking call so thread this
+ std::thread serverThread(
+ [this]
+ {
+ // this is just a super basic way to verify that servers have ports open, masterserver will try to read this before ensuring
+ // server is legit
+ m_PlayerAuthServer.Get(
+ "/verify",
+ [](const httplib::Request& request, httplib::Response& response)
+ { response.set_content(AUTHSERVER_VERIFY_STRING, "text/plain"); });
+
+ m_PlayerAuthServer.Post(
+ "/authenticate_incoming_player",
+ [this](const httplib::Request& request, httplib::Response& response)
+ {
+ if (!request.has_param("id") || !request.has_param("authToken") || request.body.size() >= R2::PERSISTENCE_MAX_SIZE ||
+ !request.has_param("serverAuthToken") ||
+ strcmp(g_pMasterServerManager->m_sOwnServerAuthToken, request.get_param_value("serverAuthToken").c_str()))
+ {
+ response.set_content("{\"success\":false}", "application/json");
+ return;
+ }
+
+ RemoteAuthData newAuthData {};
+ strncpy_s(newAuthData.uid, sizeof(newAuthData.uid), request.get_param_value("id").c_str(), sizeof(newAuthData.uid) - 1);
+ strncpy_s(
+ newAuthData.username,
+ sizeof(newAuthData.username),
+ request.get_param_value("username").c_str(),
+ sizeof(newAuthData.username) - 1);
+
+ newAuthData.pdataSize = request.body.size();
+ newAuthData.pdata = new char[newAuthData.pdataSize];
+ memcpy(newAuthData.pdata, request.body.c_str(), newAuthData.pdataSize);
+
+ std::lock_guard<std::mutex> guard(m_AuthDataMutex);
+ m_RemoteAuthenticationData.insert(std::make_pair(request.get_param_value("authToken"), newAuthData));
+
+ response.set_content("{\"success\":true}", "application/json");
+ });
+
+ m_PlayerAuthServer.listen("0.0.0.0", Cvar_ns_player_auth_port->GetInt());
+ });
+
+ serverThread.detach();
+}
+
+void ServerAuthenticationManager::StopPlayerAuthServer()
+{
+ if (!m_bRunningPlayerAuthThread)
+ {
+ spdlog::warn("ServerAuthenticationManager::StopPlayerAuthServer was called while m_bRunningPlayerAuthThread is false");
+ return;
+ }
+
+ m_bRunningPlayerAuthThread = false;
+ m_PlayerAuthServer.stop();
+}
+
+void ServerAuthenticationManager::AddPlayer(R2::CBaseClient* player, const char* pToken)
+{
+ PlayerAuthenticationData additionalData;
+ additionalData.pdataSize = m_RemoteAuthenticationData[pToken].pdataSize;
+ additionalData.usingLocalPdata = player->m_iPersistenceReady == R2::ePersistenceReady::READY_INSECURE;
+
+ m_PlayerAuthenticationData.insert(std::make_pair(player, additionalData));
+}
+
+void ServerAuthenticationManager::RemovePlayer(R2::CBaseClient* player)
+{
+ if (m_PlayerAuthenticationData.count(player))
+ m_PlayerAuthenticationData.erase(player);
+}
+
+void ServerAuthenticationManager::VerifyPlayerName(R2::CBaseClient* player, char* authToken, char* name)
+{
+ std::lock_guard<std::mutex> guard(m_AuthDataMutex);
+
+ if (!m_RemoteAuthenticationData.empty() && m_RemoteAuthenticationData.count(std::string(authToken)))
+ {
+ RemoteAuthData authData = m_RemoteAuthenticationData[authToken];
+
+ bool nameAccepted = (!*authData.username || !strcmp(name, authData.username));
+
+ if (!nameAccepted && g_pMasterServerManager->m_bRequireClientAuth && !CVar_ns_auth_allow_insecure->GetInt())
+ {
+ // limit name length to 64 characters just in case something changes, this technically shouldn't be needed given the master
+ // server gets usernames from origin but we have it just in case
+ strncpy_s(name, 64, authData.username, 63);
+ }
+ }
+}
+
+bool ServerAuthenticationManager::CheckDuplicateAccounts(R2::CBaseClient* player)
+{
+ if (m_bAllowDuplicateAccounts)
+ return true;
+
+ bool bHasUidPlayer = false;
+ for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ if (&R2::g_pClientArray[i] != player && !strcmp(R2::g_pClientArray[i].m_UID, player->m_UID))
+ return false;
+
+ return true;
+}
+
+bool ServerAuthenticationManager::AuthenticatePlayer(R2::CBaseClient* player, uint64_t uid, char* authToken)
+{
+ std::string strUid = std::to_string(uid);
+ std::lock_guard<std::mutex> guard(m_AuthDataMutex);
+
+ // copy uuid
+ strcpy(player->m_UID, strUid.c_str());
+
+ bool authFail = true;
+ if (!m_RemoteAuthenticationData.empty() && m_RemoteAuthenticationData.count(std::string(authToken)))
+ {
+ if (!CheckDuplicateAccounts(player))
+ return false;
+
+ // use stored auth data
+ RemoteAuthData authData = m_RemoteAuthenticationData[authToken];
+
+ if (!strcmp(strUid.c_str(), authData.uid)) // connecting client's uid is the same as auth's uid
+ {
+ // if we're resetting let script handle the reset
+ if (!m_bForceResetLocalPlayerPersistence || strcmp(authData.uid, R2::g_pLocalPlayerUserID))
+ {
+ // copy pdata into buffer
+ memcpy(player->m_PersistenceBuffer, authData.pdata, authData.pdataSize);
+ }
+
+ // set persistent data as ready
+ player->m_iPersistenceReady = R2::ePersistenceReady::READY_REMOTE;
+ authFail = false;
+ }
+ }
+
+ if (authFail)
+ {
+ if (CVar_ns_auth_allow_insecure->GetBool())
+ {
+ // set persistent data as ready
+ // note: actual placeholder persistent data is populated in script with InitPersistentData()
+ player->m_iPersistenceReady = R2::ePersistenceReady::READY_INSECURE;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ return true; // auth successful, client stays on
+}
+
+bool ServerAuthenticationManager::RemovePlayerAuthData(R2::CBaseClient* player)
+{
+ if (!Cvar_ns_erase_auth_info->GetBool()) // keep auth data forever
+ return false;
+
+ // hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect
+ if (m_bNeedLocalAuthForNewgame && !strcmp(player->m_UID, R2::g_pLocalPlayerUserID))
+ return false;
+
+ // we don't have our auth token at this point, so lookup authdata by uid
+ for (auto& auth : m_RemoteAuthenticationData)
+ {
+ if (!strcmp(player->m_UID, auth.second.uid))
+ {
+ // pretty sure this is fine, since we don't iterate after the erase
+ // i think if we iterated after it'd be undefined behaviour tho
+ std::lock_guard<std::mutex> guard(m_AuthDataMutex);
+
+ delete[] auth.second.pdata;
+ m_RemoteAuthenticationData.erase(auth.first);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ServerAuthenticationManager::WritePersistentData(R2::CBaseClient* player)
+{
+ if (player->m_iPersistenceReady == R2::ePersistenceReady::READY_REMOTE)
+ {
+ g_pMasterServerManager->WritePlayerPersistentData(
+ player->m_UID, (const char*)player->m_PersistenceBuffer, m_PlayerAuthenticationData[player].pdataSize);
+ }
+ else if (CVar_ns_auth_allow_insecure_write->GetBool())
+ {
+ // todo: write pdata to disk here
+ }
+}
+
+// auth hooks
+
+// store these in vars so we can use them in CBaseClient::Connect
+// this is fine because ptrs won't decay by the time we use this, just don't use it outside of calls from cbaseclient::connectclient
+char* pNextPlayerToken;
+uint64_t iNextPlayerUid;
+
+// clang-format off
+AUTOHOOK(CBaseServer__ConnectClient, engine.dll + 0x114430,
+void*,, (
+ void* server,
+ void* a2,
+ void* a3,
+ uint32_t a4,
+ uint32_t a5,
+ int32_t a6,
+ void* a7,
+ void* a8,
+ char* serverFilter,
+ void* a10,
+ char a11,
+ void* a12,
+ char a13,
+ char a14,
+ int64_t uid,
+ uint32_t a16,
+ uint32_t a17))
+// clang-format on
+{
+ // auth tokens are sent with serverfilter, can't be accessed from player struct to my knowledge, so have to do this here
+ pNextPlayerToken = serverFilter;
+ iNextPlayerUid = uid;
+
+ return CBaseServer__ConnectClient(server, a2, a3, a4, a5, a6, a7, a8, serverFilter, a10, a11, a12, a13, a14, uid, a16, a17);
+}
+
+// clang-format off
+AUTOHOOK(CBaseClient__Connect, engine.dll + 0x101740,
+bool,, (R2::CBaseClient* self, char* name, void* netchan_ptr_arg, char b_fake_player_arg, void* a5, char* Buffer, void* a7))
+// clang-format on
+{
+ // try changing name before all else
+ g_pServerAuthentication->VerifyPlayerName(self, pNextPlayerToken, name);
+
+ // try to auth player, dc if it fails
+ // we connect regardless of auth, because returning bad from this function can fuck client state p bad
+ bool ret = CBaseClient__Connect(self, name, netchan_ptr_arg, b_fake_player_arg, a5, Buffer, a7);
+ if (!ret)
+ return ret;
+
+ if (!g_pBanSystem->IsUIDAllowed(iNextPlayerUid))
+ {
+ R2::CBaseClient__Disconnect(self, 1, "Banned from server");
+ return ret;
+ }
+
+ if (strlen(name) >= 64) // fix for name overflow bug
+ R2::CBaseClient__Disconnect(self, 1, "Invalid name");
+ else if (
+ !g_pServerAuthentication->AuthenticatePlayer(self, iNextPlayerUid, pNextPlayerToken) &&
+ g_pServerAuthentication->m_bRequireClientAuth)
+ R2::CBaseClient__Disconnect(self, 1, "Authentication Failed");
+
+ g_pServerAuthentication->AddPlayer(self, pNextPlayerToken);
+ g_pServerLimits->AddPlayer(self);
+
+ return ret;
+}
+
+// clang-format off
+AUTOHOOK(CBaseClient__ActivatePlayer, engine.dll + 0x100F80,
+void,, (R2::CBaseClient* self))
+// clang-format on
+{
+ // if we're authed, write our persistent data
+ // RemovePlayerAuthData returns true if it removed successfully, i.e. on first call only, and we only want to write on >= second call
+ // (since this func is called on map loads)
+ if (self->m_iPersistenceReady >= R2::ePersistenceReady::READY && !g_pServerAuthentication->RemovePlayerAuthData(self))
+ {
+ g_pServerAuthentication->m_bForceResetLocalPlayerPersistence = false;
+ g_pServerAuthentication->WritePersistentData(self);
+ g_pServerPresence->SetPlayerCount(g_pServerAuthentication->m_PlayerAuthenticationData.size());
+ }
+
+ CBaseClient__ActivatePlayer(self);
+}
+
+// clang-format off
+AUTOHOOK(_CBaseClient__Disconnect, engine.dll + 0x1012C0,
+void,, (R2::CBaseClient* self, uint32_t unknownButAlways1, const char* pReason, ...))
+// clang-format on
+{
+ // have to manually format message because can't pass varargs to original func
+ char buf[1024];
+
+ va_list va;
+ va_start(va, pReason);
+ vsprintf(buf, pReason, va);
+ va_end(va);
+
+ // this reason is used while connecting to a local server, hacky, but just ignore it
+ if (strcmp(pReason, "Connection closing"))
+ {
+ spdlog::info("Player {} disconnected: \"{}\"", self->m_Name, buf);
+
+ // dcing, write persistent data
+ if (g_pServerAuthentication->m_PlayerAuthenticationData[self].needPersistenceWriteOnLeave)
+ g_pServerAuthentication->WritePersistentData(self);
+ g_pServerAuthentication->RemovePlayerAuthData(self); // won't do anything 99% of the time, but just in case
+ }
+
+ g_pServerAuthentication->RemovePlayer(self);
+ g_pServerLimits->RemovePlayer(self);
+
+ g_pServerPresence->SetPlayerCount(g_pServerAuthentication->m_PlayerAuthenticationData.size());
+
+ _CBaseClient__Disconnect(self, unknownButAlways1, buf);
+}
+
+void ConCommand_ns_resetpersistence(const CCommand& args)
+{
+ if (*R2::g_pServerState == R2::server_state_t::ss_active)
+ {
+ spdlog::error("ns_resetpersistence must be entered from the main menu");
+ return;
+ }
+
+ spdlog::info("resetting persistence on next lobby load...");
+ g_pServerAuthentication->m_bForceResetLocalPlayerPersistence = true;
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", ServerAuthentication, (ConCommand, ConVar), (CModule module))
+{
+ AUTOHOOK_DISPATCH()
+
+ g_pServerAuthentication = new ServerAuthenticationManager;
+
+ g_pServerAuthentication->Cvar_ns_player_auth_port = new ConVar("ns_player_auth_port", "8081", FCVAR_GAMEDLL, "");
+ g_pServerAuthentication->Cvar_ns_erase_auth_info =
+ new ConVar("ns_erase_auth_info", "1", FCVAR_GAMEDLL, "Whether auth info should be erased from this server on disconnect or crash");
+ g_pServerAuthentication->CVar_ns_auth_allow_insecure =
+ new ConVar("ns_auth_allow_insecure", "0", FCVAR_GAMEDLL, "Whether this server will allow unauthenicated players to connect");
+ g_pServerAuthentication->CVar_ns_auth_allow_insecure_write = new ConVar(
+ "ns_auth_allow_insecure_write",
+ "0",
+ FCVAR_GAMEDLL,
+ "Whether the pdata of unauthenticated clients will be written to disk when changed");
+
+ RegisterConCommand(
+ "ns_resetpersistence", ConCommand_ns_resetpersistence, "resets your pdata when you next enter the lobby", FCVAR_NONE);
+
+ // patch to disable kicking based on incorrect serverfilter in connectclient, since we repurpose it for use as an auth token
+ module.Offset(0x114655).Patch("EB");
+
+ // patch to disable fairfight marking players as cheaters and kicking them
+ module.Offset(0x101012).Patch("E9 90 00");
+
+ if (Tier0::CommandLine()->CheckParm("-allowdupeaccounts"))
+ {
+ // patch to allow same of multiple account
+ module.Offset(0x114510).Patch("EB");
+
+ g_pServerAuthentication->m_bAllowDuplicateAccounts = true;
+ }
+}
diff --git a/NorthstarDLL/serverauthentication.h b/NorthstarDLL/serverauthentication.h
new file mode 100644
index 00000000..08854ac0
--- /dev/null
+++ b/NorthstarDLL/serverauthentication.h
@@ -0,0 +1,57 @@
+#pragma once
+#include "convar.h"
+#include "httplib.h"
+#include "r2engine.h"
+#include <unordered_map>
+#include <string>
+
+struct RemoteAuthData
+{
+ char uid[33];
+ char username[64];
+
+ // pdata
+ char* pdata;
+ size_t pdataSize;
+};
+
+struct PlayerAuthenticationData
+{
+ bool usingLocalPdata;
+ size_t pdataSize;
+ bool needPersistenceWriteOnLeave = true;
+};
+
+class ServerAuthenticationManager
+{
+ private:
+ httplib::Server m_PlayerAuthServer;
+
+ public:
+ ConVar* Cvar_ns_player_auth_port;
+ ConVar* Cvar_ns_erase_auth_info;
+ ConVar* CVar_ns_auth_allow_insecure;
+ ConVar* CVar_ns_auth_allow_insecure_write;
+
+ std::mutex m_AuthDataMutex;
+ std::unordered_map<std::string, RemoteAuthData> m_RemoteAuthenticationData;
+ std::unordered_map<R2::CBaseClient*, PlayerAuthenticationData> m_PlayerAuthenticationData;
+ bool m_bRequireClientAuth = true;
+ bool m_bAllowDuplicateAccounts = false;
+ bool m_bRunningPlayerAuthThread = false;
+ bool m_bNeedLocalAuthForNewgame = false;
+ bool m_bForceResetLocalPlayerPersistence = false;
+
+ public:
+ void StartPlayerAuthServer();
+ void StopPlayerAuthServer();
+ void AddPlayer(R2::CBaseClient* player, const char* pToken);
+ void RemovePlayer(R2::CBaseClient* player);
+ bool CheckDuplicateAccounts(R2::CBaseClient* player);
+ bool AuthenticatePlayer(R2::CBaseClient* player, uint64_t uid, char* authToken);
+ void VerifyPlayerName(R2::CBaseClient* player, char* authToken, char* name);
+ bool RemovePlayerAuthData(R2::CBaseClient* player);
+ void WritePersistentData(R2::CBaseClient* player);
+};
+
+extern ServerAuthenticationManager* g_pServerAuthentication;
diff --git a/NorthstarDLL/serverchathooks.cpp b/NorthstarDLL/serverchathooks.cpp
new file mode 100644
index 00000000..1dd05830
--- /dev/null
+++ b/NorthstarDLL/serverchathooks.cpp
@@ -0,0 +1,183 @@
+#include "pch.h"
+#include "serverchathooks.h"
+#include "limits.h"
+#include "squirrel.h"
+#include "r2server.h"
+
+#include <rapidjson/document.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+
+AUTOHOOK_INIT()
+
+class CServerGameDLL;
+
+class CRecipientFilter
+{
+ char unknown[58];
+};
+
+CServerGameDLL* g_pServerGameDLL;
+
+void(__fastcall* CServerGameDLL__OnReceivedSayTextMessage)(
+ CServerGameDLL* self, unsigned int senderPlayerId, const char* text, int channelId);
+
+void(__fastcall* CRecipientFilter__Construct)(CRecipientFilter* self);
+void(__fastcall* CRecipientFilter__Destruct)(CRecipientFilter* self);
+void(__fastcall* CRecipientFilter__AddAllPlayers)(CRecipientFilter* self);
+void(__fastcall* CRecipientFilter__AddRecipient)(CRecipientFilter* self, const R2::CBasePlayer* player);
+void(__fastcall* CRecipientFilter__MakeReliable)(CRecipientFilter* self);
+
+void(__fastcall* UserMessageBegin)(CRecipientFilter* filter, const char* messagename);
+void(__fastcall* MessageEnd)();
+void(__fastcall* MessageWriteByte)(int iValue);
+void(__fastcall* MessageWriteString)(const char* sz);
+void(__fastcall* MessageWriteBool)(bool bValue);
+
+bool bShouldCallSayTextHook = false;
+// clang-format off
+AUTOHOOK(_CServerGameDLL__OnReceivedSayTextMessage, server.dll + 0x1595C0,
+void, __fastcall, (CServerGameDLL* self, unsigned int senderPlayerId, const char* text, bool isTeam))
+// clang-format on
+{
+ // MiniHook doesn't allow calling the base function outside of anywhere but the hook function.
+ // To allow bypassing the hook, isSkippingHook can be set.
+ if (bShouldCallSayTextHook)
+ {
+ bShouldCallSayTextHook = false;
+ _CServerGameDLL__OnReceivedSayTextMessage(self, senderPlayerId, text, isTeam);
+ return;
+ }
+
+ // check chat ratelimits
+ if (!g_pServerLimits->CheckChatLimits(&R2::g_pClientArray[senderPlayerId - 1]))
+ return;
+
+ if (g_pSquirrel<ScriptContext::SERVER>->setupfunc("CServerGameDLL_ProcessMessageStartThread") != SQRESULT_ERROR)
+ {
+ g_pSquirrel<ScriptContext::SERVER>->pushinteger(g_pSquirrel<ScriptContext::SERVER>->m_pSQVM->sqvm, (int)senderPlayerId - 1);
+ g_pSquirrel<ScriptContext::SERVER>->pushstring(g_pSquirrel<ScriptContext::SERVER>->m_pSQVM->sqvm, text);
+ g_pSquirrel<ScriptContext::SERVER>->pushbool(g_pSquirrel<ScriptContext::SERVER>->m_pSQVM->sqvm, isTeam);
+ g_pSquirrel<ScriptContext::SERVER>->call(g_pSquirrel<ScriptContext::SERVER>->m_pSQVM->sqvm, 3);
+ }
+ else
+ _CServerGameDLL__OnReceivedSayTextMessage(self, senderPlayerId, text, isTeam);
+}
+
+void ChatSendMessage(unsigned int playerIndex, const char* text, bool isTeam)
+{
+ bShouldCallSayTextHook = true;
+ CServerGameDLL__OnReceivedSayTextMessage(
+ g_pServerGameDLL,
+ // Ensure the first bit isn't set, since this indicates a custom message
+ (playerIndex + 1) & CUSTOM_MESSAGE_INDEX_MASK,
+ text,
+ isTeam);
+}
+
+void ChatBroadcastMessage(int fromPlayerIndex, int toPlayerIndex, const char* text, bool isTeam, bool isDead, CustomMessageType messageType)
+{
+ R2::CBasePlayer* toPlayer = NULL;
+ if (toPlayerIndex >= 0)
+ {
+ toPlayer = R2::UTIL_PlayerByIndex(toPlayerIndex + 1);
+ if (toPlayer == NULL)
+ return;
+ }
+
+ // Build a new string where the first byte is the message type
+ char sendText[256];
+ sendText[0] = (char)messageType;
+ strncpy_s(sendText + 1, 255, text, 254);
+
+ // Anonymous custom messages use playerId=0, non-anonymous ones use a player ID with the first bit set
+ unsigned int fromPlayerId = fromPlayerIndex < 0 ? 0 : ((fromPlayerIndex + 1) | CUSTOM_MESSAGE_INDEX_BIT);
+
+ CRecipientFilter filter;
+ CRecipientFilter__Construct(&filter);
+ if (toPlayer == NULL)
+ {
+ CRecipientFilter__AddAllPlayers(&filter);
+ }
+ else
+ {
+ CRecipientFilter__AddRecipient(&filter, toPlayer);
+ }
+ CRecipientFilter__MakeReliable(&filter);
+
+ UserMessageBegin(&filter, "SayText");
+ MessageWriteByte(fromPlayerId);
+ MessageWriteString(sendText);
+ MessageWriteBool(isTeam);
+ MessageWriteBool(isDead);
+ MessageEnd();
+
+ CRecipientFilter__Destruct(&filter);
+}
+
+// void function NSSendMessage( int playerIndex, string text, bool isTeam )
+SQRESULT SQ_SendMessage(HSquirrelVM* sqvm)
+{
+ int playerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 1);
+ const char* text = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 2);
+ bool isTeam = g_pSquirrel<ScriptContext::SERVER>->getbool(sqvm, 3);
+
+ ChatSendMessage(playerIndex, text, isTeam);
+
+ return SQRESULT_NULL;
+}
+
+// void function NSBroadcastMessage( int fromPlayerIndex, int toPlayerIndex, string text, bool isTeam, bool isDead, int messageType )
+SQRESULT SQ_BroadcastMessage(HSquirrelVM* sqvm)
+{
+ int fromPlayerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 1);
+ int toPlayerIndex = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 2);
+ const char* text = g_pSquirrel<ScriptContext::SERVER>->getstring(sqvm, 3);
+ bool isTeam = g_pSquirrel<ScriptContext::SERVER>->getbool(sqvm, 4);
+ bool isDead = g_pSquirrel<ScriptContext::SERVER>->getbool(sqvm, 5);
+ int messageType = g_pSquirrel<ScriptContext::SERVER>->getinteger(sqvm, 6);
+
+ if (messageType < 1)
+ {
+ g_pSquirrel<ScriptContext::SERVER>->raiseerror(sqvm, fmt::format("Invalid message type {}", messageType).c_str());
+ return SQRESULT_ERROR;
+ }
+
+ ChatBroadcastMessage(fromPlayerIndex, toPlayerIndex, text, isTeam, isDead, (CustomMessageType)messageType);
+
+ return SQRESULT_NULL;
+}
+
+ON_DLL_LOAD("engine.dll", EngineServerChatHooks, (CModule module))
+{
+ g_pServerGameDLL = module.Offset(0x13F0AA98).As<CServerGameDLL*>();
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerChatHooks, ServerSquirrel, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(server.dll)
+
+ CServerGameDLL__OnReceivedSayTextMessage =
+ module.Offset(0x1595C0).As<void(__fastcall*)(CServerGameDLL*, unsigned int, const char*, int)>();
+ CRecipientFilter__Construct = module.Offset(0x1E9440).As<void(__fastcall*)(CRecipientFilter*)>();
+ CRecipientFilter__Destruct = module.Offset(0x1E9700).As<void(__fastcall*)(CRecipientFilter*)>();
+ CRecipientFilter__AddAllPlayers = module.Offset(0x1E9940).As<void(__fastcall*)(CRecipientFilter*)>();
+ CRecipientFilter__AddRecipient = module.Offset(0x1E9B30).As<void(__fastcall*)(CRecipientFilter*, const R2::CBasePlayer*)>();
+ CRecipientFilter__MakeReliable = module.Offset(0x1EA4E0).As<void(__fastcall*)(CRecipientFilter*)>();
+
+ UserMessageBegin = module.Offset(0x15C520).As<void(__fastcall*)(CRecipientFilter*, const char*)>();
+ MessageEnd = module.Offset(0x158880).As<void(__fastcall*)()>();
+ MessageWriteByte = module.Offset(0x158A90).As<void(__fastcall*)(int)>();
+ MessageWriteString = module.Offset(0x158D00).As<void(__fastcall*)(const char*)>();
+ MessageWriteBool = module.Offset(0x158A00).As<void(__fastcall*)(bool)>();
+
+ // Chat sending functions
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration(
+ "void", "NSSendMessage", "int playerIndex, string text, bool isTeam", "", SQ_SendMessage);
+ g_pSquirrel<ScriptContext::SERVER>->AddFuncRegistration(
+ "void",
+ "NSBroadcastMessage",
+ "int fromPlayerIndex, int toPlayerIndex, string text, bool isTeam, bool isDead, int messageType",
+ "",
+ SQ_BroadcastMessage);
+}
diff --git a/NorthstarDedicatedTest/serverchathooks.h b/NorthstarDLL/serverchathooks.h
index f3425ae6..1d8a806a 100644
--- a/NorthstarDedicatedTest/serverchathooks.h
+++ b/NorthstarDLL/serverchathooks.h
@@ -23,7 +23,3 @@ void ChatSendMessage(unsigned int playerIndex, const char* text, bool isteam);
// messageType: send a specific message type
void ChatBroadcastMessage(
int fromPlayerIndex, int toPlayerIndex, const char* text, bool isTeam, bool isDead, CustomMessageType messageType);
-
-void InitialiseServerChatHooks_Engine(HMODULE baseAddress);
-
-void InitialiseServerChatHooks_Server(HMODULE baseAddress);
diff --git a/NorthstarDLL/serverpresence.cpp b/NorthstarDLL/serverpresence.cpp
new file mode 100644
index 00000000..9b7b0f1a
--- /dev/null
+++ b/NorthstarDLL/serverpresence.cpp
@@ -0,0 +1,233 @@
+#include "pch.h"
+#include "serverpresence.h"
+#include "playlist.h"
+#include "tier0.h"
+#include "convar.h"
+
+#include <regex>
+
+ServerPresenceManager* g_pServerPresence;
+
+ConVar* Cvar_hostname;
+
+// Convert a hex digit char to integer.
+inline int hctod(char c)
+{
+ if (c >= 'A' && c <= 'F')
+ {
+ return c - 'A' + 10;
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ return c - 'a' + 10;
+ }
+ else
+ {
+ return c - '0';
+ }
+}
+
+// This function interprets all 4-hexadecimal-digit unicode codepoint characters like \u4E2D to UTF-8 encoding.
+std::string UnescapeUnicode(const std::string& str)
+{
+ std::string result;
+
+ std::regex r("\\\\u([a-f\\d]{4})", std::regex::icase);
+ auto matches_begin = std::sregex_iterator(str.begin(), str.end(), r);
+ auto matches_end = std::sregex_iterator();
+ std::smatch last_match;
+
+ for (std::sregex_iterator i = matches_begin; i != matches_end; ++i)
+ {
+ last_match = *i;
+ result.append(last_match.prefix());
+ unsigned int cp = 0;
+ for (int i = 2; i <= 5; ++i)
+ {
+ cp *= 16;
+ cp += hctod(last_match.str()[i]);
+ }
+ if (cp <= 0x7F)
+ {
+ result.push_back(cp);
+ }
+ else if (cp <= 0x7FF)
+ {
+ result.push_back((cp >> 6) | 0b11000000 & (~(1 << 5)));
+ result.push_back(cp & ((1 << 6) - 1) | 0b10000000 & (~(1 << 6)));
+ }
+ else if (cp <= 0xFFFF)
+ {
+ result.push_back((cp >> 12) | 0b11100000 & (~(1 << 4)));
+ result.push_back((cp >> 6) & ((1 << 6) - 1) | 0b10000000 & (~(1 << 6)));
+ result.push_back(cp & ((1 << 6) - 1) | 0b10000000 & (~(1 << 6)));
+ }
+ }
+
+ if (!last_match.ready())
+ return str;
+ else
+ result.append(last_match.suffix());
+
+ return result;
+}
+
+ServerPresenceManager::ServerPresenceManager()
+{
+ // clang-format off
+ // register convars
+ Cvar_ns_server_presence_update_rate = new ConVar(
+ "ns_server_presence_update_rate", "5000", FCVAR_GAMEDLL, "How often we update our server's presence on server lists in ms");
+
+ Cvar_ns_server_name = new ConVar("ns_server_name", "Unnamed Northstar Server", FCVAR_GAMEDLL, "This server's description", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
+ g_pServerPresence->SetName(UnescapeUnicode(g_pServerPresence->Cvar_ns_server_name->GetString()));
+
+ // update engine hostname cvar
+ Cvar_hostname->SetValue(g_pServerPresence->Cvar_ns_server_name->GetString());
+ });
+
+ Cvar_ns_server_desc = new ConVar("ns_server_desc", "Default server description", FCVAR_GAMEDLL, "This server's name", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
+ g_pServerPresence->SetDescription(UnescapeUnicode(g_pServerPresence->Cvar_ns_server_desc->GetString()));
+ });
+
+ Cvar_ns_server_password = new ConVar("ns_server_password", "", FCVAR_GAMEDLL, "This server's password", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
+ g_pServerPresence->SetPassword(g_pServerPresence->Cvar_ns_server_password->GetString());
+ });
+
+ Cvar_ns_report_server_to_masterserver = new ConVar("ns_report_server_to_masterserver", "1", FCVAR_GAMEDLL, "Whether we should report this server to the masterserver");
+ Cvar_ns_report_sp_server_to_masterserver = new ConVar("ns_report_sp_server_to_masterserver", "0", FCVAR_GAMEDLL, "Whether we should report this server to the masterserver, when started in singleplayer");
+ // clang-format on
+}
+
+void ServerPresenceManager::AddPresenceReporter(ServerPresenceReporter* reporter)
+{
+ m_vPresenceReporters.push_back(reporter);
+}
+
+void ServerPresenceManager::CreatePresence()
+{
+ // reset presence fields that rely on runtime server state
+ // these being: port/auth port, map/playlist name, and playercount/maxplayers
+ m_ServerPresence.m_iPort = 0;
+ m_ServerPresence.m_iAuthPort = 0;
+
+ m_ServerPresence.m_iPlayerCount = 0; // this should actually be 0 at this point, so shouldn't need updating later
+ m_ServerPresence.m_iMaxPlayers = 0;
+
+ memset(m_ServerPresence.m_MapName, 0, sizeof(m_ServerPresence.m_MapName));
+ memset(m_ServerPresence.m_PlaylistName, 0, sizeof(m_ServerPresence.m_PlaylistName));
+ m_ServerPresence.m_bIsSingleplayerServer = false;
+
+ m_bHasPresence = true;
+ m_bFirstPresenceUpdate = true;
+
+ // code that's calling this should set up the reset fields at this point
+}
+
+void ServerPresenceManager::DestroyPresence()
+{
+ m_bHasPresence = false;
+
+ for (ServerPresenceReporter* reporter : m_vPresenceReporters)
+ reporter->DestroyPresence(&m_ServerPresence);
+}
+
+void ServerPresenceManager::RunFrame(double flCurrentTime)
+{
+ if (!m_bHasPresence || !Cvar_ns_report_server_to_masterserver->GetBool()) // don't run until we actually have server presence
+ return;
+
+ // don't run if we're sp and don't want to report sp
+ if (m_ServerPresence.m_bIsSingleplayerServer && !Cvar_ns_report_sp_server_to_masterserver->GetBool())
+ return;
+
+ // run on a specified delay
+ if ((flCurrentTime - m_flLastPresenceUpdate) * 1000 < Cvar_ns_server_presence_update_rate->GetFloat())
+ return;
+
+ // is this the first frame we're updating this presence?
+ if (m_bFirstPresenceUpdate)
+ {
+ // let reporters setup/clear any state
+ for (ServerPresenceReporter* reporter : m_vPresenceReporters)
+ reporter->CreatePresence(&m_ServerPresence);
+
+ m_bFirstPresenceUpdate = false;
+ }
+
+ m_flLastPresenceUpdate = flCurrentTime;
+
+ for (ServerPresenceReporter* reporter : m_vPresenceReporters)
+ reporter->ReportPresence(&m_ServerPresence);
+}
+
+void ServerPresenceManager::SetPort(const int iPort)
+{
+ // update port
+ m_ServerPresence.m_iPort = iPort;
+}
+
+void ServerPresenceManager::SetAuthPort(const int iAuthPort)
+{
+ // update authport
+ m_ServerPresence.m_iAuthPort = iAuthPort;
+}
+
+void ServerPresenceManager::SetName(const std::string sServerNameUnicode)
+{
+ // update name
+ m_ServerPresence.m_sServerName = sServerNameUnicode;
+}
+
+void ServerPresenceManager::SetDescription(const std::string sServerDescUnicode)
+{
+ // update desc
+ m_ServerPresence.m_sServerDesc = sServerDescUnicode;
+}
+
+void ServerPresenceManager::SetPassword(const char* pPassword)
+{
+ // update password
+ strncpy_s(m_ServerPresence.m_Password, sizeof(m_ServerPresence.m_Password), pPassword, sizeof(m_ServerPresence.m_Password) - 1);
+}
+
+void ServerPresenceManager::SetMap(const char* pMapName, bool isInitialising)
+{
+ // if the server is initialising (i.e. this is first map) on sp, set the server to sp
+ if (isInitialising)
+ m_ServerPresence.m_bIsSingleplayerServer = !strncmp(pMapName, "sp_", 3);
+
+ // update map
+ strncpy_s(m_ServerPresence.m_MapName, sizeof(m_ServerPresence.m_MapName), pMapName, sizeof(m_ServerPresence.m_MapName) - 1);
+}
+
+void ServerPresenceManager::SetPlaylist(const char* pPlaylistName)
+{
+ // update playlist
+ strncpy_s(
+ m_ServerPresence.m_PlaylistName,
+ sizeof(m_ServerPresence.m_PlaylistName),
+ pPlaylistName,
+ sizeof(m_ServerPresence.m_PlaylistName) - 1);
+
+ // update maxplayers
+ const char* pMaxPlayers = R2::GetCurrentPlaylistVar("max_players", true);
+
+ // can be null in some situations, so default 6
+ if (pMaxPlayers)
+ m_ServerPresence.m_iMaxPlayers = std::stoi(pMaxPlayers);
+ else
+ m_ServerPresence.m_iMaxPlayers = 6;
+}
+
+void ServerPresenceManager::SetPlayerCount(const int iPlayerCount)
+{
+ m_ServerPresence.m_iPlayerCount = iPlayerCount;
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", ServerPresence, ConVar, (CModule module))
+{
+ g_pServerPresence = new ServerPresenceManager;
+
+ Cvar_hostname = module.Offset(0x1315BAE8).Deref().As<ConVar*>();
+}
diff --git a/NorthstarDLL/serverpresence.h b/NorthstarDLL/serverpresence.h
new file mode 100644
index 00000000..f27c9393
--- /dev/null
+++ b/NorthstarDLL/serverpresence.h
@@ -0,0 +1,91 @@
+#pragma once
+#include "convar.h"
+
+struct ServerPresence
+{
+ int m_iPort;
+ int m_iAuthPort;
+
+ std::string m_sServerName;
+ std::string m_sServerDesc;
+ char m_Password[256]; // probably bigger than will ever be used in practice, lol
+
+ char m_MapName[32];
+ char m_PlaylistName[64];
+ bool m_bIsSingleplayerServer; // whether the server started in sp
+
+ int m_iPlayerCount;
+ int m_iMaxPlayers;
+
+ ServerPresence()
+ {
+ memset(this, 0, sizeof(this));
+ }
+
+ ServerPresence(const ServerPresence* obj)
+ {
+ m_iPort = obj->m_iPort;
+ m_iAuthPort = obj->m_iAuthPort;
+
+ m_sServerName = obj->m_sServerName;
+ m_sServerDesc = obj->m_sServerDesc;
+ memcpy(m_Password, obj->m_Password, sizeof(m_Password));
+
+ memcpy(m_MapName, obj->m_MapName, sizeof(m_MapName));
+ memcpy(m_PlaylistName, obj->m_PlaylistName, sizeof(m_PlaylistName));
+
+ m_iPlayerCount = obj->m_iPlayerCount;
+ m_iMaxPlayers = obj->m_iMaxPlayers;
+ }
+};
+
+class ServerPresenceReporter
+{
+ public:
+ virtual void CreatePresence(const ServerPresence* pServerPresence) {}
+ virtual void ReportPresence(const ServerPresence* pServerPresence) {}
+ virtual void DestroyPresence(const ServerPresence* pServerPresence) {}
+};
+
+class ServerPresenceManager
+{
+ private:
+ ServerPresence m_ServerPresence;
+
+ bool m_bHasPresence = false;
+ bool m_bFirstPresenceUpdate = false;
+
+ std::vector<ServerPresenceReporter*> m_vPresenceReporters;
+
+ double m_flLastPresenceUpdate = 0;
+ ConVar* Cvar_ns_server_presence_update_rate;
+
+ ConVar* Cvar_ns_server_name;
+ ConVar* Cvar_ns_server_desc;
+ ConVar* Cvar_ns_server_password;
+
+ ConVar* Cvar_ns_report_server_to_masterserver;
+ ConVar* Cvar_ns_report_sp_server_to_masterserver;
+
+ public:
+ ServerPresenceManager();
+
+ void AddPresenceReporter(ServerPresenceReporter* reporter);
+
+ void CreatePresence();
+ void DestroyPresence();
+ void RunFrame(double flCurrentTime);
+
+ void SetPort(const int iPort);
+ void SetAuthPort(const int iPort);
+
+ void SetName(const std::string sServerNameUnicode);
+ void SetDescription(const std::string sServerDescUnicode);
+ void SetPassword(const char* pPassword);
+
+ void SetMap(const char* pMapName, bool isInitialising = false);
+ void SetPlaylist(const char* pPlaylistName);
+ void SetPlayerCount(const int iPlayerCount);
+};
+
+extern ServerPresenceManager* g_pServerPresence;
diff --git a/NorthstarDLL/sourceconsole.cpp b/NorthstarDLL/sourceconsole.cpp
new file mode 100644
index 00000000..ad31e09d
--- /dev/null
+++ b/NorthstarDLL/sourceconsole.cpp
@@ -0,0 +1,73 @@
+#include "pch.h"
+#include "convar.h"
+#include "sourceconsole.h"
+#include "sourceinterface.h"
+#include "concommand.h"
+#include "printcommand.h"
+
+SourceInterface<CGameConsole>* g_pSourceGameConsole;
+
+void ConCommand_toggleconsole(const CCommand& arg)
+{
+ if ((*g_pSourceGameConsole)->IsConsoleVisible())
+ (*g_pSourceGameConsole)->Hide();
+ else
+ (*g_pSourceGameConsole)->Activate();
+}
+
+void ConCommand_showconsole(const CCommand& arg)
+{
+ (*g_pSourceGameConsole)->Activate();
+}
+
+void ConCommand_hideconsole(const CCommand& arg)
+{
+ (*g_pSourceGameConsole)->Hide();
+}
+
+void SourceConsoleSink::sink_it_(const spdlog::details::log_msg& msg)
+{
+ if (!(*g_pSourceGameConsole)->m_bInitialized)
+ return;
+
+ spdlog::memory_buf_t formatted;
+ spdlog::sinks::base_sink<std::mutex>::formatter_->format(msg, formatted);
+ (*g_pSourceGameConsole)->m_pConsole->m_pConsolePanel->ColorPrint(m_LogColours[msg.level], fmt::to_string(formatted).c_str());
+}
+
+void SourceConsoleSink::flush_() {}
+
+// clang-format off
+HOOK(OnCommandSubmittedHook, OnCommandSubmitted,
+void, __fastcall, (CConsoleDialog* consoleDialog, const char* pCommand))
+// clang-format on
+{
+ consoleDialog->m_pConsolePanel->Print("] ");
+ consoleDialog->m_pConsolePanel->Print(pCommand);
+ consoleDialog->m_pConsolePanel->Print("\n");
+
+ TryPrintCvarHelpForCommand(pCommand);
+
+ OnCommandSubmitted(consoleDialog, pCommand);
+}
+
+// called from sourceinterface.cpp in client createinterface hooks, on GameClientExports001
+void InitialiseConsoleOnInterfaceCreation()
+{
+ (*g_pSourceGameConsole)->Initialize();
+ // hook OnCommandSubmitted so we print inputted commands
+ OnCommandSubmittedHook.Dispatch((*g_pSourceGameConsole)->m_pConsole->m_vtable->OnCommandSubmitted);
+
+ auto consoleLogger = std::make_shared<SourceConsoleSink>();
+ consoleLogger->set_pattern("[%l] %v");
+ spdlog::default_logger()->sinks().push_back(consoleLogger);
+}
+
+ON_DLL_LOAD_CLIENT_RELIESON("client.dll", SourceConsole, ConCommand, (CModule module))
+{
+ g_pSourceGameConsole = new SourceInterface<CGameConsole>("client.dll", "GameConsole004");
+
+ RegisterConCommand("toggleconsole", ConCommand_toggleconsole, "Show/hide the console.", FCVAR_DONTRECORD);
+ RegisterConCommand("showconsole", ConCommand_showconsole, "Show the console.", FCVAR_DONTRECORD);
+ RegisterConCommand("hideconsole", ConCommand_hideconsole, "Hide the console.", FCVAR_DONTRECORD);
+}
diff --git a/NorthstarDedicatedTest/sourceconsole.h b/NorthstarDLL/sourceconsole.h
index cf65cbd3..e811f523 100644
--- a/NorthstarDedicatedTest/sourceconsole.h
+++ b/NorthstarDLL/sourceconsole.h
@@ -86,21 +86,24 @@ class CGameConsole
CConsoleDialog* m_pConsole;
};
-extern SourceInterface<CGameConsole>* g_SourceGameConsole;
+extern SourceInterface<CGameConsole>* g_pSourceGameConsole;
// spdlog logger
class SourceConsoleSink : public spdlog::sinks::base_sink<std::mutex>
{
private:
- std::map<spdlog::level::level_enum, SourceColor> logColours;
-
- public:
- SourceConsoleSink();
+ std::map<spdlog::level::level_enum, SourceColor> m_LogColours = {
+ {spdlog::level::trace, SourceColor(0, 255, 255, 255)},
+ {spdlog::level::debug, SourceColor(0, 255, 255, 255)},
+ {spdlog::level::info, SourceColor(255, 255, 255, 255)},
+ {spdlog::level::warn, SourceColor(255, 255, 0, 255)},
+ {spdlog::level::err, SourceColor(255, 0, 0, 255)},
+ {spdlog::level::critical, SourceColor(255, 0, 0, 255)},
+ {spdlog::level::off, SourceColor(0, 0, 0, 0)}};
protected:
void sink_it_(const spdlog::details::log_msg& msg) override;
void flush_() override;
};
-void InitialiseSourceConsole(HMODULE baseAddress);
-void InitialiseConsoleOnInterfaceCreation(); \ No newline at end of file
+void InitialiseConsoleOnInterfaceCreation();
diff --git a/NorthstarDLL/sourceinterface.cpp b/NorthstarDLL/sourceinterface.cpp
new file mode 100644
index 00000000..d5f7b7cd
--- /dev/null
+++ b/NorthstarDLL/sourceinterface.cpp
@@ -0,0 +1,49 @@
+#include "pch.h"
+#include "sourceinterface.h"
+#include "sourceconsole.h"
+
+AUTOHOOK_INIT()
+
+// really wanted to do a modular callback system here but honestly couldn't be bothered so hardcoding stuff for now: todo later
+
+// clang-format off
+AUTOHOOK_PROCADDRESS(ClientCreateInterface, client.dll, CreateInterface,
+void*, __fastcall, (const char* pName, const int* pReturnCode))
+// clang-format on
+{
+ void* ret = ClientCreateInterface(pName, pReturnCode);
+ spdlog::info("CreateInterface CLIENT {}", pName);
+
+ if (!strcmp(pName, "GameClientExports001"))
+ InitialiseConsoleOnInterfaceCreation();
+
+ return ret;
+}
+
+// clang-format off
+AUTOHOOK_PROCADDRESS(ServerCreateInterface, server.dll, CreateInterface,
+void*, __fastcall, (const char* pName, const int* pReturnCode))
+// clang-format on
+{
+ void* ret = ServerCreateInterface(pName, pReturnCode);
+ spdlog::info("CreateInterface SERVER {}", pName);
+
+ return ret;
+}
+
+// clang-format off
+AUTOHOOK_PROCADDRESS(EngineCreateInterface, engine.dll, CreateInterface,
+void*, __fastcall, (const char* pName, const int* pReturnCode))
+// clang-format on
+{
+ void* ret = EngineCreateInterface(pName, pReturnCode);
+ spdlog::info("CreateInterface ENGINE {}", pName);
+
+ return ret;
+}
+
+// clang-format off
+ON_DLL_LOAD("client.dll", ClientInterface, (CModule module)) {AUTOHOOK_DISPATCH_MODULE(client.dll)}
+ON_DLL_LOAD("server.dll", ServerInterface, (CModule module)) {AUTOHOOK_DISPATCH_MODULE(server.dll)}
+ON_DLL_LOAD("engine.dll", EngineInterface, (CModule module)) {AUTOHOOK_DISPATCH_MODULE(engine.dll)}
+// clang-format on
diff --git a/NorthstarDedicatedTest/sourceinterface.h b/NorthstarDLL/sourceinterface.h
index 05318963..474e961b 100644
--- a/NorthstarDedicatedTest/sourceinterface.h
+++ b/NorthstarDLL/sourceinterface.h
@@ -29,6 +29,3 @@ template <typename T> class SourceInterface
return m_interface;
}
};
-
-// functions for interface creation callbacks
-void InitialiseInterfaceCreationHooks(); \ No newline at end of file
diff --git a/NorthstarDLL/squirrel.cpp b/NorthstarDLL/squirrel.cpp
new file mode 100644
index 00000000..5c2d8b1b
--- /dev/null
+++ b/NorthstarDLL/squirrel.cpp
@@ -0,0 +1,592 @@
+#include "pch.h"
+#include "squirrel.h"
+#include "concommand.h"
+#include "modmanager.h"
+#include "dedicated.h"
+#include "r2engine.h"
+#include "tier0.h"
+
+AUTOHOOK_INIT()
+
+const char* GetContextName(ScriptContext context)
+{
+ switch (context)
+ {
+ case ScriptContext::CLIENT:
+ return "CLIENT";
+ case ScriptContext::SERVER:
+ return "SERVER";
+ case ScriptContext::UI:
+ return "UI";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+eSQReturnType SQReturnTypeFromString(const char* pReturnType)
+{
+ static const std::map<std::string, eSQReturnType> sqReturnTypeNameToString = {
+ {"bool", eSQReturnType::Boolean},
+ {"float", eSQReturnType::Float},
+ {"vector", eSQReturnType::Vector},
+ {"int", eSQReturnType::Integer},
+ {"entity", eSQReturnType::Entity},
+ {"string", eSQReturnType::String},
+ {"array", eSQReturnType::Arrays},
+ {"asset", eSQReturnType::Asset},
+ {"table", eSQReturnType::Table}};
+
+ if (sqReturnTypeNameToString.find(pReturnType) != sqReturnTypeNameToString.end())
+ return sqReturnTypeNameToString.at(pReturnType);
+ else
+ return eSQReturnType::Default; // previous default value
+}
+
+const char* SQTypeNameFromID(int type)
+{
+ switch (type)
+ {
+ case OT_ASSET:
+ return "asset";
+ case OT_INTEGER:
+ return "int";
+ case OT_BOOL:
+ return "bool";
+ case SQOBJECT_NUMERIC:
+ return "float or int";
+ case OT_NULL:
+ return "null";
+ case OT_VECTOR:
+ return "vector";
+ case 0:
+ return "var";
+ case OT_USERDATA:
+ return "userdata";
+ case OT_FLOAT:
+ return "float";
+ case OT_STRING:
+ return "string";
+ case OT_ARRAY:
+ return "array";
+ case 0x8000200:
+ return "function";
+ case 0x8100000:
+ return "structdef";
+ case OT_THREAD:
+ return "thread";
+ case OT_FUNCPROTO:
+ return "function";
+ case OT_CLAAS:
+ return "class";
+ case OT_WEAKREF:
+ return "weakref";
+ case 0x8080000:
+ return "unimplemented function";
+ case 0x8200000:
+ return "struct instance";
+ case OT_TABLE:
+ return "table";
+ case 0xA008000:
+ return "instance";
+ case OT_ENTITY:
+ return "entity";
+ }
+ return "";
+}
+
+// needed to define implementations for squirrelmanager outside of squirrel.h without compiler errors
+template class SquirrelManager<ScriptContext::SERVER>;
+template class SquirrelManager<ScriptContext::CLIENT>;
+template class SquirrelManager<ScriptContext::UI>;
+
+template <ScriptContext context> void SquirrelManager<context>::VMCreated(CSquirrelVM* newSqvm)
+{
+ m_pSQVM = newSqvm;
+
+ for (SQFuncRegistration* funcReg : m_funcRegistrations)
+ {
+ spdlog::info("Registering {} function {}", GetContextName(context), funcReg->squirrelFuncName);
+ RegisterSquirrelFunc(m_pSQVM, funcReg, 1);
+ }
+
+ for (auto& pair : g_pModManager->m_DependencyConstants)
+ {
+ bool bWasFound = false;
+ for (Mod& dependency : g_pModManager->m_LoadedMods)
+ {
+ if (!dependency.m_bEnabled)
+ continue;
+
+ if (dependency.Name == pair.second)
+ {
+ bWasFound = true;
+ break;
+ }
+ }
+
+ defconst(m_pSQVM, pair.first.c_str(), bWasFound);
+ }
+}
+
+template <ScriptContext context> void SquirrelManager<context>::VMDestroyed()
+{
+ m_pSQVM = nullptr;
+}
+
+template <ScriptContext context> void SquirrelManager<context>::ExecuteCode(const char* pCode)
+{
+ if (!m_pSQVM || !m_pSQVM->sqvm)
+ {
+ spdlog::error("Cannot execute code, {} squirrel vm is not initialised", GetContextName(context));
+ return;
+ }
+
+ spdlog::info("Executing {} script code {} ", GetContextName(context), pCode);
+
+ std::string strCode(pCode);
+ CompileBufferState bufferState = CompileBufferState(strCode);
+
+ SQRESULT compileResult = compilebuffer(&bufferState, "console");
+ spdlog::info("sq_compilebuffer returned {}", PrintSQRESULT.at(compileResult));
+
+ if (compileResult != SQRESULT_ERROR)
+ {
+ pushroottable(m_pSQVM->sqvm);
+ SQRESULT callResult = call(m_pSQVM->sqvm, 0);
+ spdlog::info("sq_call returned {}", PrintSQRESULT.at(callResult));
+ }
+}
+
+template <ScriptContext context> void SquirrelManager<context>::AddFuncRegistration(
+ std::string returnType, std::string name, std::string argTypes, std::string helpText, SQFunction func)
+{
+ SQFuncRegistration* reg = new SQFuncRegistration;
+
+ reg->squirrelFuncName = new char[name.size() + 1];
+ strcpy((char*)reg->squirrelFuncName, name.c_str());
+ reg->cppFuncName = reg->squirrelFuncName;
+
+ reg->helpText = new char[helpText.size() + 1];
+ strcpy((char*)reg->helpText, helpText.c_str());
+
+ reg->returnTypeString = new char[returnType.size() + 1];
+ strcpy((char*)reg->returnTypeString, returnType.c_str());
+ reg->returnType = SQReturnTypeFromString(returnType.c_str());
+
+ reg->argTypes = new char[argTypes.size() + 1];
+ strcpy((char*)reg->argTypes, argTypes.c_str());
+
+ reg->funcPtr = func;
+
+ m_funcRegistrations.push_back(reg);
+}
+
+template <ScriptContext context> SQRESULT SquirrelManager<context>::setupfunc(const SQChar* funcname)
+{
+ pushroottable(m_pSQVM->sqvm);
+ pushstring(m_pSQVM->sqvm, funcname, -1);
+
+ SQRESULT result = get(m_pSQVM->sqvm, -2);
+ if (result != SQRESULT_ERROR)
+ pushroottable(m_pSQVM->sqvm);
+
+ return result;
+}
+
+template <ScriptContext context> void SquirrelManager<context>::AddFuncOverride(std::string name, SQFunction func)
+{
+ m_funcOverrides[name] = func;
+}
+
+// hooks
+bool IsUIVM(ScriptContext context, HSquirrelVM* pSqvm)
+{
+ return context != ScriptContext::SERVER && g_pSquirrel<ScriptContext::UI>->m_pSQVM &&
+ g_pSquirrel<ScriptContext::UI>->m_pSQVM->sqvm == pSqvm;
+}
+
+template <ScriptContext context> void* (*__fastcall sq_compiler_create)(HSquirrelVM* sqvm, void* a2, void* a3, SQBool bShouldThrowError);
+template <ScriptContext context> void* __fastcall sq_compiler_createHook(HSquirrelVM* sqvm, void* a2, void* a3, SQBool bShouldThrowError)
+{
+ // store whether errors generated from this compile should be fatal
+ if (IsUIVM(context, sqvm))
+ g_pSquirrel<ScriptContext::UI>->m_bFatalCompilationErrors = bShouldThrowError;
+ else
+ g_pSquirrel<context>->m_bFatalCompilationErrors = bShouldThrowError;
+
+ return sq_compiler_create<context>(sqvm, a2, a3, bShouldThrowError);
+}
+
+template <ScriptContext context> SQInteger (*SQPrint)(HSquirrelVM* sqvm, const char* fmt);
+template <ScriptContext context> SQInteger SQPrintHook(HSquirrelVM* sqvm, const char* fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+
+ SQChar buf[1024];
+ int charsWritten = vsnprintf_s(buf, _TRUNCATE, fmt, va);
+
+ if (charsWritten > 0)
+ {
+ if (buf[charsWritten - 1] == '\n')
+ buf[charsWritten - 1] = '\0';
+
+ spdlog::info("[{} SCRIPT] {}", GetContextName(context), buf);
+ }
+
+ va_end(va);
+ return 0;
+}
+
+template <ScriptContext context> CSquirrelVM* (*__fastcall CreateNewVM)(void* a1, ScriptContext realContext);
+template <ScriptContext context> CSquirrelVM* __fastcall CreateNewVMHook(void* a1, ScriptContext realContext)
+{
+ CSquirrelVM* sqvm = CreateNewVM<context>(a1, realContext);
+ if (realContext == ScriptContext::UI)
+ g_pSquirrel<ScriptContext::UI>->VMCreated(sqvm);
+ else
+ g_pSquirrel<context>->VMCreated(sqvm);
+
+ spdlog::info("CreateNewVM {} {}", GetContextName(realContext), (void*)sqvm);
+ return sqvm;
+}
+
+template <ScriptContext context> void (*__fastcall DestroyVM)(void* a1, HSquirrelVM* sqvm);
+template <ScriptContext context> void __fastcall DestroyVMHook(void* a1, HSquirrelVM* sqvm)
+{
+ ScriptContext realContext = context; // ui and client use the same function so we use this for prints
+ if (IsUIVM(context, sqvm))
+ {
+ realContext = ScriptContext::UI;
+ g_pSquirrel<ScriptContext::UI>->VMDestroyed();
+ }
+ else
+ DestroyVM<context>(a1, sqvm);
+
+ spdlog::info("DestroyVM {} {}", GetContextName(realContext), (void*)sqvm);
+}
+
+template <ScriptContext context>
+void (*__fastcall SQCompileError)(HSquirrelVM* sqvm, const char* error, const char* file, int line, int column);
+template <ScriptContext context>
+void __fastcall ScriptCompileErrorHook(HSquirrelVM* sqvm, const char* error, const char* file, int line, int column)
+{
+ bool bIsFatalError = g_pSquirrel<context>->m_bFatalCompilationErrors;
+ ScriptContext realContext = context; // ui and client use the same function so we use this for prints
+ if (IsUIVM(context, sqvm))
+ {
+ realContext = ScriptContext::UI;
+ bIsFatalError = g_pSquirrel<ScriptContext::UI>->m_bFatalCompilationErrors;
+ }
+
+ spdlog::error("{} SCRIPT COMPILE ERROR {}", GetContextName(realContext), error);
+ spdlog::error("{} line [{}] column [{}]", file, line, column);
+
+ // use disconnect to display an error message for the compile error, but only if the compilation error was fatal
+ // todo, we could get this from sqvm itself probably, rather than hooking sq_compiler_create
+ if (bIsFatalError)
+ {
+ // kill dedicated server if we hit this
+ if (IsDedicatedServer())
+ abort();
+ else
+ {
+ R2::Cbuf_AddText(
+ R2::Cbuf_GetCurrentPlayer(),
+ fmt::format("disconnect \"Encountered {} script compilation error, see console for details.\"", GetContextName(realContext))
+ .c_str(),
+ R2::cmd_source_t::kCommandSrcCode);
+
+ // likely temp: show console so user can see any errors, as error message wont display if ui is dead
+ // maybe we could disable all mods other than the coremods and try a reload before doing this?
+ // could also maybe do some vgui bullshit to show something visually rather than console
+ if (realContext == ScriptContext::UI)
+ R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "showconsole", R2::cmd_source_t::kCommandSrcCode);
+ }
+ }
+
+ // dont call the original function since it kills game lol
+}
+
+template <ScriptContext context>
+int64_t (*__fastcall RegisterSquirrelFunction)(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown);
+template <ScriptContext context>
+int64_t __fastcall RegisterSquirrelFunctionHook(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown)
+{
+ if (IsUIVM(context, sqvm->sqvm))
+ {
+ if (g_pSquirrel<ScriptContext::UI>->m_funcOverrides.count(funcReg->squirrelFuncName))
+ {
+ g_pSquirrel<ScriptContext::UI>->m_funcOriginals[funcReg->squirrelFuncName] = funcReg->funcPtr;
+ funcReg->funcPtr = g_pSquirrel<ScriptContext::UI>->m_funcOverrides[funcReg->squirrelFuncName];
+ spdlog::info("Replacing {} in UI", std::string(funcReg->squirrelFuncName));
+ }
+
+ return g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc(sqvm, funcReg, unknown);
+ }
+
+ if (g_pSquirrel<context>->m_funcOverrides.find(funcReg->squirrelFuncName) != g_pSquirrel<context>->m_funcOverrides.end())
+ {
+ g_pSquirrel<context>->m_funcOriginals[funcReg->squirrelFuncName] = funcReg->funcPtr;
+ funcReg->funcPtr = g_pSquirrel<context>->m_funcOverrides[funcReg->squirrelFuncName];
+ spdlog::info("Replacing {} in Client", std::string(funcReg->squirrelFuncName));
+ }
+
+ return g_pSquirrel<context>->RegisterSquirrelFunc(sqvm, funcReg, unknown);
+}
+
+template <ScriptContext context> bool (*__fastcall CallScriptInitCallback)(void* sqvm, const char* callback);
+template <ScriptContext context> bool __fastcall CallScriptInitCallbackHook(void* sqvm, const char* callback)
+{
+ ScriptContext realContext = context;
+ bool bShouldCallCustomCallbacks = true;
+
+ if (context == ScriptContext::CLIENT)
+ {
+ if (!strcmp(callback, "UICodeCallback_UIInit"))
+ realContext = ScriptContext::UI;
+ else if (strcmp(callback, "ClientCodeCallback_MapSpawn"))
+ bShouldCallCustomCallbacks = false;
+ }
+ else if (context == ScriptContext::SERVER)
+ bShouldCallCustomCallbacks = !strcmp(callback, "CodeCallback_MapSpawn");
+
+ if (bShouldCallCustomCallbacks)
+ {
+ for (Mod mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.m_bEnabled)
+ continue;
+
+ for (ModScript script : mod.Scripts)
+ {
+ for (ModScriptCallback modCallback : script.Callbacks)
+ {
+ if (modCallback.Context == realContext && modCallback.BeforeCallback.length())
+ {
+ spdlog::info("Running custom {} script callback \"{}\"", GetContextName(realContext), modCallback.BeforeCallback);
+ CallScriptInitCallback<context>(sqvm, modCallback.BeforeCallback.c_str());
+ }
+ }
+ }
+ }
+ }
+
+ spdlog::info("{} CodeCallback {} called", GetContextName(realContext), callback);
+ if (!bShouldCallCustomCallbacks)
+ spdlog::info("Not executing custom callbacks for CodeCallback {}", callback);
+ bool ret = CallScriptInitCallback<context>(sqvm, callback);
+
+ // run after callbacks
+ if (bShouldCallCustomCallbacks)
+ {
+ for (Mod mod : g_pModManager->m_LoadedMods)
+ {
+ if (!mod.m_bEnabled)
+ continue;
+
+ for (ModScript script : mod.Scripts)
+ {
+ for (ModScriptCallback modCallback : script.Callbacks)
+ {
+ if (modCallback.Context == realContext && modCallback.AfterCallback.length())
+ {
+ spdlog::info("Running custom {} script callback \"{}\"", GetContextName(realContext), modCallback.AfterCallback);
+ CallScriptInitCallback<context>(sqvm, modCallback.AfterCallback.c_str());
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+template <ScriptContext context> void ConCommand_script(const CCommand& args)
+{
+ g_pSquirrel<context>->ExecuteCode(args.ArgS());
+}
+
+// literal class type that wraps a constant expression string
+template <size_t N> struct TemplateStringLiteral
+{
+ constexpr TemplateStringLiteral(const char (&str)[N])
+ {
+ std::copy_n(str, N, value);
+ }
+
+ char value[N];
+};
+
+template <ScriptContext context, TemplateStringLiteral funcName> SQRESULT SQ_StubbedFunc(HSquirrelVM* sqvm)
+{
+ spdlog::info("Blocking call to stubbed function {} in {}", funcName.value, GetContextName(context));
+ return SQRESULT_NULL;
+}
+
+template <ScriptContext context> void StubUnsafeSQFuncs()
+{
+ if (!Tier0::CommandLine()->CheckParm("-allowunsafesqfuncs"))
+ {
+ g_pSquirrel<context>->AddFuncOverride("DevTextBufferWrite", SQ_StubbedFunc<context, "DevTextBufferWrite">);
+ g_pSquirrel<context>->AddFuncOverride("DevTextBufferClear", SQ_StubbedFunc<context, "DevTextBufferClear">);
+ g_pSquirrel<context>->AddFuncOverride("DevTextBufferDumpToFile", SQ_StubbedFunc<context, "DevTextBufferDumpToFile">);
+ g_pSquirrel<context>->AddFuncOverride("Dev_CommandLineAddParam", SQ_StubbedFunc<context, "Dev_CommandLineAddParam">);
+ g_pSquirrel<context>->AddFuncOverride("DevP4Checkout", SQ_StubbedFunc<context, "DevP4Checkout">);
+ g_pSquirrel<context>->AddFuncOverride("DevP4Add", SQ_StubbedFunc<context, "DevP4Add">);
+ }
+}
+
+ON_DLL_LOAD_RELIESON("client.dll", ClientSquirrel, ConCommand, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(client.dll)
+
+ g_pSquirrel<ScriptContext::CLIENT> = new SquirrelManager<ScriptContext::CLIENT>;
+ g_pSquirrel<ScriptContext::UI> = new SquirrelManager<ScriptContext::UI>;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_defconst = module.Offset(0x12120).As<sq_defconstType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_defconst = g_pSquirrel<ScriptContext::CLIENT>->__sq_defconst;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_compilebuffer = module.Offset(0x3110).As<sq_compilebufferType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushroottable = module.Offset(0x5860).As<sq_pushroottableType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_compilebuffer = g_pSquirrel<ScriptContext::CLIENT>->__sq_compilebuffer;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushroottable = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushroottable;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_call = module.Offset(0x8650).As<sq_callType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_call = g_pSquirrel<ScriptContext::CLIENT>->__sq_call;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_newarray = module.Offset(0x39F0).As<sq_newarrayType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_arrayappend = module.Offset(0x3C70).As<sq_arrayappendType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_newarray = g_pSquirrel<ScriptContext::CLIENT>->__sq_newarray;
+ g_pSquirrel<ScriptContext::UI>->__sq_arrayappend = g_pSquirrel<ScriptContext::CLIENT>->__sq_arrayappend;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_newtable = module.Offset(0x3960).As<sq_newtableType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_newslot = module.Offset(0x70B0).As<sq_newslotType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_newtable = g_pSquirrel<ScriptContext::CLIENT>->__sq_newtable;
+ g_pSquirrel<ScriptContext::UI>->__sq_newslot = g_pSquirrel<ScriptContext::CLIENT>->__sq_newslot;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushstring = module.Offset(0x3440).As<sq_pushstringType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushinteger = module.Offset(0x36A0).As<sq_pushintegerType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushfloat = module.Offset(0x3800).As<sq_pushfloatType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushbool = module.Offset(0x3710).As<sq_pushboolType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushasset = module.Offset(0x3560).As<sq_pushassetType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_pushvector = module.Offset(0x3780).As<sq_pushvectorType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror = module.Offset(0x8470).As<sq_raiseerrorType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_pushstring = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushstring;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushinteger = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushinteger;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushfloat = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushfloat;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushbool = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushbool;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushvector = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushvector;
+ g_pSquirrel<ScriptContext::UI>->__sq_pushasset = g_pSquirrel<ScriptContext::CLIENT>->__sq_pushasset;
+ g_pSquirrel<ScriptContext::UI>->__sq_raiseerror = g_pSquirrel<ScriptContext::CLIENT>->__sq_raiseerror;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getstring = module.Offset(0x60C0).As<sq_getstringType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getinteger = module.Offset(0x60E0).As<sq_getintegerType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getfloat = module.Offset(0x6100).As<sq_getfloatType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getbool = module.Offset(0x6130).As<sq_getboolType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_get = module.Offset(0x7C30).As<sq_getType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getasset = module.Offset(0x6010).As<sq_getassetType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getuserdata = module.Offset(0x63D0).As<sq_getuserdataType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_getvector = module.Offset(0x6140).As<sq_getvectorType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_getstring = g_pSquirrel<ScriptContext::CLIENT>->__sq_getstring;
+ g_pSquirrel<ScriptContext::UI>->__sq_getinteger = g_pSquirrel<ScriptContext::CLIENT>->__sq_getinteger;
+ g_pSquirrel<ScriptContext::UI>->__sq_getfloat = g_pSquirrel<ScriptContext::CLIENT>->__sq_getfloat;
+ g_pSquirrel<ScriptContext::UI>->__sq_getbool = g_pSquirrel<ScriptContext::CLIENT>->__sq_getbool;
+ g_pSquirrel<ScriptContext::UI>->__sq_get = g_pSquirrel<ScriptContext::CLIENT>->__sq_get;
+ g_pSquirrel<ScriptContext::UI>->__sq_getasset = g_pSquirrel<ScriptContext::CLIENT>->__sq_getasset;
+ g_pSquirrel<ScriptContext::UI>->__sq_getuserdata = g_pSquirrel<ScriptContext::CLIENT>->__sq_getuserdata;
+ g_pSquirrel<ScriptContext::UI>->__sq_getvector = g_pSquirrel<ScriptContext::CLIENT>->__sq_getvector;
+
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_createuserdata = module.Offset(0x38D0).As<sq_createuserdataType>();
+ g_pSquirrel<ScriptContext::CLIENT>->__sq_setuserdatatypeid = module.Offset(0x6490).As<sq_setuserdatatypeidType>();
+ g_pSquirrel<ScriptContext::UI>->__sq_createuserdata = g_pSquirrel<ScriptContext::CLIENT>->__sq_createuserdata;
+ g_pSquirrel<ScriptContext::UI>->__sq_setuserdatatypeid = g_pSquirrel<ScriptContext::CLIENT>->__sq_setuserdatatypeid;
+
+ MAKEHOOK(
+ module.Offset(0x108E0),
+ &RegisterSquirrelFunctionHook<ScriptContext::CLIENT>,
+ &g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc);
+ g_pSquirrel<ScriptContext::UI>->RegisterSquirrelFunc = g_pSquirrel<ScriptContext::CLIENT>->RegisterSquirrelFunc;
+
+ // uiscript_reset concommand: don't loop forever if compilation fails
+ module.Offset(0x3C6E4C).NOP(6);
+
+ MAKEHOOK(module.Offset(0x8AD0), &sq_compiler_createHook<ScriptContext::CLIENT>, &sq_compiler_create<ScriptContext::CLIENT>);
+
+ MAKEHOOK(module.Offset(0x12B00), &SQPrintHook<ScriptContext::CLIENT>, &SQPrint<ScriptContext::CLIENT>);
+ MAKEHOOK(module.Offset(0x12BA0), &SQPrintHook<ScriptContext::UI>, &SQPrint<ScriptContext::UI>);
+
+ MAKEHOOK(module.Offset(0x26130), &CreateNewVMHook<ScriptContext::CLIENT>, &CreateNewVM<ScriptContext::CLIENT>);
+ MAKEHOOK(module.Offset(0x26E70), &DestroyVMHook<ScriptContext::CLIENT>, &DestroyVM<ScriptContext::CLIENT>);
+ MAKEHOOK(module.Offset(0x79A50), &ScriptCompileErrorHook<ScriptContext::CLIENT>, &SQCompileError<ScriptContext::CLIENT>);
+
+ MAKEHOOK(module.Offset(0x10190), &CallScriptInitCallbackHook<ScriptContext::CLIENT>, &CallScriptInitCallback<ScriptContext::CLIENT>);
+
+ RegisterConCommand("script_client", ConCommand_script<ScriptContext::CLIENT>, "Executes script code on the client vm", FCVAR_CLIENTDLL);
+ RegisterConCommand("script_ui", ConCommand_script<ScriptContext::UI>, "Executes script code on the ui vm", FCVAR_CLIENTDLL);
+
+ StubUnsafeSQFuncs<ScriptContext::CLIENT>();
+ StubUnsafeSQFuncs<ScriptContext::UI>();
+}
+
+ON_DLL_LOAD_RELIESON("server.dll", ServerSquirrel, ConCommand, (CModule module))
+{
+ AUTOHOOK_DISPATCH_MODULE(server.dll)
+
+ g_pSquirrel<ScriptContext::SERVER> = new SquirrelManager<ScriptContext::SERVER>;
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_defconst = module.Offset(0x1F550).As<sq_defconstType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_compilebuffer = module.Offset(0x3110).As<sq_compilebufferType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushroottable = module.Offset(0x5840).As<sq_pushroottableType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_call = module.Offset(0x8620).As<sq_callType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_newarray = module.Offset(0x39F0).As<sq_newarrayType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_arrayappend = module.Offset(0x3C70).As<sq_arrayappendType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_newtable = module.Offset(0x3960).As<sq_newtableType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_newslot = module.Offset(0x7080).As<sq_newslotType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushstring = module.Offset(0x3440).As<sq_pushstringType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushinteger = module.Offset(0x36A0).As<sq_pushintegerType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushfloat = module.Offset(0x3800).As<sq_pushfloatType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushbool = module.Offset(0x3710).As<sq_pushboolType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushasset = module.Offset(0x3560).As<sq_pushassetType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_pushvector = module.Offset(0x3780).As<sq_pushvectorType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_raiseerror = module.Offset(0x8440).As<sq_raiseerrorType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getstring = module.Offset(0x60A0).As<sq_getstringType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getinteger = module.Offset(0x60C0).As<sq_getintegerType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getfloat = module.Offset(0x60E0).As<sq_getfloatType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getbool = module.Offset(0x6110).As<sq_getboolType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getasset = module.Offset(0x5FF0).As<sq_getassetType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getuserdata = module.Offset(0x63B0).As<sq_getuserdataType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_getvector = module.Offset(0x6120).As<sq_getvectorType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_get = module.Offset(0x7C00).As<sq_getType>();
+
+ g_pSquirrel<ScriptContext::SERVER>->__sq_createuserdata = module.Offset(0x38D0).As<sq_createuserdataType>();
+ g_pSquirrel<ScriptContext::SERVER>->__sq_setuserdatatypeid = module.Offset(0x6470).As<sq_setuserdatatypeidType>();
+
+ MAKEHOOK(
+ module.Offset(0x1DD10),
+ &RegisterSquirrelFunctionHook<ScriptContext::SERVER>,
+ &g_pSquirrel<ScriptContext::SERVER>->RegisterSquirrelFunc);
+
+ MAKEHOOK(module.Offset(0x8AA0), &sq_compiler_createHook<ScriptContext::SERVER>, &sq_compiler_create<ScriptContext::SERVER>);
+
+ MAKEHOOK(module.Offset(0x1FE90), &SQPrintHook<ScriptContext::SERVER>, &SQPrint<ScriptContext::SERVER>);
+ MAKEHOOK(module.Offset(0x260E0), &CreateNewVMHook<ScriptContext::SERVER>, &CreateNewVM<ScriptContext::SERVER>);
+ MAKEHOOK(module.Offset(0x26E20), &DestroyVMHook<ScriptContext::SERVER>, &DestroyVM<ScriptContext::SERVER>);
+ MAKEHOOK(module.Offset(0x799E0), &ScriptCompileErrorHook<ScriptContext::SERVER>, &SQCompileError<ScriptContext::SERVER>);
+ MAKEHOOK(module.Offset(0x1D5C0), &CallScriptInitCallbackHook<ScriptContext::SERVER>, &CallScriptInitCallback<ScriptContext::SERVER>);
+
+ // FCVAR_CHEAT and FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS allows clients to execute this, but since it's unsafe we only allow it when cheats
+ // are enabled for script_client and script_ui, we don't use cheats, so clients can execute them on themselves all they want
+ RegisterConCommand(
+ "script",
+ ConCommand_script<ScriptContext::SERVER>,
+ "Executes script code on the server vm",
+ FCVAR_GAMEDLL | FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS | FCVAR_CHEAT);
+
+ StubUnsafeSQFuncs<ScriptContext::SERVER>();
+}
diff --git a/NorthstarDLL/squirrel.h b/NorthstarDLL/squirrel.h
new file mode 100644
index 00000000..4f644703
--- /dev/null
+++ b/NorthstarDLL/squirrel.h
@@ -0,0 +1,318 @@
+#pragma once
+
+#include "squirreldatatypes.h"
+#include "vector.h"
+
+// stolen from ttf2sdk: sqvm types
+typedef float SQFloat;
+typedef long SQInteger;
+typedef unsigned long SQUnsignedInteger;
+typedef char SQChar;
+typedef SQUnsignedInteger SQBool;
+
+enum SQRESULT : SQInteger
+{
+ SQRESULT_ERROR = -1,
+ SQRESULT_NULL = 0,
+ SQRESULT_NOTNULL = 1,
+};
+
+typedef SQRESULT (*SQFunction)(HSquirrelVM* sqvm);
+
+enum class eSQReturnType
+{
+ Float = 0x1,
+ Vector = 0x3,
+ Integer = 0x5,
+ Boolean = 0x6,
+ Entity = 0xD,
+ String = 0x21,
+ Default = 0x20,
+ Arrays = 0x25,
+ Asset = 0x28,
+ Table = 0x26,
+};
+
+const std::map<SQRESULT, const char*> PrintSQRESULT = {
+ {SQRESULT_ERROR, "SQRESULT_ERROR"}, {SQRESULT_NULL, "SQRESULT_NULL"}, {SQRESULT_NOTNULL, "SQRESULT_NOTNULL"}};
+
+struct CompileBufferState
+{
+ const SQChar* buffer;
+ const SQChar* bufferPlusLength;
+ const SQChar* bufferAgain;
+
+ CompileBufferState(const std::string& code)
+ {
+ buffer = code.c_str();
+ bufferPlusLength = code.c_str() + code.size();
+ bufferAgain = code.c_str();
+ }
+};
+
+struct SQFuncRegistration
+{
+ const char* squirrelFuncName;
+ const char* cppFuncName;
+ const char* helpText;
+ const char* returnTypeString;
+ const char* argTypes;
+ uint32_t unknown1;
+ uint32_t devLevel;
+ const char* shortNameMaybe;
+ uint32_t unknown2;
+ eSQReturnType returnType;
+ uint32_t* externalBufferPointer;
+ uint64_t externalBufferSize;
+ uint64_t unknown3;
+ uint64_t unknown4;
+ SQFunction funcPtr;
+
+ SQFuncRegistration()
+ {
+ memset(this, 0, sizeof(SQFuncRegistration));
+ this->returnType = eSQReturnType::Default;
+ }
+};
+
+enum class ScriptContext : int
+{
+ SERVER,
+ CLIENT,
+ UI,
+};
+
+const char* GetContextName(ScriptContext context);
+eSQReturnType SQReturnTypeFromString(const char* pReturnType);
+const char* SQTypeNameFromID(const int iTypeId);
+
+// core sqvm funcs
+typedef int64_t (*RegisterSquirrelFuncType)(CSquirrelVM* sqvm, SQFuncRegistration* funcReg, char unknown);
+typedef void (*sq_defconstType)(CSquirrelVM* sqvm, const SQChar* name, int value);
+
+typedef SQRESULT (*sq_compilebufferType)(
+ HSquirrelVM* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, SQBool bShouldThrowError);
+typedef SQRESULT (*sq_callType)(HSquirrelVM* sqvm, SQInteger iArgs, SQBool bShouldReturn, SQBool bThrowError);
+typedef SQInteger (*sq_raiseerrorType)(HSquirrelVM* sqvm, const SQChar* pError);
+
+// sq stack array funcs
+typedef void (*sq_newarrayType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+typedef SQRESULT (*sq_arrayappendType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+
+// sq table funcs
+typedef SQRESULT (*sq_newtableType)(HSquirrelVM* sqvm);
+typedef SQRESULT (*sq_newslotType)(HSquirrelVM* sqvm, SQInteger idx, SQBool bStatic);
+
+// sq stack push funcs
+typedef void (*sq_pushroottableType)(HSquirrelVM* sqvm);
+typedef void (*sq_pushstringType)(HSquirrelVM* sqvm, const SQChar* pStr, SQInteger iLength);
+typedef void (*sq_pushintegerType)(HSquirrelVM* sqvm, SQInteger i);
+typedef void (*sq_pushfloatType)(HSquirrelVM* sqvm, SQFloat f);
+typedef void (*sq_pushboolType)(HSquirrelVM* sqvm, SQBool b);
+typedef void (*sq_pushassetType)(HSquirrelVM* sqvm, const SQChar* str, SQInteger iLength);
+typedef void (*sq_pushvectorType)(HSquirrelVM* sqvm, const SQFloat* pVec);
+
+// sq stack get funcs
+typedef const SQChar* (*sq_getstringType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+typedef SQInteger (*sq_getintegerType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+typedef SQFloat (*sq_getfloatType)(HSquirrelVM*, SQInteger iStackpos);
+typedef SQBool (*sq_getboolType)(HSquirrelVM*, SQInteger iStackpos);
+typedef SQRESULT (*sq_getType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+typedef SQRESULT (*sq_getassetType)(HSquirrelVM* sqvm, SQInteger iStackpos, const char** pResult);
+typedef SQRESULT (*sq_getuserdataType)(HSquirrelVM* sqvm, SQInteger iStackpos, void** pData, uint64_t* pTypeId);
+typedef SQFloat* (*sq_getvectorType)(HSquirrelVM* sqvm, SQInteger iStackpos);
+
+// sq stack userpointer funcs
+typedef void* (*sq_createuserdataType)(HSquirrelVM* sqvm, SQInteger iSize);
+typedef SQRESULT (*sq_setuserdatatypeidType)(HSquirrelVM* sqvm, SQInteger iStackpos, uint64_t iTypeId);
+
+template <ScriptContext context> class SquirrelManager
+{
+ private:
+ std::vector<SQFuncRegistration*> m_funcRegistrations;
+
+ public:
+ CSquirrelVM* m_pSQVM;
+ std::map<std::string, SQFunction> m_funcOverrides = {};
+ std::map<std::string, SQFunction> m_funcOriginals = {};
+
+ bool m_bFatalCompilationErrors = false;
+
+#pragma region SQVM funcs
+ RegisterSquirrelFuncType RegisterSquirrelFunc;
+ sq_defconstType __sq_defconst;
+
+ sq_compilebufferType __sq_compilebuffer;
+ sq_callType __sq_call;
+ sq_raiseerrorType __sq_raiseerror;
+
+ sq_newarrayType __sq_newarray;
+ sq_arrayappendType __sq_arrayappend;
+
+ sq_newtableType __sq_newtable;
+ sq_newslotType __sq_newslot;
+
+ sq_pushroottableType __sq_pushroottable;
+ sq_pushstringType __sq_pushstring;
+ sq_pushintegerType __sq_pushinteger;
+ sq_pushfloatType __sq_pushfloat;
+ sq_pushboolType __sq_pushbool;
+ sq_pushassetType __sq_pushasset;
+ sq_pushvectorType __sq_pushvector;
+
+ sq_getstringType __sq_getstring;
+ sq_getintegerType __sq_getinteger;
+ sq_getfloatType __sq_getfloat;
+ sq_getboolType __sq_getbool;
+ sq_getType __sq_get;
+ sq_getassetType __sq_getasset;
+ sq_getuserdataType __sq_getuserdata;
+ sq_getvectorType __sq_getvector;
+
+ sq_createuserdataType __sq_createuserdata;
+ sq_setuserdatatypeidType __sq_setuserdatatypeid;
+#pragma endregion
+
+ public:
+ SquirrelManager() : m_pSQVM(nullptr) {}
+
+ void VMCreated(CSquirrelVM* newSqvm);
+ void VMDestroyed();
+ void ExecuteCode(const char* code);
+ void AddFuncRegistration(std::string returnType, std::string name, std::string argTypes, std::string helpText, SQFunction func);
+ SQRESULT setupfunc(const SQChar* funcname);
+ void AddFuncOverride(std::string name, SQFunction func);
+
+#pragma region SQVM func wrappers
+ inline void defconst(CSquirrelVM* sqvm, const SQChar* pName, int nValue)
+ {
+ __sq_defconst(sqvm, pName, nValue);
+ }
+
+ inline SQRESULT
+ compilebuffer(CompileBufferState* bufferState, const SQChar* bufferName = "unnamedbuffer", const SQBool bShouldThrowError = false)
+ {
+ return __sq_compilebuffer(m_pSQVM->sqvm, bufferState, bufferName, -1, bShouldThrowError);
+ }
+
+ inline SQRESULT call(HSquirrelVM* sqvm, const SQInteger args)
+ {
+ return __sq_call(sqvm, args + 1, false, false);
+ }
+
+ inline SQInteger raiseerror(HSquirrelVM* sqvm, const const SQChar* sError)
+ {
+ return __sq_raiseerror(sqvm, sError);
+ }
+
+ inline void newarray(HSquirrelVM* sqvm, const SQInteger stackpos = 0)
+ {
+ __sq_newarray(sqvm, stackpos);
+ }
+
+ inline SQRESULT arrayappend(HSquirrelVM* sqvm, const SQInteger stackpos)
+ {
+ return __sq_arrayappend(sqvm, stackpos);
+ }
+
+ inline SQRESULT newtable(HSquirrelVM* sqvm)
+ {
+ return __sq_newtable(sqvm);
+ }
+
+ inline SQRESULT newslot(HSquirrelVM* sqvm, SQInteger idx, SQBool bStatic)
+ {
+ return __sq_newslot(sqvm, idx, bStatic);
+ }
+
+ inline void pushroottable(HSquirrelVM* sqvm)
+ {
+ __sq_pushroottable(sqvm);
+ }
+
+ inline void pushstring(HSquirrelVM* sqvm, const SQChar* sVal, int length = -1)
+ {
+ __sq_pushstring(sqvm, sVal, length);
+ }
+
+ inline void pushinteger(HSquirrelVM* sqvm, const SQInteger iVal)
+ {
+ __sq_pushinteger(sqvm, iVal);
+ }
+
+ inline void pushfloat(HSquirrelVM* sqvm, const SQFloat flVal)
+ {
+ __sq_pushfloat(sqvm, flVal);
+ }
+
+ inline void pushbool(HSquirrelVM* sqvm, const SQBool bVal)
+ {
+ __sq_pushbool(sqvm, bVal);
+ }
+
+ inline void pushasset(HSquirrelVM* sqvm, const SQChar* sVal, int length = -1)
+ {
+ __sq_pushasset(sqvm, sVal, length);
+ }
+
+ inline void pushvector(HSquirrelVM* sqvm, const Vector3 pVal)
+ {
+ __sq_pushvector(sqvm, *(float**)&pVal);
+ }
+
+ inline const SQChar* getstring(HSquirrelVM* sqvm, const SQInteger stackpos)
+ {
+ return __sq_getstring(sqvm, stackpos);
+ }
+
+ inline SQInteger getinteger(HSquirrelVM* sqvm, const SQInteger stackpos)
+ {
+ return __sq_getinteger(sqvm, stackpos);
+ }
+
+ inline SQFloat getfloat(HSquirrelVM* sqvm, const SQInteger stackpos)
+ {
+ return __sq_getfloat(sqvm, stackpos);
+ }
+
+ inline SQBool getbool(HSquirrelVM* sqvm, const SQInteger stackpos)
+ {
+ return __sq_getbool(sqvm, stackpos);
+ }
+
+ inline SQRESULT get(HSquirrelVM* sqvm, const SQInteger stackpos)
+ {
+ return __sq_get(sqvm, stackpos);
+ }
+
+ inline Vector3 getvector(HSquirrelVM* sqvm, const SQInteger stackpos)
+ {
+ float* pRet = __sq_getvector(sqvm, stackpos);
+ return *(Vector3*)&pRet;
+ }
+
+ inline SQRESULT getasset(HSquirrelVM* sqvm, const SQInteger stackpos, const char** result)
+ {
+ return __sq_getasset(sqvm, stackpos, result);
+ }
+
+ template <typename T> inline SQRESULT getuserdata(HSquirrelVM* sqvm, const SQInteger stackpos, T* data, uint64_t* typeId)
+ {
+ return __sq_getuserdata(sqvm, stackpos, (void**)data, typeId); // this sometimes crashes idk
+ }
+
+ template <typename T> inline T* createuserdata(HSquirrelVM* sqvm, SQInteger size)
+ {
+ void* ret = __sq_createuserdata(sqvm, size);
+ memset(ret, 0, size);
+ return (T*)ret;
+ }
+
+ inline SQRESULT setuserdatatypeid(HSquirrelVM* sqvm, const SQInteger stackpos, uint64_t typeId)
+ {
+ return __sq_setuserdatatypeid(sqvm, stackpos, typeId);
+ }
+#pragma endregion
+};
+
+template <ScriptContext context> SquirrelManager<context>* g_pSquirrel;
diff --git a/NorthstarDLL/squirreldatatypes.h b/NorthstarDLL/squirreldatatypes.h
new file mode 100644
index 00000000..818ce2a4
--- /dev/null
+++ b/NorthstarDLL/squirreldatatypes.h
@@ -0,0 +1,484 @@
+#pragma once
+/*
+ This file has been generated by IDA.
+ It contains local type definitions from
+ the type library 'server.dll'
+*/
+
+struct HSquirrelVM;
+struct CallInfo;
+struct SQTable;
+struct SQString;
+struct SQFunctionProto;
+struct SQClosure;
+struct SQSharedState;
+struct StringTable;
+struct SQStructInstance;
+struct SQStructDef;
+struct SQNativeClosure;
+struct SQArray;
+struct tableNode;
+struct SQUserData;
+
+typedef void (*releasehookType)(void* val, int size);
+
+/* 127 */
+enum SQObjectType : int
+{
+ _RT_NULL = 0x1,
+ _RT_INTEGER = 0x2,
+ _RT_FLOAT = 0x4,
+ _RT_BOOL = 0x8,
+ _RT_STRING = 0x10,
+ _RT_TABLE = 0x20,
+ _RT_ARRAY = 0x40,
+ _RT_USERDATA = 0x80,
+ _RT_CLOSURE = 0x100,
+ _RT_NATIVECLOSURE = 0x200,
+ _RT_GENERATOR = 0x400,
+ OT_USERPOINTER = 0x800,
+ _RT_USERPOINTER = 0x800,
+ _RT_THREAD = 0x1000,
+ _RT_FUNCPROTO = 0x2000,
+ _RT_CLASS = 0x4000,
+ _RT_INSTANCE = 0x8000,
+ _RT_WEAKREF = 0x10000,
+ OT_VECTOR = 0x40000,
+ SQOBJECT_CANBEFALSE = 0x1000000,
+ OT_NULL = 0x1000001,
+ OT_BOOL = 0x1000008,
+ SQOBJECT_DELEGABLE = 0x2000000,
+ SQOBJECT_NUMERIC = 0x4000000,
+ OT_INTEGER = 0x5000002,
+ OT_FLOAT = 0x5000004,
+ SQOBJECT_REF_COUNTED = 0x8000000,
+ OT_STRING = 0x8000010,
+ OT_ARRAY = 0x8000040,
+ OT_CLOSURE = 0x8000100,
+ OT_NATIVECLOSURE = 0x8000200,
+ OT_ASSET = 0x8000400,
+ OT_THREAD = 0x8001000,
+ OT_FUNCPROTO = 0x8002000,
+ OT_CLAAS = 0x8004000,
+ OT_STRUCT = 0x8200000,
+ OT_WEAKREF = 0x8010000,
+ OT_TABLE = 0xA000020,
+ OT_USERDATA = 0xA000080,
+ OT_INSTANCE = 0xA008000,
+ OT_ENTITY = 0xA400000,
+};
+
+/* 156 */
+union SQObjectValue
+{
+ SQString* asString;
+ SQTable* asTable;
+ SQClosure* asClosure;
+ SQFunctionProto* asFuncProto;
+ SQStructDef* asStructDef;
+ long long as64Integer;
+ SQNativeClosure* asNativeClosure;
+ SQArray* asArray;
+ HSquirrelVM* asThread;
+ float asFloat;
+ int asInteger;
+ SQUserData* asUserdata;
+};
+
+/* 160 */
+struct SQVector
+{
+ SQObjectType _Type;
+ float x;
+ float y;
+ float z;
+};
+
+/* 128 */
+struct SQObject
+{
+ SQObjectType _Type;
+ int structNumber;
+ SQObjectValue _VAL;
+};
+
+/* 138 */
+struct alignas(8) SQString
+{
+ void* vftable;
+ int uiRef;
+ int padding;
+ SQString* _next_maybe;
+ SQSharedState* sharedState;
+ int length;
+ unsigned char gap_24[4];
+ char _hash[8];
+ char _val[1];
+};
+
+/* 137 */
+struct alignas(8) SQTable
+{
+ void* vftable;
+ unsigned char gap_08[4];
+ int uiRef;
+ unsigned char gap_10[8];
+ void* pointer_18;
+ void* pointer_20;
+ void* _sharedState;
+ long long field_30;
+ tableNode* _nodes;
+ int _numOfNodes;
+ int size;
+ int field_48;
+ int _usedNodes;
+ unsigned char _gap_50[20];
+ int field_64;
+ unsigned char _gap_68[80];
+};
+
+/* 140 */
+struct alignas(8) SQClosure
+{
+ void* vftable;
+ unsigned char gap_08[4];
+ int uiRef;
+ void* pointer_10;
+ void* pointer_18;
+ void* pointer_20;
+ void* sharedState;
+ SQObject obj_30;
+ SQObject _function;
+ SQObject* _outervalues;
+ unsigned char gap_58[8];
+ unsigned char gap_60[96];
+ SQObject* objectPointer_C0;
+ unsigned char gap_C8[16];
+};
+
+/* 139 */
+struct alignas(8) SQFunctionProto
+{
+ void* vftable;
+ unsigned char gap_08[4];
+ int uiRef;
+ unsigned char gap_10[8];
+ void* pointer_18;
+ void* pointer_20;
+ void* sharedState;
+ void* pointer_30;
+ SQObjectType _fileNameType;
+ SQString* _fileName;
+ SQObjectType _funcNameType;
+ SQString* _funcName;
+ SQObject obj_58;
+ unsigned char gap_68[12];
+ int _stacksize;
+ unsigned char gap_78[48];
+ int nParameters;
+ unsigned char gap_AC[60];
+ int nDefaultParams;
+ unsigned char gap_EC[200];
+};
+
+/* 152 */
+struct SQStructDef
+{
+ void* vtable;
+ int uiRef;
+ unsigned char padding_C[4];
+ unsigned char unknown[24];
+ SQSharedState* sharedState;
+ SQObjectType _nameType;
+ SQString* _name;
+ unsigned char gap_38[16];
+ SQObjectType _variableNamesType;
+ SQTable* _variableNames;
+ unsigned char gap_[32];
+};
+
+/* 157 */
+struct alignas(8) SQNativeClosure
+{
+ void* vftable;
+ int uiRef;
+ unsigned char gap_C[4];
+ long long value_10;
+ long long value_18;
+ long long value_20;
+ SQSharedState* sharedState;
+ char unknown_30;
+ unsigned char padding_34[7];
+ long long value_38;
+ long long value_40;
+ long long value_48;
+ long long value_50;
+ long long value_58;
+ SQObjectType _nameType;
+ SQString* _name;
+ long long value_70;
+ long long value_78;
+ unsigned char justInCaseGap_80[300];
+};
+
+/* 162 */
+struct SQArray
+{
+ void* vftable;
+ int uiRef;
+ unsigned char gap_24[36];
+ SQObject* _values;
+ int _usedSlots;
+ int _allocated;
+};
+
+/* 129 */
+struct alignas(8) HSquirrelVM
+{
+ void* vftable;
+ int uiRef;
+ unsigned char gap_8[12];
+ void* _toString;
+ void* _roottable_pointer;
+ void* pointer_28;
+ CallInfo* ci;
+ CallInfo* _callstack;
+ int _callsstacksize;
+ int _stackbase;
+ SQObject* _stackOfCurrentFunction;
+ SQSharedState* sharedState;
+ void* pointer_58;
+ void* pointer_60;
+ int _top;
+ SQObject* _stack;
+ unsigned char gap_78[8];
+ SQObject* _vargvstack;
+ unsigned char gap_88[8];
+ SQObject temp_reg;
+ unsigned char gapA0[8];
+ void* pointer_A8;
+ unsigned char gap_B0[8];
+ SQObject _roottable_object;
+ SQObject _lasterror;
+ SQObject _errorHandler;
+ long long field_E8;
+ int traps;
+ unsigned char gap_F4[12];
+ int _nnativecalls;
+ int _suspended;
+ int _suspended_root;
+ int _callstacksize;
+ int _suspended_target;
+ int trapAmount;
+ int _suspend_varargs;
+ int unknown_field_11C;
+ SQObject object_120;
+};
+
+/* 150 */
+struct SQStructInstance
+{
+ void* vftable;
+ unsigned char gap_8[16];
+ void* pointer_18;
+ unsigned char gap_20[8];
+ SQSharedState* _sharedState;
+ unsigned char gap[8];
+ SQObject data[20];
+};
+
+/* 148 */
+struct SQSharedState
+{
+ unsigned char gap_0[72];
+ void* unknown;
+ unsigned char gap_50[16344];
+ SQObjectType _unknownTableType00;
+ long long _unknownTableValue00;
+ unsigned char gap_4038[16];
+ StringTable* _stringTable;
+ unsigned char gap_4050[32];
+ SQObjectType _unknownTableType0;
+ long long _unknownTableValue0;
+ SQObjectType _unknownObjectType1;
+ long long _unknownObjectValue1;
+ unsigned char gap_4090[8];
+ SQObjectType _unknownArrayType2;
+ long long _unknownArrayValue2;
+ SQObjectType _gobalsArrayType;
+ SQStructInstance* _globalsArray;
+ unsigned char gap_40B8[16];
+ SQObjectType _nativeClosuresType;
+ SQTable* _nativeClosures;
+ SQObjectType _typedConstantsType;
+ SQTable* _typedConstants;
+ SQObjectType _untypedConstantsType;
+ SQTable* _untypedConstants;
+ SQObjectType _globalsMaybeType;
+ SQTable* _globals;
+ SQObjectType _functionsType;
+ SQTable* _functions;
+ SQObjectType _structsType;
+ SQTable* _structs;
+ SQObjectType _typeDefsType;
+ SQTable* _typeDefs;
+ SQObjectType unknownTableType;
+ SQTable* unknownTable;
+ SQObjectType _squirrelFilesType;
+ SQTable* _squirrelFiles;
+ unsigned char gap_4158[80];
+ SQObjectType _nativeClosures2Type;
+ SQTable* _nativeClosures2;
+ SQObjectType _entityTypesMaybeType;
+ SQTable* _entityTypesMaybe;
+ SQObjectType unknownTable2Type;
+ SQTable* unknownTable2;
+ unsigned char gap_41D8[72];
+ SQObjectType _compilerKeywordsType;
+ SQTable* _compilerKeywords;
+ HSquirrelVM* _currentThreadMaybe;
+ unsigned char gap_4238[8];
+ SQObjectType unknownTable3Type;
+ SQTable* unknownTable3;
+ unsigned char gap_4250[16];
+ SQObjectType unknownThreadType;
+ SQTable* unknownThread;
+ SQObjectType _tableNativeFunctionsType;
+ SQTable* _tableNativeFunctions;
+ SQObjectType _unknownTableType4;
+ long long _unknownObjectValue4;
+ SQObjectType _unknownObjectType5;
+ long long _unknownObjectValue5;
+ SQObjectType _unknownObjectType6;
+ long long _unknownObjectValue6;
+ SQObjectType _unknownObjectType7;
+ long long _unknownObjectValue7;
+ SQObjectType _unknownObjectType8;
+ long long _unknownObjectValue8;
+ SQObjectType _unknownObjectType9;
+ long long _unknownObjectValue9;
+ SQObjectType _unknownObjectType10;
+ long long _unknownObjectValue10;
+ SQObjectType _unknownObjectType11;
+ long long _unknownObjectValue11;
+ SQObjectType _unknownObjectType12;
+ long long _unknownObjectValue12;
+ SQObjectType _unknownObjectType13;
+ long long _unknownObjectValue13;
+ SQObjectType _unknownObjectType14;
+ long long _unknownObjectValue14;
+ SQObjectType _unknownObjectType15;
+ long long _unknownObjectValue15;
+ unsigned char gap_4340[16];
+ void* printFunction;
+ unsigned char gap_4358[16];
+ void* logEntityFunction;
+ unsigned char gap_4370[40];
+ SQObjectType _waitStringType;
+ SQString* _waitStringValue;
+ SQObjectType _SpinOffAndWaitForStringType;
+ SQString* _SpinOffAndWaitForStringValue;
+ SQObjectType _SpinOffAndWaitForSoloStringType;
+ SQString* _SpinOffAndWaitForSoloStringValue;
+ SQObjectType _SpinOffStringType;
+ SQString* _SpinOffStringValue;
+ SQObjectType _SpinOffDelayedStringType;
+ SQString* _SpinOffDelayedStringValue;
+ unsigned char gap_43E8[8];
+ bool enableDebugInfo; // functionality stripped
+ unsigned char gap_43F1[23];
+};
+
+/* 165 */
+struct tableNode
+{
+ SQObject val;
+ SQObject key;
+ tableNode* next;
+};
+
+/* 136 */
+struct alignas(8) CallInfo
+{
+ long long ip;
+ SQObject* _literals;
+ SQObject obj10;
+ SQObject closure;
+ int _etraps[4];
+ int _root;
+ short _vargs_size;
+ short _vargs_base;
+ unsigned char gap[16];
+};
+
+/* 149 */
+struct StringTable
+{
+ unsigned char gap_0[12];
+ int _numofslots;
+ unsigned char gap_10[200];
+};
+
+/* 141 */
+struct alignas(8) SQStackInfos
+{
+ char* _name;
+ char* _sourceName;
+ int _line;
+};
+
+/* 151 */
+struct alignas(4) SQInstruction
+{
+ int op;
+ int arg1;
+ int output;
+ short arg2;
+ short arg3;
+};
+
+/* 154 */
+struct SQLexer
+{
+ unsigned char gap_0[112];
+};
+
+/* 153 */
+struct SQCompiler
+{
+ unsigned char gap_0[4];
+ int _token;
+ unsigned char gap_8[8];
+ SQObject object_10;
+ SQLexer lexer;
+ unsigned char gap_90[752];
+ HSquirrelVM* sqvm;
+ unsigned char gap_288[8];
+};
+
+/* 155 */
+struct CSquirrelVM
+{
+ unsigned char gap_0[8];
+ HSquirrelVM* sqvm;
+ unsigned char gap_10[44];
+ int loadEnumFromFileMaybe;
+ unsigned char gap_40[200];
+};
+
+struct SQUserData
+{
+ void* vftable;
+ int uiRef;
+ char gap_12[4];
+ long long unknown_10;
+ long long unknown_18;
+ long long unknown_20;
+ long long sharedState;
+ long long unknown_30;
+ int size;
+ char padding1[4];
+ releasehookType releaseHook;
+ long long typeId;
+ char data[1];
+};
diff --git a/NorthstarDLL/tier0.cpp b/NorthstarDLL/tier0.cpp
new file mode 100644
index 00000000..61ad7783
--- /dev/null
+++ b/NorthstarDLL/tier0.cpp
@@ -0,0 +1,37 @@
+#include "pch.h"
+#include "tier0.h"
+
+// use the Tier0 namespace for tier0 funcs
+namespace Tier0
+{
+ IMemAlloc* g_pMemAllocSingleton;
+
+ ErrorType Error;
+ CommandLineType CommandLine;
+ Plat_FloatTimeType Plat_FloatTime;
+ ThreadInServerFrameThreadType ThreadInServerFrameThread;
+} // namespace Tier0
+
+typedef Tier0::IMemAlloc* (*CreateGlobalMemAllocType)();
+CreateGlobalMemAllocType CreateGlobalMemAlloc;
+
+// needs to be a seperate function, since memalloc.cpp calls it
+void TryCreateGlobalMemAlloc()
+{
+ // init memalloc stuff
+ CreateGlobalMemAlloc =
+ reinterpret_cast<CreateGlobalMemAllocType>(GetProcAddress(GetModuleHandleA("tier0.dll"), "CreateGlobalMemAlloc"));
+ Tier0::g_pMemAllocSingleton = CreateGlobalMemAlloc(); // if it already exists, this returns the preexisting IMemAlloc instance
+}
+
+ON_DLL_LOAD("tier0.dll", Tier0GameFuncs, (CModule module))
+{
+ // shouldn't be necessary, but do this just in case
+ TryCreateGlobalMemAlloc();
+
+ // setup tier0 funcs
+ Tier0::Error = module.GetExport("Error").As<Tier0::ErrorType>();
+ Tier0::CommandLine = module.GetExport("CommandLine").As<Tier0::CommandLineType>();
+ Tier0::Plat_FloatTime = module.GetExport("Plat_FloatTime").As<Tier0::Plat_FloatTimeType>();
+ Tier0::ThreadInServerFrameThread = module.GetExport("ThreadInServerFrameThread").As<Tier0::ThreadInServerFrameThreadType>();
+}
diff --git a/NorthstarDLL/tier0.h b/NorthstarDLL/tier0.h
new file mode 100644
index 00000000..92a63027
--- /dev/null
+++ b/NorthstarDLL/tier0.h
@@ -0,0 +1,68 @@
+#pragma once
+namespace Tier0
+{
+ class IMemAlloc
+ {
+ public:
+ struct VTable
+ {
+ void* unknown[1]; // alloc debug
+ void* (*Alloc)(IMemAlloc* memAlloc, size_t nSize);
+ void* unknown2[1]; // realloc debug
+ void* (*Realloc)(IMemAlloc* memAlloc, void* pMem, size_t nSize);
+ void* unknown3[1]; // free #1
+ void (*Free)(IMemAlloc* memAlloc, void* pMem);
+ void* unknown4[2]; // nullsubs, maybe CrtSetDbgFlag
+ size_t (*GetSize)(IMemAlloc* memAlloc, void* pMem);
+ void* unknown5[9]; // they all do literally nothing
+ void (*DumpStats)(IMemAlloc* memAlloc);
+ void (*DumpStatsFileBase)(IMemAlloc* memAlloc, const char* pchFileBase);
+ void* unknown6[4];
+ int (*heapchk)(IMemAlloc* memAlloc);
+ };
+
+ VTable* m_vtable;
+ };
+
+ class CCommandLine
+ {
+ public:
+ // based on the defs in the 2013 source sdk, but for some reason has an extra function (may be another CreateCmdLine overload?)
+ // these seem to line up with what they should be though
+ virtual void CreateCmdLine(const char* commandline) {}
+ virtual void CreateCmdLine(int argc, char** argv) {}
+ virtual void unknown() {}
+ virtual const char* GetCmdLine(void) const {}
+
+ virtual const char* CheckParm(const char* psz, const char** ppszValue = 0) const {}
+ virtual void RemoveParm() const {}
+ virtual void AppendParm(const char* pszParm, const char* pszValues) {}
+
+ virtual const char* ParmValue(const char* psz, const char* pDefaultVal = 0) const {}
+ virtual int ParmValue(const char* psz, int nDefaultVal) const {}
+ virtual float ParmValue(const char* psz, float flDefaultVal) const {}
+
+ virtual int ParmCount() const {}
+ virtual int FindParm(const char* psz) const {}
+ virtual const char* GetParm(int nIndex) const {}
+ virtual void SetParm(int nIndex, char const* pParm) {}
+
+ // virtual const char** GetParms() const {}
+ };
+
+ extern IMemAlloc* g_pMemAllocSingleton;
+
+ typedef void (*ErrorType)(const char* fmt, ...);
+ extern ErrorType Error;
+
+ typedef CCommandLine* (*CommandLineType)();
+ extern CommandLineType CommandLine;
+
+ typedef double (*Plat_FloatTimeType)();
+ extern Plat_FloatTimeType Plat_FloatTime;
+
+ typedef bool (*ThreadInServerFrameThreadType)();
+ extern ThreadInServerFrameThreadType ThreadInServerFrameThread;
+} // namespace Tier0
+
+void TryCreateGlobalMemAlloc();
diff --git a/NorthstarDLL/vector.h b/NorthstarDLL/vector.h
new file mode 100644
index 00000000..c06e0bba
--- /dev/null
+++ b/NorthstarDLL/vector.h
@@ -0,0 +1,52 @@
+#pragma once
+
+union Vector3
+{
+ struct
+ {
+ float x;
+ float y;
+ float z;
+ };
+
+ float raw[3];
+
+ Vector3() : x(0), y(0), z(0) {}
+ Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
+ Vector3(float* pRawFloats) // assumes float[3] => vector
+ {
+ memcpy(raw, pRawFloats, sizeof(this));
+ }
+
+ void MakeValid()
+ {
+ for (auto& fl : raw)
+ if (isnan(fl))
+ fl = 0;
+ }
+
+ // todo: more operators maybe
+ bool operator==(const Vector3& other)
+ {
+ return x == other.x && y == other.y && z == other.z;
+ }
+};
+
+union QAngle
+{
+ struct
+ {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ float raw[4];
+
+ // todo: more operators maybe
+ bool operator==(const QAngle& other)
+ {
+ return x == other.x && y == other.y && z == other.z && w == other.w;
+ }
+};
diff --git a/NorthstarDedicatedTest/version.cpp b/NorthstarDLL/version.cpp
index 3755e4c4..3755e4c4 100644
--- a/NorthstarDedicatedTest/version.cpp
+++ b/NorthstarDLL/version.cpp
diff --git a/NorthstarDedicatedTest/version.h b/NorthstarDLL/version.h
index d9d29fec..261a4cf1 100644
--- a/NorthstarDedicatedTest/version.h
+++ b/NorthstarDLL/version.h
@@ -3,4 +3,4 @@
extern char version[16];
extern char NSUserAgent[32];
-void InitialiseVersion(); \ No newline at end of file
+void InitialiseVersion();
diff --git a/NorthstarDedicatedTest/ExploitFixes.cpp b/NorthstarDedicatedTest/ExploitFixes.cpp
deleted file mode 100644
index db754ad5..00000000
--- a/NorthstarDedicatedTest/ExploitFixes.cpp
+++ /dev/null
@@ -1,419 +0,0 @@
-#include "pch.h"
-
-#include "ExploitFixes.h"
-#include "ExploitFixes_UTF8Parser.h"
-#include "NSMem.h"
-#include "cvar.h"
-
-ConVar* ns_exploitfixes_log;
-#define SHOULD_LOG (ns_exploitfixes_log->m_Value.m_nValue > 0)
-#define BLOCKED_INFO(s) \
- ( \
- [=]() -> bool \
- { \
- if (SHOULD_LOG) \
- { \
- std::stringstream stream; \
- stream << "ExploitFixes.cpp: " << BLOCK_PREFIX << s; \
- spdlog::error(stream.str()); \
- } \
- return false; \
- }())
-
-// Make sure 3 or less floats are valid
-bool ValidateFloats(float a, float b = 0, float c = 0)
-{
- return !isnan(a) && !isnan(b) && !isnan(c);
-}
-
-struct Vector
-{
- float x, y, z;
-
- Vector(float x = 0, float y = 0, float z = 0) : x(x), y(y), z(z) {}
-
- bool IsValid()
- {
- return ValidateFloats(x, y, z);
- }
-};
-
-struct Angle
-{
- float pitch, yaw, roll;
-
- Angle(float pitch = 0, float yaw = 0, float roll = 0) : pitch(pitch), yaw(yaw), roll(roll) {}
-
- bool IsInvalid()
- {
- if (!ValidateFloats(pitch, yaw, roll))
- return false;
-
- return (pitch > 90 || pitch < -90) || (yaw > 180 || yaw < -180) || (roll > 180 || roll < -180);
- }
-};
-
-#define BLOCK_NETMSG_FUNC(name, pattern) \
- KHOOK(name, ("engine.dll", pattern), bool, __fastcall, (void* thisptr, void* buffer)) \
- { \
- return false; \
- }
-
-// Servers can literally request a screenshot from any client, yeah no
-BLOCK_NETMSG_FUNC(CLC_Screenshot_WriteToBuffer, "48 89 5C 24 ? 57 48 83 EC 20 8B 42 10");
-BLOCK_NETMSG_FUNC(CLC_Screenshot_ReadFromBuffer, "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B DA 48 8B 52 38");
-
-// This is unused ingame and a big exploit vector
-BLOCK_NETMSG_FUNC(Base_CmdKeyValues_ReadFromBuffer, "40 55 48 81 EC ? ? ? ? 48 8D 6C 24 ? 48 89 5D 70");
-
-KHOOK(CClient_ProcessSetConVar, ("engine.dll", "48 8B D1 48 8B 49 18 48 8B 01 48 FF 60 10"), bool, __fastcall, (void* pMsg))
-{
-
- constexpr int ENTRY_STR_LEN = 260;
- struct SetConVarEntry
- {
- char name[ENTRY_STR_LEN];
- char val[ENTRY_STR_LEN];
- };
-
- struct NET_SetConVar
- {
- void* vtable;
- void* unk1;
- void* unk2;
- void* m_pMessageHandler;
- SetConVarEntry* m_ConVars; // convar entry array
- void* unk5; // these 2 unks are just vector capacity or whatever
- void* unk6;
- int m_ConVars_count; // amount of cvar entries in array (this will not be out of bounds)
- };
-
- auto msg = (NET_SetConVar*)pMsg;
-
- bool areWeServer;
-
- {
- // Figure out of we are the client or the server
- // To do this, we utilize the msg's m_pMessageHandler pointer
- // m_pMessageHandler points to a virtual class that handles all net messages
- // The first virtual table function of our m_pMessageHandler will differ if it is IServerMessageHandler or IClientMessageHandler
- void* msgHandlerVTableFirstFunc = **(void****)(msg->m_pMessageHandler);
- static auto engineBaseAddress = (uintptr_t)GetModuleHandleA("engine.dll");
- auto offset = uintptr_t(msgHandlerVTableFirstFunc) - engineBaseAddress;
-
- constexpr uintptr_t CLIENTSTATE_FIRST_VFUNC_OFFSET = 0x8A15C;
- areWeServer = offset != CLIENTSTATE_FIRST_VFUNC_OFFSET;
- }
-
- std::string BLOCK_PREFIX = std::string {"NET_SetConVar ("} + (areWeServer ? "server" : "client") + "): Blocked dangerous/invalid msg: ";
-
- if (areWeServer)
- {
- constexpr int SETCONVAR_SANITY_AMOUNT_LIMIT = 69;
- if (msg->m_ConVars_count < 1 || msg->m_ConVars_count > SETCONVAR_SANITY_AMOUNT_LIMIT)
- {
- return BLOCKED_INFO("Invalid m_ConVars_count (" << msg->m_ConVars_count << ")");
- }
- }
-
- for (int i = 0; i < msg->m_ConVars_count; i++)
- {
- auto entry = msg->m_ConVars + i;
-
- // Safety check for memory access
- if (NSMem::IsMemoryReadable(entry, sizeof(*entry)))
- {
-
- // Find null terminators
- bool nameValid = false, valValid = false;
- for (int i = 0; i < ENTRY_STR_LEN; i++)
- {
- if (!entry->name[i])
- nameValid = true;
- if (!entry->val[i])
- valValid = true;
- }
-
- if (!nameValid || !valValid)
- return BLOCKED_INFO("Missing null terminators");
-
- auto realVar = g_pCVar->FindVar(entry->name);
-
- if (realVar)
- memcpy(
- entry->name,
- realVar->m_ConCommandBase.m_pszName,
- strlen(realVar->m_ConCommandBase.m_pszName) + 1); // Force name to match case
-
- bool isValidFlags = true;
- if (areWeServer)
- {
- if (realVar)
- isValidFlags = ConVar::IsFlagSet(realVar, FCVAR_USERINFO); // ConVar MUST be userinfo var
- }
- else
- {
- // TODO: Should probably have some sanity checks, but can't find any that are consistent
- }
-
- if (!isValidFlags)
- {
- if (!realVar)
- {
- return BLOCKED_INFO("Invalid flags on nonexistant cvar (how tho???)");
- }
- else
- {
- return BLOCKED_INFO(
- "Invalid flags (" << std::hex << "0x" << realVar->m_ConCommandBase.m_nFlags << "), var is " << entry->name);
- }
- }
- }
- else
- {
- return BLOCKED_INFO("Unreadable memory at " << (void*)entry); // Not risking that one, they all gotta be readable
- }
- }
-
- return oCClient_ProcessSetConVar(msg);
-}
-
-// Purpose: prevent invalid user CMDs
-KHOOK(CClient_ProcessUsercmds, ("engine.dll", "40 55 56 48 83 EC 58"), bool, __fastcall, (void* thisptr, void* pMsg))
-{
- struct CLC_Move
- {
- BYTE gap0[24];
- void* m_pMessageHandler;
- int m_nBackupCommands;
- int m_nNewCommands;
- int m_nLength;
- // bf_read m_DataIn;
- // bf_write m_DataOut;
- };
-
- auto msg = (CLC_Move*)pMsg;
-
- const char* BLOCK_PREFIX = "ProcessUserCmds: ";
-
- if (msg->m_nBackupCommands < 0)
- {
- return BLOCKED_INFO("Invalid m_nBackupCommands (" << msg->m_nBackupCommands << ")");
- }
-
- if (msg->m_nNewCommands < 0)
- {
- return BLOCKED_INFO("Invalid m_nNewCommands (" << msg->m_nNewCommands << ")");
- }
-
- constexpr int NUMCMD_SANITY_LIMIT = 16;
- if ((msg->m_nNewCommands + msg->m_nBackupCommands) > NUMCMD_SANITY_LIMIT)
- {
- return BLOCKED_INFO("Command count is too high (new: " << msg->m_nNewCommands << ", backup: " << msg->m_nBackupCommands << ")");
- }
-
- if (msg->m_nLength <= 0)
- return BLOCKED_INFO("Invalid message length (" << msg->m_nLength << ")");
-
- return oCClient_ProcessUsercmds(thisptr, pMsg);
-}
-
-KHOOK(ReadUsercmd, ("server.dll", "4C 89 44 24 ? 53 55 56 57"), void, __fastcall, (void* buf, void* pCmd_move, void* pCmd_from))
-{
- // Let normal usercmd read happen first, it's safe
- oReadUsercmd(buf, pCmd_move, pCmd_from);
-
- // Now let's make sure the CMD we read isnt messed up to prevent numerous exploits (including server crashing)
- struct __declspec(align(4)) SV_CUserCmd
- {
- DWORD command_number;
- DWORD tick_count;
- float command_time;
- Angle worldViewAngles;
- BYTE gap18[4];
- Angle localViewAngles;
- Angle attackangles;
- Vector move;
- DWORD buttons;
- BYTE impulse;
- short weaponselect;
- DWORD meleetarget;
- BYTE gap4C[24];
- char headoffset;
- BYTE gap65[11];
- Vector cameraPos;
- Angle cameraAngles;
- BYTE gap88[4];
- int tickSomething;
- DWORD dword90;
- DWORD predictedServerEventAck;
- DWORD dword98;
- float frameTime;
- };
-
- auto cmd = (SV_CUserCmd*)pCmd_move;
- auto fromCmd = (SV_CUserCmd*)pCmd_from;
-
- std::string BLOCK_PREFIX =
- "ReadUsercmd (command_number delta: " + std::to_string(cmd->command_number - fromCmd->command_number) + "): ";
-
- if (cmd->worldViewAngles.IsInvalid())
- {
- BLOCKED_INFO("CMD has invalid worldViewAngles");
- goto INVALID_CMD;
- }
-
- if (cmd->attackangles.IsInvalid())
- {
- BLOCKED_INFO("CMD has invalid attackangles");
- goto INVALID_CMD;
- }
-
- if (cmd->localViewAngles.IsInvalid())
- {
- BLOCKED_INFO("CMD has invalid localViewAngles");
- goto INVALID_CMD;
- }
-
- if (cmd->cameraAngles.IsInvalid())
- {
- BLOCKED_INFO("CMD has invalid cameraAngles");
- goto INVALID_CMD;
- }
-
- if (cmd->frameTime <= 0 || cmd->tick_count == 0 || cmd->command_time <= 0)
- {
- BLOCKED_INFO(
- "Bogus cmd timing (tick_count: " << cmd->tick_count << ", frameTime: " << cmd->frameTime
- << ", commandTime : " << cmd->command_time << ")");
- goto INVALID_CMD; // No simulation of bogus-timed cmds
- }
-
- if (!cmd->move.IsValid())
- {
- BLOCKED_INFO("Invalid move vector");
- goto INVALID_CMD;
- }
-
- if (!cmd->cameraPos.IsValid())
- {
- BLOCKED_INFO("Invalid cameraPos"); // IIRC this can crash spectating clients or anyone watching replays
- goto INVALID_CMD;
- }
-
- return;
-INVALID_CMD:
-
- // Fix any gameplay-affecting cmd properties
- // NOTE: Currently tickcount/frametime is set to 0, this ~shouldn't~ cause any problems
- cmd->worldViewAngles = cmd->localViewAngles = cmd->attackangles = cmd->cameraAngles = Angle(0, 0, 0);
- cmd->tick_count = cmd->frameTime = 0;
- cmd->move = cmd->cameraPos = Vector(0, 0, 0);
- cmd->buttons = 0;
- cmd->meleetarget = 0;
-}
-
-// basically: by default r2 isn't set as a valve mod, meaning that m_bRestrictServerCommands is false
-// this is HORRIBLE for security, because it means servers can run arbitrary concommands on clients
-// especially since we have script commands this could theoretically be awful
-#include "gameutils.h"
-KHOOK(IsValveMod, ("engine.dll", "48 83 EC 28 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? E8 ? ? ? ? 85 C0 74 63"), bool, __fastcall, ())
-{
- return !CommandLine()->CheckParm("-norestrictservercommands");
-}
-
-// Fix respawn's crappy UTF8 parser so it doesn't crash -_-
-// This also means you can launch multiplayer with "communities_enabled 1" and not crash, you're welcome
-KHOOK(
- CrashFunc_ParseUTF8,
- ("engine.dll", "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 54 41 55 41 56 41 57 48 83 EC 20 8B 1A"),
- bool,
- __fastcall,
- (INT64 * a1, DWORD* a2, char* strData))
-{
-
- static void* targetRetAddr = NSMem::PatternScan("engine.dll", "84 C0 75 2C 49 8B 16");
-
- if (_ReturnAddress() == targetRetAddr)
- {
- if (!ExploitFixes_UTF8Parser::CheckValid(a1, a2, strData))
- {
- const char* BLOCK_PREFIX = "ParseUTF8 Hook: ";
- BLOCKED_INFO("Ignoring potentially-crashing utf8 string");
- return false;
- }
- }
-
- return oCrashFunc_ParseUTF8(a1, a2, strData);
-}
-
-//////////////////////////////////////////////////
-
-void DoBytePatches()
-{
- uintptr_t engineBase = (uintptr_t)GetModuleHandleA("engine.dll");
- uintptr_t serverBase = (uintptr_t)GetModuleHandleA("server.dll");
-
- // patches to make commands run from client/ui script still work
- // note: this is likely preventable in a nicer way? test prolly
- NSMem::BytePatch(engineBase + 0x4FB65, "EB 11");
- NSMem::BytePatch(engineBase + 0x4FBAC, "EB 16");
-
- // disconnect concommand
- {
- uintptr_t addr = engineBase + 0x5ADA2D;
- int val = *(int*)addr | FCVAR_SERVER_CAN_EXECUTE;
- NSMem::BytePatch(addr, (BYTE*)&val, sizeof(int));
- }
-
- { // Dumb ANTITAMPER patches (they negatively impact performance and security)
-
- constexpr const char* ANTITAMPER_EXPORTS[] = {
- "ANTITAMPER_SPOTCHECK_CODEMARKER",
- "ANTITAMPER_TESTVALUE_CODEMARKER",
- "ANTITAMPER_TRIGGER_CODEMARKER",
- };
-
- // Prevent thesefrom actually doing anything
- for (auto exportName : ANTITAMPER_EXPORTS)
- {
-
- auto address = (uintptr_t)GetProcAddress(GetModuleHandleA("server.dll"), exportName);
- if (!address)
- {
- spdlog::warn("Failed to find AntiTamper function export \"{}\"", exportName);
- }
- else
- {
- // Just return, none of them have any args or are userpurge
- NSMem::BytePatch(address, "C3");
-
- spdlog::info("Patched AntiTamper function export \"{}\"", exportName);
- }
- }
- }
-}
-
-void ExploitFixes::LoadCallback(HMODULE unused)
-{
- spdlog::info("ExploitFixes::LoadCallback ...");
-
- spdlog::info("\tByte patching...");
- DoBytePatches();
-
- if (KHook::InitAllHooks())
- {
- spdlog::info("\tInitialized " + std::to_string(KHook::_allHooks.size()) + " exploit-patch hooks.");
- }
- else
- {
- spdlog::critical("\tFAILED to initialize all exploit patches.");
-
- // Force exit?
- MessageBoxA(0, "FAILED to initialize all exploit patches.", "Northstar", MB_ICONERROR);
- exit(0);
- }
-
- ns_exploitfixes_log =
- new ConVar("ns_exploitfixes_log", "1", FCVAR_GAMEDLL, "Whether to log whenever ExploitFixes.cpp blocks/corrects something");
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/ExploitFixes.h b/NorthstarDedicatedTest/ExploitFixes.h
deleted file mode 100644
index 7a407a3d..00000000
--- a/NorthstarDedicatedTest/ExploitFixes.h
+++ /dev/null
@@ -1,9 +0,0 @@
-// KittenPopo's exploit fix hooks, feel free to add more here
-
-#pragma once
-#include "pch.h"
-
-namespace ExploitFixes
-{
- void LoadCallback(HMODULE unused);
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/ExploitFixes_UTF8Parser.h b/NorthstarDedicatedTest/ExploitFixes_UTF8Parser.h
deleted file mode 100644
index 41242655..00000000
--- a/NorthstarDedicatedTest/ExploitFixes_UTF8Parser.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Reimplementation of a exploitable UTF decoding function in titanfall
-
-#include "NSMem.h"
-
-#pragma once
-
-namespace ExploitFixes_UTF8Parser
-{
- bool __fastcall CheckValid(INT64* a1, DWORD* a2, char* strData)
- {
- static auto sub_F1320 = (INT64(__fastcall*)(DWORD a1, char* a2))NSMem::PatternScan("engine.dll", "83 F9 7F 77 08 88 0A");
-
- DWORD v3; // eax
- char* v4; // rbx
- char v5; // si
- char* _strData; // rdi
- char* v7; // rbp
- char v11; // al
- DWORD v12; // er9
- DWORD v13; // ecx
- DWORD v14; // edx
- DWORD v15; // er8
- int v16; // eax
- DWORD v17; // er9
- int v18; // eax
- DWORD v19; // er9
- DWORD v20; // ecx
- int v21; // eax
- int v22; // er9
- DWORD v23; // edx
- int v24; // eax
- int v25; // er9
- DWORD v26; // er9
- DWORD v27; // er10
- DWORD v28; // ecx
- DWORD v29; // edx
- DWORD v30; // er8
- int v31; // eax
- DWORD v32; // er10
- int v33; // eax
- DWORD v34; // er10
- DWORD v35; // ecx
- int v36; // eax
- int v37; // er10
- DWORD v38; // edx
- int v39; // eax
- int v40; // er10
- DWORD v41; // er10
- INT64 v43; // r8
- INT64 v44; // rdx
- INT64 v45; // rcx
- INT64 v46; // rax
- INT64 v47; // rax
- char v48; // al
- INT64 v49; // r8
- INT64 v50; // rdx
- INT64 v51; // rcx
- INT64 v52; // rax
- INT64 v53; // rax
-
- v3 = a2[2];
- v4 = (char*)(a1[1] + *a2);
- v5 = 0;
- _strData = strData;
- v7 = &v4[*((UINT16*)a2 + 2)];
- if (v3 >= 2)
- {
- ++v4;
- --v7;
- if (v3 != 2)
- {
- while (1)
- {
-
- if (!NSMem::IsMemoryReadable(v4, 1))
- return false; // INVALID
-
- v11 = *v4++; // crash potential
- if (v11 != 92)
- goto LABEL_6;
- v11 = *v4++;
- if (v11 == 110)
- break;
- switch (v11)
- {
- case 't':
- v11 = 9;
- goto LABEL_6;
- case 'r':
- v11 = 13;
- goto LABEL_6;
- case 'b':
- v11 = 8;
- goto LABEL_6;
- case 'f':
- v11 = 12;
- goto LABEL_6;
- }
- if (v11 != 117)
- goto LABEL_6;
- v12 = *v4 | 0x20;
- v13 = v4[1] | 0x20;
- v14 = v4[2] | 0x20;
- v15 = v4[3] | 0x20;
- v16 = 87;
- if (v12 <= 0x39)
- v16 = 48;
- v17 = v12 - v16;
- v18 = 87;
- v19 = v17 << 12;
- if (v13 <= 0x39)
- v18 = 48;
- v20 = v13 - v18;
- v21 = 87;
- v22 = (v20 << 8) | v19;
- if (v14 <= 0x39)
- v21 = 48;
- v23 = v14 - v21;
- v24 = 87;
- v25 = (16 * v23) | v22;
- if (v15 <= 0x39)
- v24 = 48;
- v4 += 4;
- v26 = (v15 - v24) | v25;
- if (v26 - 55296 <= 0x7FF)
- {
- if (v26 >= 0xDC00)
- return true;
- if (*v4 != 92 || v4[1] != 117)
- return true;
-
- v27 = v4[2] | 0x20;
- v28 = v4[3] | 0x20;
- v29 = v4[4] | 0x20;
- v30 = v4[5] | 0x20;
- v31 = 87;
- if (v27 <= 0x39)
- v31 = 48;
- v32 = v27 - v31;
- v33 = 87;
- v34 = v32 << 12;
- if (v28 <= 0x39)
- v33 = 48;
- v35 = v28 - v33;
- v36 = 87;
- v37 = (v35 << 8) | v34;
- if (v29 <= 0x39)
- v36 = 48;
- v38 = v29 - v36;
- v39 = 87;
- v40 = (16 * v38) | v37;
- if (v30 <= 0x39)
- v39 = 48;
- v4 += 6;
- v41 = ((v30 - v39) | v40) - 56320;
- if (v41 > 0x3FF)
- return true;
- v26 = v41 | ((v26 - 55296) << 10);
- }
- _strData += (DWORD)sub_F1320(v26, _strData);
- LABEL_7:
- if (v4 == v7)
- goto LABEL_48;
- }
- v11 = 10;
- LABEL_6:
- v5 |= v11;
- *_strData++ = v11;
- goto LABEL_7;
- }
- }
- LABEL_48:
- return true;
- }
-} // namespace ExploitFixes_UTF8Parser \ No newline at end of file
diff --git a/NorthstarDedicatedTest/NSMem.h b/NorthstarDedicatedTest/NSMem.h
deleted file mode 100644
index 74df3a84..00000000
--- a/NorthstarDedicatedTest/NSMem.h
+++ /dev/null
@@ -1,211 +0,0 @@
-#pragma once
-#include "pch.h"
-
-// KittenPopo's memory stuff, made for northstar (because I really can't handle working with northstar's original memory stuff tbh)
-
-#pragma region Pattern Scanning
-namespace NSMem
-{
- inline std::vector<int> HexBytesToString(const char* str)
- {
- std::vector<int> patternNums;
- int size = strlen(str);
- for (int i = 0; i < size; i++)
- {
- char c = str[i];
-
- // If this is a space character, ignore it
- if (c == ' ' || c == '\t')
- continue;
-
- if (c == '?')
- {
- // Add a wildcard (-1)
- patternNums.push_back(-1);
- }
- else if (i < size - 1)
- {
- BYTE result = 0;
- for (int j = 0; j < 2; j++)
- {
- int val = 0;
- char c = *(str + i + j);
- if (c >= 'a')
- {
- val = c - 'a' + 0xA;
- }
- else if (c >= 'A')
- {
- val = c - 'A' + 0xA;
- }
- else if (isdigit(c))
- {
- val = c - '0';
- }
- else
- {
- assert(false, "Failed to parse invalid hex string.");
- val = -1;
- }
-
- result += (j == 0) ? val * 16 : val;
- }
- patternNums.push_back(result);
- }
-
- i++;
- }
-
- return patternNums;
- }
-
- inline void* PatternScan(void* module, const int* pattern, int patternSize, int offset)
- {
- if (!module)
- return NULL;
-
- auto dosHeader = (PIMAGE_DOS_HEADER)module;
- auto ntHeaders = (PIMAGE_NT_HEADERS)((BYTE*)module + dosHeader->e_lfanew);
-
- auto sizeOfImage = ntHeaders->OptionalHeader.SizeOfImage;
-
- auto scanBytes = (BYTE*)module;
-
- for (auto i = 0; i < sizeOfImage - patternSize; ++i)
- {
- bool found = true;
- for (auto j = 0; j < patternSize; ++j)
- {
- if (scanBytes[i + j] != pattern[j] && pattern[j] != -1)
- {
- found = false;
- break;
- }
- }
-
- if (found)
- {
- uintptr_t addressInt = (uintptr_t)(&scanBytes[i]) + offset;
- return (uint8_t*)addressInt;
- }
- }
-
- return nullptr;
- }
-
- inline void* PatternScan(const char* moduleName, const char* pattern, int offset = 0)
- {
- std::vector<int> patternNums = HexBytesToString(pattern);
-
- return PatternScan(GetModuleHandleA(moduleName), &patternNums[0], patternNums.size(), offset);
- }
-
- inline void BytePatch(uintptr_t address, const BYTE* vals, int size)
- {
- WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, vals, size, NULL);
- }
-
- inline void BytePatch(uintptr_t address, std::initializer_list<BYTE> vals)
- {
- std::vector<BYTE> bytes = vals;
- if (!bytes.empty())
- BytePatch(address, &bytes[0], bytes.size());
- }
-
- inline void BytePatch(uintptr_t address, const char* bytesStr)
- {
- std::vector<int> byteInts = HexBytesToString(bytesStr);
- std::vector<BYTE> bytes;
- for (int v : byteInts)
- bytes.push_back(v);
-
- if (!bytes.empty())
- BytePatch(address, &bytes[0], bytes.size());
- }
-
- inline void NOP(uintptr_t address, int size)
- {
- BYTE* buf = (BYTE*)malloc(size);
- memset(buf, 0x90, size);
- BytePatch(address, buf, size);
- free(buf);
- }
-
- inline bool IsMemoryReadable(void* ptr, size_t size)
- {
- static SYSTEM_INFO sysInfo;
- if (!sysInfo.dwPageSize)
- GetSystemInfo(&sysInfo); // This should always be 4096 unless ur playing on NES or some shit but whatever
-
- MEMORY_BASIC_INFORMATION memInfo;
-
- if (!VirtualQuery(ptr, &memInfo, sizeof(memInfo)))
- return false;
-
- if (memInfo.RegionSize < size)
- return false;
-
- return (memInfo.State & MEM_COMMIT) && !(memInfo.Protect & PAGE_NOACCESS);
- }
-} // namespace NSMem
-
-#pragma region KHOOK
-struct KHookPatternInfo
-{
- const char *moduleName, *pattern;
- int offset = 0;
-
- KHookPatternInfo(const char* moduleName, const char* pattern, int offset = 0) : moduleName(moduleName), pattern(pattern), offset(offset)
- {
- }
-};
-
-struct KHook
-{
- KHookPatternInfo targetFunc;
- void* targetFuncAddr;
- void* hookFunc;
- void** original;
-
- static inline std::vector<KHook*> _allHooks;
-
- KHook(KHookPatternInfo targetFunc, void* hookFunc, void** original) : targetFunc(targetFunc)
- {
- this->hookFunc = hookFunc;
- this->original = original;
- _allHooks.push_back(this);
- }
-
- bool Setup()
- {
- targetFuncAddr = NSMem::PatternScan(targetFunc.moduleName, targetFunc.pattern, targetFunc.offset);
- if (!targetFuncAddr)
- return false;
-
- return MH_CreateHook(targetFuncAddr, hookFunc, original) == MH_OK;
- }
-
- // Returns true if succeeded
- static bool InitAllHooks()
- {
- for (KHook* hook : _allHooks)
- {
- if (hook->Setup())
- {
- spdlog::info("KHook hooked at {}", hook->targetFuncAddr);
- }
- else
- {
- return false;
- }
- }
-
- return MH_EnableHook(MH_ALL_HOOKS) == MH_OK;
- }
-};
-#define KHOOK(name, funcPatternInfo, returnType, convention, args) \
- returnType convention hk##name args; \
- auto o##name = (returnType(convention*) args)0; \
- KHook k##name = KHook(KHookPatternInfo funcPatternInfo, &hk##name, (void**)&o##name); \
- returnType convention hk##name args
-#pragma endregion \ No newline at end of file
diff --git a/NorthstarDedicatedTest/bansystem.cpp b/NorthstarDedicatedTest/bansystem.cpp
deleted file mode 100644
index 93cf9c65..00000000
--- a/NorthstarDedicatedTest/bansystem.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#pragma once
-#include "pch.h"
-#include "bansystem.h"
-#include "serverauthentication.h"
-#include "concommand.h"
-#include "miscserverscript.h"
-#include <filesystem>
-#include "configurables.h"
-
-const char* BANLIST_PATH_SUFFIX = "/banlist.txt";
-
-ServerBanSystem* g_ServerBanSystem;
-
-void ServerBanSystem::OpenBanlist()
-{
- std::ifstream enabledModsStream(GetNorthstarPrefix() + "/banlist.txt");
- std::stringstream enabledModsStringStream;
-
- if (!enabledModsStream.fail())
- {
- std::string line;
- while (std::getline(enabledModsStream, line))
- m_vBannedUids.push_back(strtoll(line.c_str(), nullptr, 10));
-
- enabledModsStream.close();
- }
-
- // open write stream for banlist
- m_sBanlistStream.open(GetNorthstarPrefix() + "/banlist.txt", std::ofstream::out | std::ofstream::binary | std::ofstream::app);
-}
-
-void ServerBanSystem::ClearBanlist()
-{
- m_vBannedUids.clear();
-
- // reopen the file, don't provide std::ofstream::app so it clears on open
- m_sBanlistStream.close();
- m_sBanlistStream.open(GetNorthstarPrefix() + "/banlist.txt", std::ofstream::out | std::ofstream::binary);
-}
-
-void ServerBanSystem::BanUID(uint64_t uid)
-{
- m_vBannedUids.push_back(uid);
- m_sBanlistStream << std::to_string(uid) << std::endl;
- spdlog::info("{} was banned", uid);
-}
-
-void ServerBanSystem::UnbanUID(uint64_t uid)
-{
- auto findResult = std::find(m_vBannedUids.begin(), m_vBannedUids.end(), uid);
- if (findResult == m_vBannedUids.end())
- return;
-
- m_vBannedUids.erase(findResult);
- spdlog::info("{} was unbanned", uid);
- // todo: this needs to erase from the banlist file
- // atm unsure how to do this aside from just clearing and fully rewriting the file
-}
-
-bool ServerBanSystem::IsUIDAllowed(uint64_t uid)
-{
- return std::find(m_vBannedUids.begin(), m_vBannedUids.end(), uid) == m_vBannedUids.end();
-}
-
-void BanPlayerCommand(const CCommand& args)
-{
- if (args.ArgC() < 2)
- return;
-
- // assuming maxplayers 32
- for (int i = 0; i < 32; i++)
- {
- void* player = GetPlayerByIndex(i);
-
- if (!strcmp((char*)player + 0x16, args.Arg(1)) || !strcmp((char*)player + 0xF500, args.Arg(1)))
- {
- g_ServerBanSystem->BanUID(strtoll((char*)player + 0xF500, nullptr, 10));
- CBaseClient__Disconnect(player, 1, "Banned from server");
- break;
- }
- }
-}
-
-void UnbanPlayerCommand(const CCommand& args)
-{
- if (args.ArgC() < 2)
- return;
-
- // assumedly the player being unbanned here wasn't already connected, so don't need to iterate over players or anything
- g_ServerBanSystem->UnbanUID(strtoll(args.Arg(1), nullptr, 10));
-}
-
-void ClearBanlistCommand(const CCommand& args)
-{
- g_ServerBanSystem->ClearBanlist();
-}
-
-void InitialiseBanSystem(HMODULE baseAddress)
-{
- g_ServerBanSystem = new ServerBanSystem;
- g_ServerBanSystem->OpenBanlist();
-
- RegisterConCommand("ban", BanPlayerCommand, "bans a given player by uid or name", FCVAR_GAMEDLL);
- RegisterConCommand("unban", UnbanPlayerCommand, "unbans a given player by uid", FCVAR_NONE);
- RegisterConCommand("clearbanlist", ClearBanlistCommand, "clears all uids on the banlist", FCVAR_NONE);
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/buildainfile.h b/NorthstarDedicatedTest/buildainfile.h
deleted file mode 100644
index a3c0e090..00000000
--- a/NorthstarDedicatedTest/buildainfile.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseBuildAINFileHooks(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/chatcommand.h b/NorthstarDedicatedTest/chatcommand.h
deleted file mode 100644
index 546d0126..00000000
--- a/NorthstarDedicatedTest/chatcommand.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseChatCommands(HMODULE baseAddress);
diff --git a/NorthstarDedicatedTest/clientauthhooks.h b/NorthstarDedicatedTest/clientauthhooks.h
deleted file mode 100644
index e40a68a5..00000000
--- a/NorthstarDedicatedTest/clientauthhooks.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void InitialiseClientAuthHooks(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/clientchathooks.cpp b/NorthstarDedicatedTest/clientchathooks.cpp
deleted file mode 100644
index 74418c06..00000000
--- a/NorthstarDedicatedTest/clientchathooks.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-#include "pch.h"
-#include "clientchathooks.h"
-#include <rapidjson/document.h>
-#include "squirrel.h"
-#include "serverchathooks.h"
-#include "localchatwriter.h"
-
-typedef void(__fastcall* CHudChat__AddGameLineType)(void* self, const char* message, int fromPlayerId, bool isteam, bool isdead);
-CHudChat__AddGameLineType CHudChat__AddGameLine;
-
-struct ChatTags
-{
- bool whisper;
- bool team;
- bool dead;
-};
-
-static void CHudChat__AddGameLineHook(void* self, const char* message, int inboxId, bool isTeam, bool isDead)
-{
- // This hook is called for each HUD, but we only want our logic to run once.
- if (self != *CHudChat::allHuds)
- {
- return;
- }
-
- if (g_ClientSquirrelManager->setupfunc("CHudChat_ProcessMessageStartThread") != SQRESULT_ERROR)
- {
- int senderId = inboxId & CUSTOM_MESSAGE_INDEX_MASK;
- bool isAnonymous = senderId == 0;
- bool isCustom = isAnonymous || (inboxId & CUSTOM_MESSAGE_INDEX_BIT);
-
- // Type is set to 0 for non-custom messages, custom messages have a type encoded as the first byte
- int type = 0;
- const char* payload = message;
- if (isCustom)
- {
- type = message[0];
- payload = message + 1;
- }
-
- g_ClientSquirrelManager->pusharg((int)senderId - 1);
- g_ClientSquirrelManager->pusharg(payload);
- g_ClientSquirrelManager->pusharg(isTeam);
- g_ClientSquirrelManager->pusharg(isDead);
- g_ClientSquirrelManager->pusharg(type);
- g_ClientSquirrelManager->call(5);
- }
- else
- {
- for (CHudChat* hud = *CHudChat::allHuds; hud != NULL; hud = hud->next)
- {
- CHudChat__AddGameLine(hud, message, inboxId, isTeam, isDead);
- }
- }
-}
-
-// void NSChatWrite( int context, string str )
-static SQRESULT SQ_ChatWrite(void* sqvm)
-{
- int context = ClientSq_getinteger(sqvm, 1);
- const char* str = ClientSq_getstring(sqvm, 2);
-
- LocalChatWriter((LocalChatWriter::Context)context).Write(str);
- return SQRESULT_NOTNULL;
-}
-
-// void NSChatWriteRaw( int context, string str )
-static SQRESULT SQ_ChatWriteRaw(void* sqvm)
-{
- int context = ClientSq_getinteger(sqvm, 1);
- const char* str = ClientSq_getstring(sqvm, 2);
-
- LocalChatWriter((LocalChatWriter::Context)context).InsertText(str);
- return SQRESULT_NOTNULL;
-}
-
-// void NSChatWriteLine( int context, string str )
-static SQRESULT SQ_ChatWriteLine(void* sqvm)
-{
- int context = ClientSq_getinteger(sqvm, 1);
- const char* str = ClientSq_getstring(sqvm, 2);
-
- LocalChatWriter((LocalChatWriter::Context)context).WriteLine(str);
- return SQRESULT_NOTNULL;
-}
-
-void InitialiseClientChatHooks(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x22E580, &CHudChat__AddGameLineHook, reinterpret_cast<LPVOID*>(&CHudChat__AddGameLine));
-
- g_ClientSquirrelManager->AddFuncRegistration("void", "NSChatWrite", "int context, string text", "", SQ_ChatWrite);
- g_ClientSquirrelManager->AddFuncRegistration("void", "NSChatWriteRaw", "int context, string text", "", SQ_ChatWriteRaw);
- g_ClientSquirrelManager->AddFuncRegistration("void", "NSChatWriteLine", "int context, string text", "", SQ_ChatWriteLine);
-}
diff --git a/NorthstarDedicatedTest/clientchathooks.h b/NorthstarDedicatedTest/clientchathooks.h
deleted file mode 100644
index 79a1b3e2..00000000
--- a/NorthstarDedicatedTest/clientchathooks.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-#include "pch.h"
-#include "serverchathooks.h"
-
-void InitialiseClientChatHooks(HMODULE baseAddress);
diff --git a/NorthstarDedicatedTest/clientruihooks.cpp b/NorthstarDedicatedTest/clientruihooks.cpp
deleted file mode 100644
index bc6c7aa7..00000000
--- a/NorthstarDedicatedTest/clientruihooks.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "pch.h"
-#include "clientruihooks.h"
-#include "convar.h"
-
-ConVar* Cvar_rui_drawEnable;
-
-typedef char (*DrawRUIFuncType)(void* a1, float* a2);
-DrawRUIFuncType DrawRUIFunc;
-
-char DrawRUIFuncHook(void* a1, float* a2)
-{
- if (!Cvar_rui_drawEnable->GetBool())
- return 0;
-
- return DrawRUIFunc(a1, a2);
-}
-
-void InitialiseEngineClientRUIHooks(HMODULE baseAddress)
-{
- Cvar_rui_drawEnable = new ConVar("rui_drawEnable", "1", FCVAR_CLIENTDLL, "Controls whether RUI should be drawn");
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0xFC500, &DrawRUIFuncHook, reinterpret_cast<LPVOID*>(&DrawRUIFunc));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/clientruihooks.h b/NorthstarDedicatedTest/clientruihooks.h
deleted file mode 100644
index 967ccefe..00000000
--- a/NorthstarDedicatedTest/clientruihooks.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void InitialiseEngineClientRUIHooks(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/clientvideooverrides.cpp b/NorthstarDedicatedTest/clientvideooverrides.cpp
deleted file mode 100644
index d5674f51..00000000
--- a/NorthstarDedicatedTest/clientvideooverrides.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "pch.h"
-#include "clientvideooverrides.h"
-#include "modmanager.h"
-
-typedef void* (*BinkOpenType)(const char* path, uint32_t flags);
-BinkOpenType BinkOpen;
-
-void* BinkOpenHook(const char* path, uint32_t flags)
-{
- std::string filename(fs::path(path).filename().string());
- spdlog::info("BinkOpen {}", filename);
-
- // figure out which mod is handling the bink
- Mod* fileOwner = nullptr;
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- if (std::find(mod.BinkVideos.begin(), mod.BinkVideos.end(), filename) != mod.BinkVideos.end())
- fileOwner = &mod;
- }
-
- if (fileOwner)
- {
- // create new path
- fs::path binkPath(fileOwner->ModDirectory / "media" / filename);
- return BinkOpen(binkPath.string().c_str(), flags);
- }
- else
- return BinkOpen(path, flags);
-}
-
-void InitialiseClientVideoOverrides(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook, GetProcAddress(GetModuleHandleA("bink2w64.dll"), "BinkOpen"), &BinkOpenHook, reinterpret_cast<LPVOID*>(&BinkOpen));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/clientvideooverrides.h b/NorthstarDedicatedTest/clientvideooverrides.h
deleted file mode 100644
index 8819e404..00000000
--- a/NorthstarDedicatedTest/clientvideooverrides.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void InitialiseClientVideoOverrides(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/context.cpp b/NorthstarDedicatedTest/context.cpp
deleted file mode 100644
index 7478faa3..00000000
--- a/NorthstarDedicatedTest/context.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "pch.h"
-#include "context.h"
-
-const char* GetContextName(ScriptContext context)
-{
- if (context == ScriptContext::CLIENT)
- return "CLIENT";
- else if (context == ScriptContext::SERVER)
- return "SERVER";
- else if (context == ScriptContext::UI)
- return "UI";
-
- return "";
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/context.h b/NorthstarDedicatedTest/context.h
deleted file mode 100644
index b6097780..00000000
--- a/NorthstarDedicatedTest/context.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-enum class ScriptContext : int
-{
- SERVER,
- CLIENT,
- UI,
- NONE
-};
-
-const char* GetContextName(ScriptContext context); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/debugoverlay.h b/NorthstarDedicatedTest/debugoverlay.h
deleted file mode 100644
index a300018c..00000000
--- a/NorthstarDedicatedTest/debugoverlay.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseDebugOverlay(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp
deleted file mode 100644
index 5099a6d2..00000000
--- a/NorthstarDedicatedTest/dedicated.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-#include "pch.h"
-#include "dedicated.h"
-#include "hookutils.h"
-#include "gameutils.h"
-#include "serverauthentication.h"
-#include "masterserver.h"
-
-bool IsDedicated()
-{
- static bool result = strstr(GetCommandLineA(), "-dedicated");
- return result;
-}
-
-// CDedidcatedExports defs
-struct CDedicatedExports; // forward declare
-
-typedef void (*DedicatedSys_PrintfType)(CDedicatedExports* dedicated, const char* msg);
-typedef void (*DedicatedRunServerType)(CDedicatedExports* dedicated);
-
-// would've liked to just do this as a class but have not been able to get it to work
-struct CDedicatedExports
-{
- void* vtable; // because it's easier, we just set this to &this, since CDedicatedExports has no props we care about other than funcs
-
- char unused[56];
-
- DedicatedSys_PrintfType Sys_Printf;
- DedicatedRunServerType RunServer;
-};
-
-void Sys_Printf(CDedicatedExports* dedicated, const char* msg)
-{
- spdlog::info("[DEDICATED PRINT] {}", msg);
-}
-
-typedef void (*CHostState__InitType)(CHostState* self);
-
-void RunServer(CDedicatedExports* dedicated)
-{
- spdlog::info("CDedicatedExports::RunServer(): starting");
- spdlog::info(CommandLine()->GetCmdLine());
-
- // initialise engine
- g_pEngine->Frame();
-
- // add +map if not present
- // don't manually execute this from cbuf as users may have it in their startup args anyway, easier just to run from stuffcmds if present
- if (!CommandLine()->CheckParm("+map"))
- CommandLine()->AppendParm("+map", g_pCVar->FindVar("match_defaultMap")->GetString());
-
- // run server autoexec and re-run commandline
- Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec autoexec_ns_server", cmd_source_t::kCommandSrcCode);
- Cbuf_AddText(Cbuf_GetCurrentPlayer(), "stuffcmds", cmd_source_t::kCommandSrcCode);
- Cbuf_Execute();
-
- // ensure playlist initialises right, if we've not explicitly called setplaylist
- SetCurrentPlaylist(GetCurrentPlaylistName());
-
- // note: we no longer manually set map and hoststate to start server in g_pHostState, we just use +map which seems to initialise stuff
- // better
-
- // get tickinterval
- ConVar* Cvar_base_tickinterval_mp = g_pCVar->FindVar("base_tickinterval_mp");
-
- // main loop
- double frameTitle = 0;
- while (g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING)
- {
- double frameStart = Plat_FloatTime();
- g_pEngine->Frame();
-
- // only update the title after at least 500ms since the last update
- if ((frameStart - frameTitle) > 0.5)
- {
- frameTitle = frameStart;
-
- // this way of getting playercount/maxplayers honestly really sucks, but not got any other methods of doing it rn
- const char* maxPlayers = GetCurrentPlaylistVar("max_players", false);
- if (!maxPlayers)
- maxPlayers = "6";
-
- SetConsoleTitleA(fmt::format(
- "{} - {} {}/{} players ({})",
- g_MasterServerManager->ns_auth_srvName,
- g_pHostState->m_levelName,
- g_ServerAuthenticationManager->m_additionalPlayerData.size(),
- maxPlayers,
- GetCurrentPlaylistName())
- .c_str());
- }
-
- std::this_thread::sleep_for(std::chrono::duration<double, std::ratio<1>>(
- Cvar_base_tickinterval_mp->GetFloat() - fmin(Plat_FloatTime() - frameStart, 0.25)));
- }
-}
-
-typedef bool (*IsGameActiveWindowType)();
-IsGameActiveWindowType IsGameActiveWindow;
-bool IsGameActiveWindowHook()
-{
- return true;
-}
-
-HANDLE consoleInputThreadHandle = NULL;
-
-DWORD WINAPI ConsoleInputThread(PVOID pThreadParameter)
-{
- while (!g_pEngine || !g_pHostState || g_pHostState->m_iCurrentState != HostState_t::HS_RUN)
- Sleep(1000);
-
- // Bind stdin to receive console input.
- FILE* fp = nullptr;
- freopen_s(&fp, "CONIN$", "r", stdin);
-
- spdlog::info("Ready to receive console commands.");
-
- {
- // Process console input
- std::string input;
- while (g_pEngine && g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING && std::getline(std::cin, input))
- {
- input += "\n";
- Cbuf_AddText(Cbuf_GetCurrentPlayer(), input.c_str(), cmd_source_t::kCommandSrcCode);
- }
- }
-
- return 0;
-}
-
-#include "NSMem.h"
-void InitialiseDedicated(HMODULE engineAddress)
-{
- spdlog::info("InitialiseDedicated");
-
- uintptr_t ea = (uintptr_t)engineAddress;
-
- {
- // Host_Init
- // prevent a particle init that relies on client dll
- NSMem::NOP(ea + 0x156799, 5);
- }
-
- {
- // CModAppSystemGroup::Create
- // force the engine into dedicated mode by changing the first comparison to IsServerOnly to an assignment
- auto ptr = ea + 0x1C4EBD;
-
- // cmp => mov
- NSMem::BytePatch(ptr + 1, "C6 87");
-
- // 00 => 01
- NSMem::BytePatch(ptr + 7, "01");
- }
-
- {
- // Some init that i'm not sure of that crashes
- // nop the call to it
- NSMem::NOP(ea + 0x156A63, 5);
- }
-
- {
- // runframeserver
- // nop some access violations
- NSMem::NOP(ea + 0x159819, 17);
- }
-
- {
- NSMem::NOP(ea + 0x156B4C, 7);
-
- // previously patched these, took me a couple weeks to figure out they were the issue
- // removing these will mess up register state when this function is over, so we'll write HS_RUN to the wrong address
- // so uhh, don't do that
- // NSMem::NOP(ea + 0x156B4C + 7, 8);
-
- NSMem::NOP(ea + 0x156B4C + 15, 9);
- }
-
- {
- // HostState_State_NewGame
- // nop an access violation
- NSMem::NOP(ea + 0xB934C, 9);
- }
-
- {
- // CEngineAPI::Connect
- // remove call to Shader_Connect
- NSMem::NOP(ea + 0x1C4D7D, 5);
- }
-
- // currently does not work, crashes stuff, likely gotta keep this here
- //{
- // // CEngineAPI::Connect
- // // remove calls to register ui rpak asset types
- // NSMem::NOP(ea + 0x1C4E07, 5);
- //}
-
- {
- // Host_Init
- // remove call to ui loading stuff
- NSMem::NOP(ea + 0x156595, 5);
- }
-
- {
- // some function that gets called from RunFrameServer
- // nop a function that makes requests to stryder, this will eventually access violation if left alone and isn't necessary anyway
- NSMem::NOP(ea + 0x15A0BB, 5);
- }
-
- {
- // RunFrameServer
- // nop a function that access violations
- NSMem::NOP(ea + 0x159BF3, 5);
- }
-
- {
- // func that checks if origin is inited
- // always return 1
- NSMem::BytePatch(
- ea + 0x183B70,
- {
- 0xB0,
- 0x01, // mov al,01
- 0xC3 // ret
- });
- }
-
- {
- // HostState_State_ChangeLevel
- // nop clientinterface call
- NSMem::NOP(ea + 0x1552ED, 16);
- }
-
- {
- // HostState_State_ChangeLevel
- // nop clientinterface call
- NSMem::NOP(ea + 0x155363, 16);
- }
-
- // note: previously had DisableDedicatedWindowCreation patches here, but removing those rn since they're all shit and unstable and bad
- // and such check commit history if any are needed for reimplementation
- {
- // IVideoMode::CreateGameWindow
- // nop call to ShowWindow
- NSMem::NOP(ea + 0x1CD146, 5);
- }
-
- CDedicatedExports* dedicatedExports = new CDedicatedExports;
- dedicatedExports->vtable = dedicatedExports;
- dedicatedExports->Sys_Printf = Sys_Printf;
- dedicatedExports->RunServer = RunServer;
-
- CDedicatedExports** exports = (CDedicatedExports**)((char*)engineAddress + 0x13F0B668);
- *exports = dedicatedExports;
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)engineAddress + 0x1CDC80, &IsGameActiveWindowHook, reinterpret_cast<LPVOID*>(&IsGameActiveWindow));
-
- // extra potential patches:
- // nop engine.dll+1c67d1 and +1c67d8 to skip videomode creategamewindow
- // also look into launcher.dll+d381, seems to cause renderthread to get made
- // this crashes HARD if no window which makes sense tbh
- // also look into materialsystem + 5B344 since it seems to be the base of all the renderthread stuff
-
- // big note: datatable gets registered in window creation
- // make sure it still gets registered
-
- // add cmdline args that are good for dedi
- CommandLine()->AppendParm("-nomenuvid", 0);
- CommandLine()->AppendParm("-nosound", 0);
- CommandLine()->AppendParm("-windowed", 0);
- CommandLine()->AppendParm("-nomessagebox", 0);
- CommandLine()->AppendParm("+host_preload_shaders", "0");
- CommandLine()->AppendParm("+net_usesocketsforloopback", "1");
-
- // Disable Quick Edit mode to reduce chance of user unintentionally hanging their server by selecting something.
- if (!CommandLine()->CheckParm("-bringbackquickedit"))
- {
- HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
- DWORD mode = 0;
-
- if (GetConsoleMode(stdIn, &mode))
- {
- if (mode & ENABLE_QUICK_EDIT_MODE)
- {
- mode &= ~ENABLE_QUICK_EDIT_MODE;
- mode &= ~ENABLE_MOUSE_INPUT;
-
- mode |= ENABLE_PROCESSED_INPUT;
-
- SetConsoleMode(stdIn, mode);
- }
- }
- }
- else
- spdlog::info("Quick Edit enabled by user request");
-
- // create console input thread
- if (!CommandLine()->CheckParm("-noconsoleinput"))
- consoleInputThreadHandle = CreateThread(0, 0, ConsoleInputThread, 0, 0, NULL);
- else
- spdlog::info("Console input disabled by user request");
-}
-
-void InitialiseDedicatedOrigin(HMODULE baseAddress)
-{
- // disable origin on dedicated
- // for any big ea lawyers, this can't be used to play the game without origin, game will throw a fit if you try to do anything without
- // an origin id as a client for dedi it's fine though, game doesn't care if origin is disabled as long as there's only a server
-
- NSMem::BytePatch(
- (uintptr_t)GetProcAddress(GetModuleHandleA("tier0.dll"), "Tier0_InitOrigin"),
- {
- 0xC3 // ret
- });
-}
-
-typedef void (*PrintFatalSquirrelErrorType)(void* sqvm);
-PrintFatalSquirrelErrorType PrintFatalSquirrelError;
-void PrintFatalSquirrelErrorHook(void* sqvm)
-{
- PrintFatalSquirrelError(sqvm);
- g_pEngine->m_nQuitting = EngineQuitState::QUIT_TODESKTOP;
-}
-
-void InitialiseDedicatedServerGameDLL(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, baseAddress + 0x794D0, &PrintFatalSquirrelErrorHook, reinterpret_cast<LPVOID*>(&PrintFatalSquirrelError));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/dedicated.h b/NorthstarDedicatedTest/dedicated.h
deleted file mode 100644
index 0b4d9188..00000000
--- a/NorthstarDedicatedTest/dedicated.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#pragma once
-
-bool IsDedicated();
-
-void InitialiseDedicated(HMODULE moduleAddress);
-void InitialiseDedicatedOrigin(HMODULE baseAddress);
-void InitialiseDedicatedServerGameDLL(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp b/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp
deleted file mode 100644
index f1a91e22..00000000
--- a/NorthstarDedicatedTest/dedicatedmaterialsystem.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-#pragma once
-#include "pch.h"
-#include "dedicated.h"
-#include "dedicatedmaterialsystem.h"
-#include "hookutils.h"
-#include "gameutils.h"
-#include "NSMem.h"
-
-typedef HRESULT (*__stdcall D3D11CreateDeviceType)(
- void* pAdapter,
- int DriverType,
- HMODULE Software,
- UINT Flags,
- int* pFeatureLevels,
- UINT FeatureLevels,
- UINT SDKVersion,
- void** ppDevice,
- int* pFeatureLevel,
- void** ppImmediateContext);
-D3D11CreateDeviceType D3D11CreateDevice;
-
-HRESULT __stdcall D3D11CreateDeviceHook(
- void* pAdapter,
- int DriverType,
- HMODULE Software,
- UINT Flags,
- int* pFeatureLevels,
- UINT FeatureLevels,
- UINT SDKVersion,
- void** ppDevice,
- int* pFeatureLevel,
- void** ppImmediateContext)
-{
- // note: this is super duper temp pretty much just messing around with it
- // does run surprisingly well on dedi for a software driver tho if you ignore the +1gb ram usage at times, seems like dedi doesn't
- // really call gpu much even with renderthread still being a thing will be using this hook for actual d3d stubbing and stuff later
-
- // atm, i think the play might be to run d3d in software, and then just stub out any calls that allocate memory/use alot of resources
- // (e.g. createtexture and that sorta thing)
- // note: this has been succeeded by the d3d11 and gfsdk stubs, and is only being kept around for posterity and as a fallback option
- if (CommandLine()->CheckParm("-softwared3d11"))
- DriverType = 5; // D3D_DRIVER_TYPE_WARP
-
- return D3D11CreateDevice(
- pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext);
-}
-
-void InitialiseDedicatedMaterialSystem(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0xD9A0E, &D3D11CreateDeviceHook, reinterpret_cast<LPVOID*>(&D3D11CreateDevice));
-
- // not using these for now since they're related to nopping renderthread/gamewindow i.e. very hard
- //{
- // // function that launches renderthread
- // char* ptr = (char*)baseAddress + 0x87047;
- // TempReadWrite rw(ptr);
- //
- // // make it not launch renderthread
- // *ptr = (char)0x90;
- // *(ptr + 1) = (char)0x90;
- // *(ptr + 2) = (char)0x90;
- // *(ptr + 3) = (char)0x90;
- // *(ptr + 4) = (char)0x90;
- // *(ptr + 5) = (char)0x90;
- //}
- //
- //{
- // // some function that waits on renderthread job
- // char* ptr = (char*)baseAddress + 0x87d00;
- // TempReadWrite rw(ptr);
- //
- // // return immediately
- // *ptr = (char)0xC3;
- //}
-
- {
- // CMaterialSystem::FindMaterial
- // make the game always use the error material
- NSMem::BytePatch((uintptr_t)baseAddress + 0x5F0F1, {0xE9, 0x34, 0x03, 0x00});
- }
-
- // previously had DisableDedicatedWindowCreation stuff here, removing for now since shit and unstable
- // check commit history if needed
-}
-
-typedef void* (*PakLoadAPI__LoadRpakType)(char* filename, void* unknown, int flags);
-PakLoadAPI__LoadRpakType PakLoadAPI__LoadRpak;
-
-void* PakLoadAPI__LoadRpakHook(char* filename, void* unknown, int flags)
-{
- spdlog::info("PakLoadAPI__LoadRpakHook {}", filename);
-
- // on dedi, don't load any paks that aren't required
- if (strncmp(filename, "common", 6))
- return 0;
-
- return PakLoadAPI__LoadRpak(filename, unknown, flags);
-}
-
-typedef void* (*PakLoadAPI__LoadRpak2Type)(char* filename, void* unknown, int flags, void* callback, void* callback2);
-PakLoadAPI__LoadRpak2Type PakLoadAPI__LoadRpak2;
-
-void* PakLoadAPI__LoadRpak2Hook(char* filename, void* unknown, int flags, void* callback, void* callback2)
-{
- spdlog::info("PakLoadAPI__LoadRpak2Hook {}", filename);
-
- // on dedi, don't load any paks that aren't required
- if (strncmp(filename, "common", 6))
- return 0;
-
- return PakLoadAPI__LoadRpak2(filename, unknown, flags, callback, callback2);
-}
-
-void InitialiseDedicatedRtechGame(HMODULE baseAddress)
-{
- baseAddress = GetModuleHandleA("rtech_game.dll");
-
- HookEnabler hook;
- // unfortunately this is unstable, seems to freeze when changing maps
- // ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0xB0F0, &PakLoadAPI__LoadRpakHook, reinterpret_cast<LPVOID*>(&PakLoadAPI__LoadRpak));
- // ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0xB170, &PakLoadAPI__LoadRpak2Hook, reinterpret_cast<LPVOID*>(&PakLoadAPI__LoadRpak2));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/dedicatedmaterialsystem.h b/NorthstarDedicatedTest/dedicatedmaterialsystem.h
deleted file mode 100644
index 38343d17..00000000
--- a/NorthstarDedicatedTest/dedicatedmaterialsystem.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-void InitialiseDedicatedMaterialSystem(HMODULE baseAddress);
-void InitialiseDedicatedRtechGame(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
deleted file mode 100644
index 62094b4e..00000000
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-#include "pch.h"
-#include "hooks.h"
-#include "main.h"
-#include "squirrel.h"
-#include "dedicated.h"
-#include "dedicatedmaterialsystem.h"
-#include "sourceconsole.h"
-#include "logging.h"
-#include "concommand.h"
-#include "modmanager.h"
-#include "filesystem.h"
-#include "serverauthentication.h"
-#include "scriptmodmenu.h"
-#include "scriptserverbrowser.h"
-#include "keyvalues.h"
-#include "masterserver.h"
-#include "gameutils.h"
-#include "chatcommand.h"
-#include "modlocalisation.h"
-#include "playlist.h"
-#include "miscserverscript.h"
-#include "clientauthhooks.h"
-#include "latencyflex.h"
-#include "scriptbrowserhooks.h"
-#include "scriptmainmenupromos.h"
-#include "miscclientfixes.h"
-#include "miscserverfixes.h"
-#include "rpakfilesystem.h"
-#include "bansystem.h"
-#include "memalloc.h"
-#include "maxplayers.h"
-#include "languagehooks.h"
-#include "audio.h"
-#include "buildainfile.h"
-#include "configurables.h"
-#include "serverchathooks.h"
-#include "clientchathooks.h"
-#include "localchatwriter.h"
-#include "scriptservertoclientstringcommand.h"
-#include "plugin_abi.h"
-#include "plugins.h"
-#include "debugoverlay.h"
-#include "clientvideooverrides.h"
-#include "clientruihooks.h"
-#include <string.h>
-#include "version.h"
-#include "pch.h"
-
-#include "rapidjson/document.h"
-#include "rapidjson/stringbuffer.h"
-#include "rapidjson/writer.h"
-#include "rapidjson/error/en.h"
-#include "ExploitFixes.h"
-#include "emit_blocker.h"
-
-typedef void (*initPluginFuncPtr)(void* getPluginObject);
-
-bool initialised = false;
-
-BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
-{
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
-
- return TRUE;
-}
-
-void WaitForDebugger(HMODULE baseAddress)
-{
- // earlier waitfordebugger call than is in vanilla, just so we can debug stuff a little easier
- if (CommandLine()->CheckParm("-waitfordebugger"))
- {
- spdlog::info("waiting for debugger...");
-
- while (!IsDebuggerPresent())
- Sleep(100);
- }
-}
-
-void freeLibrary(HMODULE hLib)
-{
- if (!FreeLibrary(hLib))
- {
- spdlog::error("There was an error while trying to free library");
- }
-}
-
-bool LoadPlugins()
-{
-
- std::vector<fs::path> paths;
-
- std::string pluginPath = GetNorthstarPrefix() + "/plugins";
- if (!fs::exists(pluginPath))
- {
- spdlog::warn("Could not find a plugins directory. Skipped loading plugins");
- return false;
- }
- // ensure dirs exist
- fs::recursive_directory_iterator iterator(pluginPath);
- if (std::filesystem::begin(iterator) == std::filesystem::end(iterator))
- {
- spdlog::warn("Could not find any plugins. Skipped loading plugins");
- return false;
- }
- for (auto const& entry : iterator)
- {
- if (fs::is_regular_file(entry) && entry.path().extension() == ".dll")
- paths.emplace_back(entry.path().filename());
- }
- initGameState();
- for (fs::path path : paths)
- {
- std::string pathstring = (pluginPath / path).string();
- std::wstring wpath = (pluginPath / path).wstring();
-
- LPCWSTR wpptr = wpath.c_str();
- HMODULE datafile =
- LoadLibraryExW(wpptr, 0, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); // Load the DLL as a data file
- if (datafile == NULL)
- {
- spdlog::info("Failed to load library {}: ", std::system_category().message(GetLastError()));
- continue;
- }
- HRSRC manifestResource = FindResourceW(datafile, MAKEINTRESOURCE(101), MAKEINTRESOURCE(RT_RCDATA));
-
- if (manifestResource == NULL)
- {
- spdlog::info("Could not find manifest for library {}", pathstring);
- freeLibrary(datafile);
- continue;
- }
- spdlog::info("Loading resource from library");
- HGLOBAL myResourceData = LoadResource(datafile, manifestResource);
- if (myResourceData == NULL)
- {
- spdlog::error("Failed to load resource from library");
- freeLibrary(datafile);
- continue;
- }
- int manifestSize = SizeofResource(datafile, manifestResource);
- std::string manifest = std::string((const char*)LockResource(myResourceData), 0, manifestSize);
- freeLibrary(datafile);
-
- rapidjson_document manifestJSON;
- manifestJSON.Parse(manifest.c_str());
-
- if (manifestJSON.HasParseError())
- {
- spdlog::error("Manifest for {} was invalid", pathstring);
- continue;
- }
- if (!manifestJSON.HasMember("api_version"))
- {
- spdlog::error("{} does not have a version number in its manifest", pathstring);
- continue;
- // spdlog::info(manifestJSON["version"].GetString());
- }
- if (strcmp(manifestJSON["api_version"].GetString(), std::to_string(ABI_VERSION).c_str()))
- {
- spdlog::error("{} has an incompatible API version number in its manifest", pathstring);
- continue;
- }
- // Passed all checks, going to actually load it now
-
- HMODULE pluginLib = LoadLibraryW(wpptr); // Load the DLL as a data file
- if (pluginLib == NULL)
- {
- spdlog::info("Failed to load library {}: ", std::system_category().message(GetLastError()));
- continue;
- }
- initPluginFuncPtr initPlugin = (initPluginFuncPtr)GetProcAddress(pluginLib, "initializePlugin");
- if (initPlugin == NULL)
- {
- spdlog::info("Library {} has no function initializePlugin", pathstring);
- continue;
- }
- spdlog::info("Succesfully loaded {}", pathstring);
- initPlugin(&getPluginObject);
- }
- return true;
-}
-
-bool InitialiseNorthstar()
-{
- if (initialised)
- {
- // spdlog::warn("Called InitialiseNorthstar more than once!"); // it's actually 100% fine for that to happen
- return false;
- }
-
- initialised = true;
-
- parseConfigurables();
- InitialiseVersion();
-
- // Fix some users' failure to connect to respawn datacenters
- SetEnvironmentVariableA("OPENSSL_ia32cap", "~0x200000200000000");
-
- curl_global_init_mem(CURL_GLOBAL_DEFAULT, _malloc_base, _free_base, _realloc_base, _strdup_base, _calloc_base);
-
- InitialiseLogging();
- InstallInitialHooks();
- CreateLogFiles();
-
- // Write launcher version to log
- spdlog::info("NorthstarLauncher version: {}", version);
-
- InitialiseInterfaceCreationHooks();
-
- AddDllLoadCallback("tier0.dll", InitialiseTier0GameUtilFunctions);
- AddDllLoadCallback("engine.dll", WaitForDebugger);
- AddDllLoadCallback("engine.dll", InitialiseEngineGameUtilFunctions);
- AddDllLoadCallback("server.dll", InitialiseServerGameUtilFunctions);
-
- // dedi patches
- {
- AddDllLoadCallbackForDedicatedServer("tier0.dll", InitialiseDedicatedOrigin);
- AddDllLoadCallbackForDedicatedServer("engine.dll", InitialiseDedicated);
- AddDllLoadCallbackForDedicatedServer("server.dll", InitialiseDedicatedServerGameDLL);
- AddDllLoadCallbackForDedicatedServer("materialsystem_dx11.dll", InitialiseDedicatedMaterialSystem);
- // this fucking sucks, but seemingly we somehow load after rtech_game???? unsure how, but because of this we have to apply patches
- // here, not on rtech_game load
- AddDllLoadCallbackForDedicatedServer("engine.dll", InitialiseDedicatedRtechGame);
- }
-
- AddDllLoadCallback("engine.dll", InitialiseConVars);
- AddDllLoadCallback("engine.dll", InitialiseConCommands);
-
- // client-exclusive patches
- {
-
- AddDllLoadCallbackForClient("tier0.dll", InitialiseTier0LanguageHooks);
- AddDllLoadCallbackForClient("client.dll", InitialiseClientSquirrel);
- AddDllLoadCallbackForClient("client.dll", InitialiseSourceConsole);
- AddDllLoadCallbackForClient("engine.dll", InitialiseChatCommands);
- AddDllLoadCallbackForClient("client.dll", InitialiseScriptModMenu);
- AddDllLoadCallbackForClient("client.dll", InitialiseScriptServerBrowser);
- AddDllLoadCallbackForClient("localize.dll", InitialiseModLocalisation);
- AddDllLoadCallbackForClient("engine.dll", InitialiseClientAuthHooks);
- AddDllLoadCallbackForClient("client.dll", InitialiseLatencyFleX);
- AddDllLoadCallbackForClient("engine.dll", InitialiseScriptExternalBrowserHooks);
- AddDllLoadCallbackForClient("client.dll", InitialiseScriptMainMenuPromos);
- AddDllLoadCallbackForClient("client.dll", InitialiseMiscClientFixes);
- AddDllLoadCallbackForClient("client.dll", InitialiseClientPrintHooks);
- AddDllLoadCallbackForClient("client.dll", InitialisePluginCommands);
- AddDllLoadCallbackForClient("client.dll", InitialiseClientChatHooks);
- AddDllLoadCallbackForClient("client.dll", InitialiseLocalChatWriter);
- AddDllLoadCallbackForClient("client.dll", InitialiseScriptServerToClientStringCommands);
- AddDllLoadCallbackForClient("client.dll", InitialiseClientVideoOverrides);
- AddDllLoadCallbackForClient("engine.dll", InitialiseEngineClientRUIHooks);
- AddDllLoadCallbackForClient("engine.dll", InitialiseDebugOverlay);
- // audio hooks
- AddDllLoadCallbackForClient("client.dll", InitialiseMilesAudioHooks);
- }
-
- AddDllLoadCallback("engine.dll", InitialiseEngineSpewFuncHooks);
- AddDllLoadCallback("server.dll", InitialiseServerSquirrel);
- AddDllLoadCallback("engine.dll", InitialiseBanSystem);
- AddDllLoadCallback("engine.dll", InitialiseServerAuthentication);
- AddDllLoadCallback("engine.dll", InitialiseSharedMasterServer);
- AddDllLoadCallback("server.dll", InitialiseMiscServerScriptCommand);
- AddDllLoadCallback("server.dll", InitialiseMiscServerFixes);
- AddDllLoadCallback("server.dll", InitialiseBuildAINFileHooks);
-
- AddDllLoadCallback("engine.dll", InitialisePlaylistHooks);
-
- AddDllLoadCallback("filesystem_stdio.dll", InitialiseFilesystem);
- AddDllLoadCallback("engine.dll", InitialiseEngineRpakFilesystem);
- AddDllLoadCallback("engine.dll", InitialiseKeyValues);
-
- AddDllLoadCallback("engine.dll", InitialiseServerChatHooks_Engine);
- AddDllLoadCallback("server.dll", InitialiseServerChatHooks_Server);
-
- // maxplayers increase
- AddDllLoadCallback("engine.dll", InitialiseMaxPlayersOverride_Engine);
- AddDllLoadCallback("client.dll", InitialiseMaxPlayersOverride_Client);
- AddDllLoadCallback("server.dll", InitialiseMaxPlayersOverride_Server);
-
- // mod manager after everything else
- AddDllLoadCallback("engine.dll", InitialiseModManager);
-
- // activate exploit fixes
- AddDllLoadCallback("server.dll", ExploitFixes::LoadCallback);
- AddDllLoadCallback("server.dll", InitialiseServerEmit_Blocker);
-
- // run callbacks for any libraries that are already loaded by now
- CallAllPendingDLLLoadCallbacks();
-
- return true;
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/emit_blocker.cpp b/NorthstarDedicatedTest/emit_blocker.cpp
deleted file mode 100644
index 3f996c69..00000000
--- a/NorthstarDedicatedTest/emit_blocker.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "pch.h"
-#include "cvar.h"
-
-ConVar* sv_cheats;
-
-typedef char(__fastcall* function_containing_emit_t)(uint64_t a1, uint64_t a2);
-function_containing_emit_t function_containing_emit;
-
-char function_containing_emit_hook(uint64_t unknown_value, uint64_t command_ptr)
-{
- char* command_string = *(char**)(command_ptr + 1040); // From decompile
- if (!sv_cheats->m_Value.m_nValue && !strncmp(command_string, "emit", 5))
- {
- spdlog::info("Blocking command \"emit\" because sv_cheats was 0");
- return 1;
- }
- return function_containing_emit(unknown_value, command_ptr);
-}
-
-void InitialiseServerEmit_Blocker(HMODULE baseAddress)
-{
- HookEnabler hook;
- sv_cheats = g_pCVar->FindVar("sv_cheats");
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x5889A0, &function_containing_emit_hook, reinterpret_cast<LPVOID*>(&function_containing_emit));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/emit_blocker.h b/NorthstarDedicatedTest/emit_blocker.h
deleted file mode 100644
index 43991927..00000000
--- a/NorthstarDedicatedTest/emit_blocker.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseServerEmit_Blocker(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/filesystem.cpp b/NorthstarDedicatedTest/filesystem.cpp
deleted file mode 100644
index 702141bb..00000000
--- a/NorthstarDedicatedTest/filesystem.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-#include "pch.h"
-#include "filesystem.h"
-#include "hooks.h"
-#include "hookutils.h"
-#include "sourceinterface.h"
-#include "modmanager.h"
-
-#include <iostream>
-#include <sstream>
-
-// hook forward declares
-typedef FileHandle_t (*ReadFileFromVPKType)(VPKData* vpkInfo, __int64* b, char* filename);
-ReadFileFromVPKType readFileFromVPK;
-FileHandle_t ReadFileFromVPKHook(VPKData* vpkInfo, __int64* b, char* filename);
-
-typedef bool (*ReadFromCacheType)(IFileSystem* filesystem, char* path, void* result);
-ReadFromCacheType readFromCache;
-bool ReadFromCacheHook(IFileSystem* filesystem, char* path, void* result);
-
-typedef void (*AddSearchPathType)(IFileSystem* fileSystem, const char* pPath, const char* pathID, SearchPathAdd_t addType);
-AddSearchPathType addSearchPathOriginal;
-void AddSearchPathHook(IFileSystem* fileSystem, const char* pPath, const char* pathID, SearchPathAdd_t addType);
-
-typedef FileHandle_t (*ReadFileFromFilesystemType)(
- IFileSystem* filesystem, const char* pPath, const char* pOptions, int64_t a4, uint32_t a5);
-ReadFileFromFilesystemType readFileFromFilesystem;
-FileHandle_t ReadFileFromFilesystemHook(IFileSystem* filesystem, const char* pPath, const char* pOptions, int64_t a4, uint32_t a5);
-
-typedef VPKData* (*MountVPKType)(IFileSystem* fileSystem, const char* vpkPath);
-MountVPKType mountVPK;
-VPKData* MountVPKHook(IFileSystem* fileSystem, const char* vpkPath);
-
-bool readingOriginalFile;
-std::string currentModPath;
-SourceInterface<IFileSystem>* g_Filesystem;
-
-void InitialiseFilesystem(HMODULE baseAddress)
-{
- g_Filesystem = new SourceInterface<IFileSystem>("filesystem_stdio.dll", "VFileSystem017");
-
- // create hooks
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x5CBA0, &ReadFileFromVPKHook, reinterpret_cast<LPVOID*>(&readFileFromVPK));
- ENABLER_CREATEHOOK(hook, (*g_Filesystem)->m_vtable->ReadFromCache, &ReadFromCacheHook, reinterpret_cast<LPVOID*>(&readFromCache));
- ENABLER_CREATEHOOK(
- hook, (*g_Filesystem)->m_vtable->AddSearchPath, &AddSearchPathHook, reinterpret_cast<LPVOID*>(&addSearchPathOriginal));
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x15F20, &ReadFileFromFilesystemHook, reinterpret_cast<LPVOID*>(&readFileFromFilesystem));
- ENABLER_CREATEHOOK(hook, (*g_Filesystem)->m_vtable->MountVPK, &MountVPKHook, reinterpret_cast<LPVOID*>(&mountVPK));
-}
-
-std::string ReadVPKFile(const char* path)
-{
- // read scripts.rson file, todo: check if this can be overwritten
- FileHandle_t fileHandle = (*g_Filesystem)->m_vtable2->Open(&(*g_Filesystem)->m_vtable2, path, "rb", "GAME", 0);
-
- std::stringstream fileStream;
- int bytesRead = 0;
- char data[4096];
- do
- {
- bytesRead = (*g_Filesystem)->m_vtable2->Read(&(*g_Filesystem)->m_vtable2, data, (int)std::size(data), fileHandle);
- fileStream.write(data, bytesRead);
- } while (bytesRead == std::size(data));
-
- (*g_Filesystem)->m_vtable2->Close(*g_Filesystem, fileHandle);
-
- return fileStream.str();
-}
-
-std::string ReadVPKOriginalFile(const char* path)
-{
- readingOriginalFile = true;
- std::string ret = ReadVPKFile(path);
- readingOriginalFile = false;
-
- return ret;
-}
-
-void SetNewModSearchPaths(Mod* mod)
-{
- // put our new path to the head if we need to read from a different mod path
- // in the future we could also determine whether the file we're setting paths for needs a mod dir, or compiled assets
- if (mod != nullptr)
- {
- if ((fs::absolute(mod->ModDirectory) / MOD_OVERRIDE_DIR).string().compare(currentModPath))
- {
- spdlog::info("changing mod search path from {} to {}", currentModPath, mod->ModDirectory.string());
-
- addSearchPathOriginal(
- &*(*g_Filesystem), (fs::absolute(mod->ModDirectory) / MOD_OVERRIDE_DIR).string().c_str(), "GAME", PATH_ADD_TO_HEAD);
- currentModPath = (fs::absolute(mod->ModDirectory) / MOD_OVERRIDE_DIR).string();
- }
- }
- else // push compiled to head
- addSearchPathOriginal(&*(*g_Filesystem), fs::absolute(GetCompiledAssetsPath()).string().c_str(), "GAME", PATH_ADD_TO_HEAD);
-}
-
-bool TryReplaceFile(char* path, bool shouldCompile)
-{
- if (readingOriginalFile)
- return false;
-
- if (shouldCompile)
- (*g_ModManager).CompileAssetsForFile(path);
-
- // idk how efficient the lexically normal check is
- // can't just set all /s in path to \, since some paths aren't in writeable memory
- auto file = g_ModManager->m_modFiles.find(fs::path(path).lexically_normal().string());
- if (file != g_ModManager->m_modFiles.end())
- {
- SetNewModSearchPaths(file->second.owningMod);
- return true;
- }
-
- return false;
-}
-
-FileHandle_t ReadFileFromVPKHook(VPKData* vpkInfo, __int64* b, char* filename)
-{
- // move this to a convar at some point when we can read them in native
- // spdlog::info("ReadFileFromVPKHook {} {}", filename, vpkInfo->path);
-
- // there is literally never any reason to compile here, since we'll always compile in ReadFileFromFilesystemHook in the same codepath
- // this is called
- if (TryReplaceFile(filename, false))
- {
- *b = -1;
- return b;
- }
-
- return readFileFromVPK(vpkInfo, b, filename);
-}
-
-bool ReadFromCacheHook(IFileSystem* filesystem, char* path, void* result)
-{
- // move this to a convar at some point when we can read them in native
- // spdlog::info("ReadFromCacheHook {}", path);
-
- if (TryReplaceFile(path, true))
- return false;
-
- return readFromCache(filesystem, path, result);
-}
-
-void AddSearchPathHook(IFileSystem* fileSystem, const char* pPath, const char* pathID, SearchPathAdd_t addType)
-{
- addSearchPathOriginal(fileSystem, pPath, pathID, addType);
-
- // make sure current mod paths are at head
- if (!strcmp(pathID, "GAME") && currentModPath.compare(pPath) && addType == PATH_ADD_TO_HEAD)
- {
- addSearchPathOriginal(fileSystem, currentModPath.c_str(), "GAME", PATH_ADD_TO_HEAD);
- addSearchPathOriginal(fileSystem, GetCompiledAssetsPath().string().c_str(), "GAME", PATH_ADD_TO_HEAD);
- }
-}
-
-FileHandle_t ReadFileFromFilesystemHook(IFileSystem* filesystem, const char* pPath, const char* pOptions, int64_t a4, uint32_t a5)
-{
- // this isn't super efficient, but it's necessary, since calling addsearchpath in readfilefromvpk doesn't work, possibly refactor later
- // it also might be possible to hook functions that are called later, idk look into callstack for ReadFileFromVPK
- if (!readingOriginalFile)
- TryReplaceFile((char*)pPath, true);
-
- return readFileFromFilesystem(filesystem, pPath, pOptions, a4, a5);
-}
-
-VPKData* MountVPKHook(IFileSystem* fileSystem, const char* vpkPath)
-{
- spdlog::info("MountVPK {}", vpkPath);
- VPKData* ret = mountVPK(fileSystem, vpkPath);
-
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- for (ModVPKEntry& vpkEntry : mod.Vpks)
- {
- // if we're autoloading, just load no matter what
- if (!vpkEntry.m_bAutoLoad)
- {
- // resolve vpk name and try to load one with the same name
- // todo: we should be unloading these on map unload manually
- std::string mapName(fs::path(vpkPath).filename().string());
- std::string modMapName(fs::path(vpkEntry.m_sVpkPath.c_str()).filename().string());
- if (mapName.compare(modMapName))
- continue;
- }
-
- VPKData* loaded = mountVPK(fileSystem, vpkEntry.m_sVpkPath.c_str());
- if (!ret) // this is primarily for map vpks and stuff, so the map's vpk is what gets returned from here
- ret = loaded;
- }
- }
-
- return ret;
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/gameutils.cpp b/NorthstarDedicatedTest/gameutils.cpp
deleted file mode 100644
index 792d8bf2..00000000
--- a/NorthstarDedicatedTest/gameutils.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-#include "pch.h"
-#include "convar.h"
-#include "gameutils.h"
-
-// memory
-IMemAlloc* g_pMemAllocSingleton;
-typedef IMemAlloc* (*CreateGlobalMemAllocType)();
-CreateGlobalMemAllocType CreateGlobalMemAlloc;
-
-// cmd.h
-Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer;
-Cbuf_AddTextType Cbuf_AddText;
-Cbuf_ExecuteType Cbuf_Execute;
-
-// hoststate stuff
-CHostState* g_pHostState;
-
-// cengine stuff
-CEngine* g_pEngine;
-server_state_t* sv_m_State;
-
-// network stuff
-ConVar* Cvar_hostport;
-
-// playlist stuff
-GetCurrentPlaylistType GetCurrentPlaylistName;
-SetCurrentPlaylistType SetCurrentPlaylist;
-SetPlaylistVarOverrideType SetPlaylistVarOverride;
-GetCurrentPlaylistVarType GetCurrentPlaylistVar;
-
-// server entity stuff
-Server_GetEntityByIndexType Server_GetEntityByIndex;
-
-// auth
-char* g_LocalPlayerUserID;
-char* g_LocalPlayerOriginToken;
-
-// misc stuff
-ErrorType Error;
-CommandLineType CommandLine;
-Plat_FloatTimeType Plat_FloatTime;
-ThreadInServerFrameThreadType ThreadInServerFrameThread;
-GetBaseLocalClientType GetBaseLocalClient;
-
-void InitialiseEngineGameUtilFunctions(HMODULE baseAddress)
-{
- Cbuf_GetCurrentPlayer = (Cbuf_GetCurrentPlayerType)((char*)baseAddress + 0x120630);
- Cbuf_AddText = (Cbuf_AddTextType)((char*)baseAddress + 0x1203B0);
- Cbuf_Execute = (Cbuf_ExecuteType)((char*)baseAddress + 0x1204B0);
-
- g_pHostState = (CHostState*)((char*)baseAddress + 0x7CF180);
- g_pEngine = *(CEngine**)((char*)baseAddress + 0x7D70C8);
- sv_m_State = (server_state_t*)((char*)baseAddress + 0x12A53D48);
-
- GetCurrentPlaylistName = (GetCurrentPlaylistType)((char*)baseAddress + 0x18C640);
- SetCurrentPlaylist = (SetCurrentPlaylistType)((char*)baseAddress + 0x18EB20);
- SetPlaylistVarOverride = (SetPlaylistVarOverrideType)((char*)baseAddress + 0x18ED00);
- GetCurrentPlaylistVar = (GetCurrentPlaylistVarType)((char*)baseAddress + 0x18C680);
-
- g_LocalPlayerUserID = (char*)baseAddress + 0x13F8E688;
- g_LocalPlayerOriginToken = (char*)baseAddress + 0x13979C80;
-
- GetBaseLocalClient = (GetBaseLocalClientType)((char*)baseAddress + 0x78200);
-
- /* NOTE:
- g_pCVar->FindVar("convar_name") now works. These are no longer needed.
- You can also itterate over every ConVar using CCVarIteratorInternal
- dump the pointers to a vector and access them from there.
- Example:
- std::vector<ConVar*> g_pAllConVars;
- for (auto& map : g_pCVar->DumpToMap())
- {
- ConVar* pConVar = g_pCVar->FindVar(map.first.c_str());
- if (pConVar)
- {
- g_pAllConVars.push_back(pConVar);
- }
- }*/
-
- Cvar_hostport = (ConVar*)((char*)baseAddress + 0x13FA6070);
-}
-
-void InitialiseServerGameUtilFunctions(HMODULE baseAddress)
-{
- Server_GetEntityByIndex = (Server_GetEntityByIndexType)((char*)baseAddress + 0xFB820);
-}
-
-void InitialiseTier0GameUtilFunctions(HMODULE baseAddress)
-{
- if (!baseAddress)
- {
- spdlog::critical("tier0 base address is null, but it should be already loaded");
- throw "tier0 base address is null, but it should be already loaded";
- }
- if (g_pMemAllocSingleton)
- return; // seems this function was already called
- CreateGlobalMemAlloc = reinterpret_cast<CreateGlobalMemAllocType>(GetProcAddress(baseAddress, "CreateGlobalMemAlloc"));
- IMemAlloc** ppMemAllocSingleton = reinterpret_cast<IMemAlloc**>(GetProcAddress(baseAddress, "g_pMemAllocSingleton"));
- if (!ppMemAllocSingleton)
- {
- spdlog::critical("Address of g_pMemAllocSingleton is a null pointer, this should never happen");
- throw "Address of g_pMemAllocSingleton is a null pointer, this should never happen";
- }
- if (!*ppMemAllocSingleton)
- {
- g_pMemAllocSingleton = CreateGlobalMemAlloc();
- *ppMemAllocSingleton = g_pMemAllocSingleton;
- spdlog::info("Created new g_pMemAllocSingleton");
- }
- else
- {
- g_pMemAllocSingleton = *ppMemAllocSingleton;
- }
-
- Error = reinterpret_cast<ErrorType>(GetProcAddress(baseAddress, "Error"));
- CommandLine = reinterpret_cast<CommandLineType>(GetProcAddress(baseAddress, "CommandLine"));
- Plat_FloatTime = reinterpret_cast<Plat_FloatTimeType>(GetProcAddress(baseAddress, "Plat_FloatTime"));
- ThreadInServerFrameThread = reinterpret_cast<ThreadInServerFrameThreadType>(GetProcAddress(baseAddress, "ThreadInServerFrameThread"));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/gameutils.h b/NorthstarDedicatedTest/gameutils.h
deleted file mode 100644
index 6d625c16..00000000
--- a/NorthstarDedicatedTest/gameutils.h
+++ /dev/null
@@ -1,249 +0,0 @@
-#pragma once
-#include "convar.h"
-
-// memory
-class IMemAlloc
-{
- public:
- struct VTable
- {
- void* unknown[1]; // alloc debug
- void* (*Alloc)(IMemAlloc* memAlloc, size_t nSize);
- void* unknown2[1]; // realloc debug
- void* (*Realloc)(IMemAlloc* memAlloc, void* pMem, size_t nSize);
- void* unknown3[1]; // free #1
- void (*Free)(IMemAlloc* memAlloc, void* pMem);
- void* unknown4[2]; // nullsubs, maybe CrtSetDbgFlag
- size_t (*GetSize)(IMemAlloc* memAlloc, void* pMem);
- void* unknown5[9]; // they all do literally nothing
- void (*DumpStats)(IMemAlloc* memAlloc);
- void (*DumpStatsFileBase)(IMemAlloc* memAlloc, const char* pchFileBase);
- void* unknown6[4];
- int (*heapchk)(IMemAlloc* memAlloc);
- };
-
- VTable* m_vtable;
-};
-
-extern IMemAlloc* g_pMemAllocSingleton;
-typedef IMemAlloc* (*CreateGlobalMemAllocType)();
-extern CreateGlobalMemAllocType CreateGlobalMemAlloc;
-
-// cmd.h
-enum class ECommandTarget_t
-{
- CBUF_FIRST_PLAYER = 0,
- CBUF_LAST_PLAYER = 1, // MAX_SPLITSCREEN_CLIENTS - 1, MAX_SPLITSCREEN_CLIENTS = 2
- CBUF_SERVER = CBUF_LAST_PLAYER + 1,
-
- CBUF_COUNT,
-};
-
-enum class cmd_source_t
-{
- // Added to the console buffer by gameplay code. Generally unrestricted.
- kCommandSrcCode,
-
- // Sent from code via engine->ClientCmd, which is restricted to commands visible
- // via FCVAR_CLIENTCMD_CAN_EXECUTE.
- kCommandSrcClientCmd,
-
- // Typed in at the console or via a user key-bind. Generally unrestricted, although
- // the client will throttle commands sent to the server this way to 16 per second.
- kCommandSrcUserInput,
-
- // Came in over a net connection as a clc_stringcmd
- // host_client will be valid during this state.
- //
- // Restricted to FCVAR_GAMEDLL commands (but not convars) and special non-ConCommand
- // server commands hardcoded into gameplay code (e.g. "joingame")
- kCommandSrcNetClient,
-
- // Received from the server as the client
- //
- // Restricted to commands with FCVAR_SERVER_CAN_EXECUTE
- kCommandSrcNetServer,
-
- // Being played back from a demo file
- //
- // Not currently restricted by convar flag, but some commands manually ignore calls
- // from this source. FIXME: Should be heavily restricted as demo commands can come
- // from untrusted sources.
- kCommandSrcDemoFile,
-
- // Invalid value used when cleared
- kCommandSrcInvalid = -1
-};
-
-typedef ECommandTarget_t (*Cbuf_GetCurrentPlayerType)();
-extern Cbuf_GetCurrentPlayerType Cbuf_GetCurrentPlayer;
-
-// compared to the defs i've seen, this is missing an arg, it could be nTickInterval or source, not sure, guessing it's source
-typedef void (*Cbuf_AddTextType)(ECommandTarget_t eTarget, const char* text, cmd_source_t source);
-extern Cbuf_AddTextType Cbuf_AddText;
-
-typedef void (*Cbuf_ExecuteType)();
-extern Cbuf_ExecuteType Cbuf_Execute;
-
-// commandline stuff
-class CCommandLine
-{
- public:
- // based on the defs in the 2013 source sdk, but for some reason has an extra function (may be another CreateCmdLine overload?)
- // these seem to line up with what they should be though
- virtual void CreateCmdLine(const char* commandline) {}
- virtual void CreateCmdLine(int argc, char** argv) {}
- virtual void unknown() {}
- virtual const char* GetCmdLine(void) const {}
-
- virtual const char* CheckParm(const char* psz, const char** ppszValue = 0) const {}
- virtual void RemoveParm() const {}
- virtual void AppendParm(const char* pszParm, const char* pszValues) {}
-
- virtual const char* ParmValue(const char* psz, const char* pDefaultVal = 0) const {}
- virtual int ParmValue(const char* psz, int nDefaultVal) const {}
- virtual float ParmValue(const char* psz, float flDefaultVal) const {}
-
- virtual int ParmCount() const {}
- virtual int FindParm(const char* psz) const {}
- virtual const char* GetParm(int nIndex) const {}
- virtual void SetParm(int nIndex, char const* pParm) {}
-
- // virtual const char** GetParms() const {}
-};
-
-// hoststate stuff
-enum HostState_t
-{
- HS_NEW_GAME = 0,
- HS_LOAD_GAME,
- HS_CHANGE_LEVEL_SP,
- HS_CHANGE_LEVEL_MP,
- HS_RUN,
- HS_GAME_SHUTDOWN,
- HS_SHUTDOWN,
- HS_RESTART,
-};
-
-struct CHostState
-{
- public:
- HostState_t m_iCurrentState;
- HostState_t m_iNextState;
-
- float m_vecLocation[3];
- float m_angLocation[3];
-
- char m_levelName[32];
- char m_mapGroupName[32];
- char m_landmarkName[32];
- char m_saveName[32];
- float m_flShortFrameTime; // run a few one-tick frames to avoid large timesteps while loading assets
-
- bool m_activeGame;
- bool m_bRememberLocation;
- bool m_bBackgroundLevel;
- bool m_bWaitingForConnection;
- bool m_bLetToolsOverrideLoadGameEnts; // During a load game, this tells Foundry to override ents that are selected in Hammer.
- bool m_bSplitScreenConnect;
- bool m_bGameHasShutDownAndFlushedMemory; // This is false once we load a map into memory, and set to true once the map is unloaded and
- // all memory flushed
- bool m_bWorkshopMapDownloadPending;
-};
-
-extern CHostState* g_pHostState;
-
-// cengine stuff
-enum EngineQuitState
-{
- QUIT_NOTQUITTING = 0,
- QUIT_TODESKTOP,
- QUIT_RESTART
-};
-
-enum EngineState_t
-{
- DLL_INACTIVE = 0, // no dll
- DLL_ACTIVE, // engine is focused
- DLL_CLOSE, // closing down dll
- DLL_RESTART, // engine is shutting down but will restart right away
- DLL_PAUSED, // engine is paused, can become active from this state
-};
-
-class CEngine
-{
- public:
- virtual void unknown() {} // unsure if this is where
- virtual bool Load(bool dedicated, const char* baseDir) {}
- virtual void Unload() {}
- virtual void SetNextState(EngineState_t iNextState) {}
- virtual EngineState_t GetState() {}
- virtual void Frame() {}
- virtual double GetFrameTime() {}
- virtual float GetCurTime() {}
-
- EngineQuitState m_nQuitting;
- EngineState_t m_nDllState;
- EngineState_t m_nNextDllState;
- double m_flCurrentTime;
- float m_flFrameTime;
- double m_flPreviousTime;
- float m_flFilteredTime;
- float m_flMinFrameTime; // Expected duration of a frame, or zero if it is unlimited.
-};
-
-extern CEngine* g_pEngine;
-
-enum server_state_t
-{
- ss_dead = 0, // Dead
- ss_loading, // Spawning
- ss_active, // Running
- ss_paused, // Running, but paused
-};
-
-extern server_state_t* sv_m_State;
-
-// network stuff
-extern ConVar* Cvar_hostport;
-
-// playlist stuff
-typedef const char* (*GetCurrentPlaylistType)();
-extern GetCurrentPlaylistType GetCurrentPlaylistName;
-
-typedef void (*SetCurrentPlaylistType)(const char* playlistName);
-extern SetCurrentPlaylistType SetCurrentPlaylist;
-
-typedef void (*SetPlaylistVarOverrideType)(const char* varName, const char* value);
-extern SetPlaylistVarOverrideType SetPlaylistVarOverride;
-
-typedef char* (*GetCurrentPlaylistVarType)(const char* varName, bool useOverrides);
-extern GetCurrentPlaylistVarType GetCurrentPlaylistVar;
-
-// server entity stuff
-typedef void* (*Server_GetEntityByIndexType)(int index);
-extern Server_GetEntityByIndexType Server_GetEntityByIndex;
-
-// auth
-extern char* g_LocalPlayerUserID;
-extern char* g_LocalPlayerOriginToken;
-
-// misc stuff
-typedef void (*ErrorType)(const char* fmt, ...);
-extern ErrorType Error;
-
-typedef CCommandLine* (*CommandLineType)();
-extern CommandLineType CommandLine;
-
-typedef double (*Plat_FloatTimeType)();
-extern Plat_FloatTimeType Plat_FloatTime;
-
-typedef bool (*ThreadInServerFrameThreadType)();
-extern ThreadInServerFrameThreadType ThreadInServerFrameThread;
-
-typedef void* (*GetBaseLocalClientType)();
-extern GetBaseLocalClientType GetBaseLocalClient;
-
-void InitialiseEngineGameUtilFunctions(HMODULE baseAddress);
-void InitialiseServerGameUtilFunctions(HMODULE baseAddress);
-void InitialiseTier0GameUtilFunctions(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/hooks.cpp b/NorthstarDedicatedTest/hooks.cpp
deleted file mode 100644
index cc99341a..00000000
--- a/NorthstarDedicatedTest/hooks.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-#include "pch.h"
-#include "hooks.h"
-#include "hookutils.h"
-#include "sigscanning.h"
-#include "dedicated.h"
-
-#include <wchar.h>
-#include <iostream>
-#include <vector>
-#include <fstream>
-#include <sstream>
-#include <filesystem>
-#include <Psapi.h>
-
-typedef LPSTR (*GetCommandLineAType)();
-LPSTR GetCommandLineAHook();
-
-typedef HMODULE (*LoadLibraryExAType)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
-HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
-
-typedef HMODULE (*LoadLibraryAType)(LPCSTR lpLibFileName);
-HMODULE LoadLibraryAHook(LPCSTR lpLibFileName);
-
-typedef HMODULE (*LoadLibraryExWType)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
-HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
-
-typedef HMODULE (*LoadLibraryWType)(LPCWSTR lpLibFileName);
-HMODULE LoadLibraryWHook(LPCWSTR lpLibFileName);
-
-GetCommandLineAType GetCommandLineAOriginal;
-LoadLibraryExAType LoadLibraryExAOriginal;
-LoadLibraryAType LoadLibraryAOriginal;
-LoadLibraryExWType LoadLibraryExWOriginal;
-LoadLibraryWType LoadLibraryWOriginal;
-
-void InstallInitialHooks()
-{
- if (MH_Initialize() != MH_OK)
- spdlog::error("MH_Initialize (minhook initialization) failed");
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, &GetCommandLineA, &GetCommandLineAHook, reinterpret_cast<LPVOID*>(&GetCommandLineAOriginal));
- ENABLER_CREATEHOOK(hook, &LoadLibraryExA, &LoadLibraryExAHook, reinterpret_cast<LPVOID*>(&LoadLibraryExAOriginal));
- ENABLER_CREATEHOOK(hook, &LoadLibraryA, &LoadLibraryAHook, reinterpret_cast<LPVOID*>(&LoadLibraryAOriginal));
- ENABLER_CREATEHOOK(hook, &LoadLibraryExW, &LoadLibraryExWHook, reinterpret_cast<LPVOID*>(&LoadLibraryExWOriginal));
- ENABLER_CREATEHOOK(hook, &LoadLibraryW, &LoadLibraryWHook, reinterpret_cast<LPVOID*>(&LoadLibraryWOriginal));
-}
-
-LPSTR GetCommandLineAHook()
-{
- static char* cmdlineModified;
- static char* cmdlineOrg;
-
- if (cmdlineOrg == nullptr || cmdlineModified == nullptr)
- {
- cmdlineOrg = GetCommandLineAOriginal();
- bool isDedi = strstr(cmdlineOrg, "-dedicated"); // well, this one has to be a real argument
- bool ignoreStartupArgs = strstr(cmdlineOrg, "-nostartupargs");
-
- std::string args;
- std::ifstream cmdlineArgFile;
-
- // it looks like CommandLine() prioritizes parameters apprearing first, so we want the real commandline to take priority
- // not to mention that cmdlineOrg starts with the EXE path
- args.append(cmdlineOrg);
- args.append(" ");
-
- // append those from the file
-
- if (!ignoreStartupArgs)
- {
-
- cmdlineArgFile = std::ifstream(!isDedi ? "ns_startup_args.txt" : "ns_startup_args_dedi.txt");
-
- if (cmdlineArgFile)
- {
- std::stringstream argBuffer;
- argBuffer << cmdlineArgFile.rdbuf();
- cmdlineArgFile.close();
-
- // if some other command line option includes "-northstar" in the future then you have to refactor this check to check with
- // both either space after or ending with
- if (!isDedi && argBuffer.str().find("-northstar") != std::string::npos)
- MessageBoxA(
- NULL,
- "The \"-northstar\" command line option is NOT supposed to go into ns_startup_args.txt file!\n\nThis option is "
- "supposed to go into Origin/Steam game launch options, and then you are supposed to launch the original "
- "Titanfall2.exe "
- "rather than NorthstarLauncher.exe to make use of it.",
- "Northstar Warning",
- MB_ICONWARNING);
-
- args.append(argBuffer.str());
- }
- }
-
- auto len = args.length();
- cmdlineModified = new char[len + 1];
- if (!cmdlineModified)
- {
- spdlog::error("malloc failed for command line");
- return cmdlineOrg;
- }
- memcpy(cmdlineModified, args.c_str(), len + 1);
-
- spdlog::info("Command line: {}", cmdlineModified);
- }
-
- return cmdlineModified;
-}
-
-// dll load callback stuff
-// this allows for code to register callbacks to be run as soon as a dll is loaded, mainly to allow for patches to be made on dll load
-struct DllLoadCallback
-{
- std::string dll;
- DllLoadCallbackFuncType callback;
- bool called;
-};
-
-std::vector<DllLoadCallback*> dllLoadCallbacks;
-
-void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback)
-{
- DllLoadCallback* callbackStruct = new DllLoadCallback;
- callbackStruct->dll = dll;
- callbackStruct->callback = callback;
- callbackStruct->called = false;
-
- dllLoadCallbacks.push_back(callbackStruct);
-}
-
-void AddDllLoadCallbackForDedicatedServer(std::string dll, DllLoadCallbackFuncType callback)
-{
- if (!IsDedicated())
- return;
-
- DllLoadCallback* callbackStruct = new DllLoadCallback;
- callbackStruct->dll = dll;
- callbackStruct->callback = callback;
- callbackStruct->called = false;
-
- dllLoadCallbacks.push_back(callbackStruct);
-}
-
-void AddDllLoadCallbackForClient(std::string dll, DllLoadCallbackFuncType callback)
-{
- if (IsDedicated())
- return;
-
- DllLoadCallback* callbackStruct = new DllLoadCallback;
- callbackStruct->dll = dll;
- callbackStruct->callback = callback;
- callbackStruct->called = false;
-
- dllLoadCallbacks.push_back(callbackStruct);
-}
-
-void CallLoadLibraryACallbacks(LPCSTR lpLibFileName, HMODULE moduleAddress)
-{
- for (auto& callbackStruct : dllLoadCallbacks)
- {
- if (!callbackStruct->called &&
- strstr(lpLibFileName + (strlen(lpLibFileName) - callbackStruct->dll.length()), callbackStruct->dll.c_str()) != nullptr)
- {
- callbackStruct->callback(moduleAddress);
- callbackStruct->called = true;
- }
- }
-}
-
-void CallLoadLibraryWCallbacks(LPCWSTR lpLibFileName, HMODULE moduleAddress)
-{
- for (auto& callbackStruct : dllLoadCallbacks)
- {
- std::wstring wcharStrDll = std::wstring(callbackStruct->dll.begin(), callbackStruct->dll.end());
- const wchar_t* callbackDll = wcharStrDll.c_str();
- if (!callbackStruct->called && wcsstr(lpLibFileName + (wcslen(lpLibFileName) - wcharStrDll.length()), callbackDll) != nullptr)
- {
- callbackStruct->callback(moduleAddress);
- callbackStruct->called = true;
- }
- }
-}
-
-void CallAllPendingDLLLoadCallbacks()
-{
- HMODULE hMods[1024];
- HANDLE hProcess = GetCurrentProcess();
- DWORD cbNeeded;
- unsigned int i;
-
- // Get a list of all the modules in this process.
- if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
- {
- for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
- {
- wchar_t szModName[MAX_PATH];
-
- // Get the full path to the module's file.
- if (GetModuleFileNameExW(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
- {
- CallLoadLibraryWCallbacks(szModName, hMods[i]);
- }
- }
- }
-}
-
-HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
-{
- HMODULE moduleAddress = LoadLibraryExAOriginal(lpLibFileName, hFile, dwFlags);
-
- if (moduleAddress)
- {
- CallLoadLibraryACallbacks(lpLibFileName, moduleAddress);
- }
-
- return moduleAddress;
-}
-
-HMODULE LoadLibraryAHook(LPCSTR lpLibFileName)
-{
- HMODULE moduleAddress = LoadLibraryAOriginal(lpLibFileName);
-
- if (moduleAddress)
- {
- CallLoadLibraryACallbacks(lpLibFileName, moduleAddress);
- }
-
- return moduleAddress;
-}
-
-HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
-{
- HMODULE moduleAddress = LoadLibraryExWOriginal(lpLibFileName, hFile, dwFlags);
-
- if (moduleAddress)
- {
- CallLoadLibraryWCallbacks(lpLibFileName, moduleAddress);
- }
-
- return moduleAddress;
-}
-
-HMODULE LoadLibraryWHook(LPCWSTR lpLibFileName)
-{
- HMODULE moduleAddress = LoadLibraryWOriginal(lpLibFileName);
-
- if (moduleAddress)
- {
- CallLoadLibraryWCallbacks(lpLibFileName, moduleAddress);
- }
-
- return moduleAddress;
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/hooks.h b/NorthstarDedicatedTest/hooks.h
deleted file mode 100644
index ab7b3d64..00000000
--- a/NorthstarDedicatedTest/hooks.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-#include <string>
-
-void InstallInitialHooks();
-
-typedef void (*DllLoadCallbackFuncType)(HMODULE moduleAddress);
-void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback);
-void AddDllLoadCallbackForDedicatedServer(std::string dll, DllLoadCallbackFuncType callback);
-void AddDllLoadCallbackForClient(std::string dll, DllLoadCallbackFuncType callback);
-
-void CallAllPendingDLLLoadCallbacks(); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/hookutils.cpp b/NorthstarDedicatedTest/hookutils.cpp
deleted file mode 100644
index f5df3996..00000000
--- a/NorthstarDedicatedTest/hookutils.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "pch.h"
-#include "hookutils.h"
-
-#include <iostream>
-
-void HookEnabler::CreateHook(LPVOID ppTarget, LPVOID ppDetour, LPVOID* ppOriginal, const char* targetName)
-{
- // the macro for this uses ppTarget's name as targetName, and this typically starts with &
- // targetname is used for debug stuff and debug output is nicer if we don't have this
- if (*targetName == '&')
- targetName++;
-
- if (MH_CreateHook(ppTarget, ppDetour, ppOriginal) == MH_OK)
- {
- HookTarget* target = new HookTarget;
- target->targetAddress = ppTarget;
- target->targetName = (char*)targetName;
-
- m_hookTargets.push_back(target);
- }
- else
- {
- if (targetName != nullptr)
- spdlog::error("MH_CreateHook failed for function {}", targetName);
- else
- spdlog::error("MH_CreateHook failed for unknown function");
- }
-}
-
-HookEnabler::~HookEnabler()
-{
- for (auto& hook : m_hookTargets)
- {
- if (MH_EnableHook(hook->targetAddress) != MH_OK)
- {
- if (hook->targetName != nullptr)
- spdlog::error("MH_EnableHook failed for function {}", hook->targetName);
- else
- spdlog::error("MH_EnableHook failed for unknown function");
- }
- else
- spdlog::info("Enabling hook {}", hook->targetName);
- }
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/hookutils.h b/NorthstarDedicatedTest/hookutils.h
deleted file mode 100644
index 47ec12bf..00000000
--- a/NorthstarDedicatedTest/hookutils.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include <vector>
-
-// Enables all hooks created with the HookEnabler object when it goes out of scope and handles hook errors
-class HookEnabler
-{
- private:
- struct HookTarget
- {
- char* targetName;
- LPVOID targetAddress;
- };
-
- std::vector<HookTarget*> m_hookTargets;
-
- public:
- void CreateHook(LPVOID ppTarget, LPVOID ppDetour, LPVOID* ppOriginal, const char* targetName = nullptr);
- ~HookEnabler();
-};
-
-// macro to call HookEnabler::CreateHook with the hook's name
-#define ENABLER_CREATEHOOK(enabler, ppTarget, ppDetour, ppOriginal) enabler.CreateHook(ppTarget, ppDetour, ppOriginal, #ppDetour) \ No newline at end of file
diff --git a/NorthstarDedicatedTest/keyvalues.h b/NorthstarDedicatedTest/keyvalues.h
deleted file mode 100644
index b7de850d..00000000
--- a/NorthstarDedicatedTest/keyvalues.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseKeyValues(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/languagehooks.h b/NorthstarDedicatedTest/languagehooks.h
deleted file mode 100644
index 55b591e0..00000000
--- a/NorthstarDedicatedTest/languagehooks.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseTier0LanguageHooks(HMODULE baseAddress);
diff --git a/NorthstarDedicatedTest/latencyflex.cpp b/NorthstarDedicatedTest/latencyflex.cpp
deleted file mode 100644
index 4ac1c760..00000000
--- a/NorthstarDedicatedTest/latencyflex.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "pch.h"
-#include "latencyflex.h"
-#include "hookutils.h"
-#include "convar.h"
-
-typedef void (*OnRenderStartType)();
-OnRenderStartType OnRenderStart;
-
-ConVar* Cvar_r_latencyflex;
-
-HMODULE m_lfxModule {};
-typedef void (*PFN_winelfx_WaitAndBeginFrame)();
-PFN_winelfx_WaitAndBeginFrame m_winelfx_WaitAndBeginFrame {};
-
-void OnRenderStartHook()
-{
- if (Cvar_r_latencyflex->GetInt())
- m_winelfx_WaitAndBeginFrame();
-
- OnRenderStart();
-}
-
-void InitialiseLatencyFleX(HMODULE baseAddress)
-{
- // Connect to the LatencyFleX service
- // LatencyFleX is an open source vendor agnostic replacement for Nvidia Reflex input latency reduction technology.
- // https://ishitatsuyuki.github.io/post/latencyflex/
- m_lfxModule = LoadLibraryA("latencyflex_wine.dll");
-
- if (m_lfxModule == nullptr)
- {
- spdlog::info("Unable to load LatencyFleX library, LatencyFleX disabled.");
- return;
- }
-
- m_winelfx_WaitAndBeginFrame =
- reinterpret_cast<PFN_winelfx_WaitAndBeginFrame>(reinterpret_cast<void*>(GetProcAddress(m_lfxModule, "winelfx_WaitAndBeginFrame")));
- spdlog::info("LatencyFleX initialized.");
-
- Cvar_r_latencyflex = new ConVar("r_latencyflex", "1", FCVAR_ARCHIVE, "Whether or not to use LatencyFleX input latency reduction.");
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1952C0, &OnRenderStartHook, reinterpret_cast<LPVOID*>(&OnRenderStart));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/latencyflex.h b/NorthstarDedicatedTest/latencyflex.h
deleted file mode 100644
index db801261..00000000
--- a/NorthstarDedicatedTest/latencyflex.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void InitialiseLatencyFleX(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/logging.h b/NorthstarDedicatedTest/logging.h
deleted file mode 100644
index 2e78c81a..00000000
--- a/NorthstarDedicatedTest/logging.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#pragma once
-#include "context.h"
-
-void CreateLogFiles();
-void InitialiseLogging();
-void InitialiseEngineSpewFuncHooks(HMODULE baseAddress);
-void InitialiseClientPrintHooks(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp
deleted file mode 100644
index 38268e60..00000000
--- a/NorthstarDedicatedTest/masterserver.cpp
+++ /dev/null
@@ -1,1366 +0,0 @@
-#include "pch.h"
-#include "masterserver.h"
-#include "concommand.h"
-#include "gameutils.h"
-#include "hookutils.h"
-#include "serverauthentication.h"
-#include "gameutils.h"
-#include "rapidjson/document.h"
-#include "rapidjson/stringbuffer.h"
-#include "rapidjson/writer.h"
-#include "rapidjson/error/en.h"
-#include "modmanager.h"
-#include "misccommands.h"
-#include <cstring>
-#include <regex>
-#include "version.h"
-// NOTE for anyone reading this: we used to use httplib for requests here, but it had issues, so we're moving to curl now for masterserver
-// requests so httplib is used exclusively for server stuff now
-
-ConVar* Cvar_ns_masterserver_hostname;
-ConVar* Cvar_ns_report_server_to_masterserver;
-ConVar* Cvar_ns_report_sp_server_to_masterserver;
-
-ConVar* Cvar_ns_server_name;
-ConVar* Cvar_ns_server_desc;
-ConVar* Cvar_ns_server_password;
-
-ConVar* Cvar_ns_curl_log_enable;
-
-// Source ConVar
-ConVar* Cvar_hostname;
-
-MasterServerManager* g_MasterServerManager;
-
-typedef void (*CHostState__State_NewGameType)(CHostState* hostState);
-CHostState__State_NewGameType CHostState__State_NewGame;
-
-typedef void (*CHostState__State_ChangeLevelMPType)(CHostState* hostState);
-CHostState__State_ChangeLevelMPType CHostState__State_ChangeLevelMP;
-
-typedef void (*CHostState__State_ChangeLevelSPType)(CHostState* hostState);
-CHostState__State_ChangeLevelSPType CHostState__State_ChangeLevelSP;
-
-typedef void (*CHostState__State_GameShutdownType)(CHostState* hostState);
-CHostState__State_GameShutdownType CHostState__State_GameShutdown;
-
-// Convert a hex digit char to integer.
-inline int hctod(char c)
-{
- if (c >= 'A' && c <= 'F')
- {
- return c - 'A' + 10;
- }
- else if (c >= 'a' && c <= 'f')
- {
- return c - 'a' + 10;
- }
- else
- {
- return c - '0';
- }
-}
-
-// This function interprets all 4-hexadecimal-digit unicode codepoint characters like \u4E2D to UTF-8 encoding.
-std::string unescape_unicode(const std::string& str)
-{
- std::string result;
- std::regex r("\\\\u([a-f\\d]{4})", std::regex::icase);
- auto matches_begin = std::sregex_iterator(str.begin(), str.end(), r);
- auto matches_end = std::sregex_iterator();
- std::smatch last_match;
- for (std::sregex_iterator i = matches_begin; i != matches_end; ++i)
- {
- last_match = *i;
- result.append(last_match.prefix());
- unsigned int cp = 0;
- for (int i = 2; i <= 5; ++i)
- {
- cp *= 16;
- cp += hctod(last_match.str()[i]);
- }
- if (cp <= 0x7F)
- {
- result.push_back(cp);
- }
- else if (cp <= 0x7FF)
- {
- result.push_back((cp >> 6) | 0b11000000 & (~(1 << 5)));
- result.push_back(cp & ((1 << 6) - 1) | 0b10000000 & (~(1 << 6)));
- }
- else if (cp <= 0xFFFF)
- {
- result.push_back((cp >> 12) | 0b11100000 & (~(1 << 4)));
- result.push_back((cp >> 6) & ((1 << 6) - 1) | 0b10000000 & (~(1 << 6)));
- result.push_back(cp & ((1 << 6) - 1) | 0b10000000 & (~(1 << 6)));
- }
- }
- if (!last_match.ready())
- {
- return str;
- }
- else
- {
- result.append(last_match.suffix());
- }
- return result;
-}
-
-void UpdateServerInfoFromUnicodeToUTF8()
-{
- g_MasterServerManager->ns_auth_srvName = unescape_unicode(Cvar_ns_server_name->GetString());
- g_MasterServerManager->ns_auth_srvDesc = unescape_unicode(Cvar_ns_server_desc->GetString());
-}
-
-const char* HttplibErrorToString(httplib::Error error)
-{
- switch (error)
- {
- case httplib::Error::Success:
- return "httplib::Error::Success";
- case httplib::Error::Unknown:
- return "httplib::Error::Unknown";
- case httplib::Error::Connection:
- return "httplib::Error::Connection";
- case httplib::Error::BindIPAddress:
- return "httplib::Error::BindIPAddress";
- case httplib::Error::Read:
- return "httplib::Error::Read";
- case httplib::Error::Write:
- return "httplib::Error::Write";
- case httplib::Error::ExceedRedirectCount:
- return "httplib::Error::ExceedRedirectCount";
- case httplib::Error::Canceled:
- return "httplib::Error::Canceled";
- case httplib::Error::SSLConnection:
- return "httplib::Error::SSLConnection";
- case httplib::Error::SSLLoadingCerts:
- return "httplib::Error::SSLLoadingCerts";
- case httplib::Error::SSLServerVerification:
- return "httplib::Error::SSLServerVerification";
- case httplib::Error::UnsupportedMultipartBoundaryChars:
- return "httplib::Error::UnsupportedMultipartBoundaryChars";
- }
-
- return "";
-}
-
-RemoteServerInfo::RemoteServerInfo(
- const char* newId,
- const char* newName,
- const char* newDescription,
- const char* newMap,
- const char* newPlaylist,
- int newPlayerCount,
- int newMaxPlayers,
- bool newRequiresPassword)
-{
- // passworded servers don't have public ips
- requiresPassword = newRequiresPassword;
-
- strncpy((char*)id, newId, sizeof(id));
- id[sizeof(id) - 1] = 0;
- strncpy((char*)name, newName, sizeof(name));
- name[sizeof(name) - 1] = 0;
-
- description = std::string(newDescription);
-
- strncpy((char*)map, newMap, sizeof(map));
- map[sizeof(map) - 1] = 0;
- strncpy((char*)playlist, newPlaylist, sizeof(playlist));
- playlist[sizeof(playlist) - 1] = 0;
-
- playerCount = newPlayerCount;
- maxPlayers = newMaxPlayers;
-}
-
-void MasterServerManager::SetCommonHttpClientOptions(CURL* curl)
-{
- curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
- curl_easy_setopt(curl, CURLOPT_VERBOSE, Cvar_ns_curl_log_enable->GetBool());
- curl_easy_setopt(curl, CURLOPT_USERAGENT, &NSUserAgent);
- // curl_easy_setopt(curl, CURLOPT_STDERR, stdout);
- if (CommandLine()->FindParm("-msinsecure")) // TODO: this check doesn't seem to work
- {
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- }
-}
-
-void MasterServerManager::ClearServerList()
-{
- // this doesn't really do anything lol, probably isn't threadsafe
- m_requestingServerList = true;
-
- m_remoteServers.clear();
-
- m_requestingServerList = false;
-}
-
-size_t CurlWriteToStringBufferCallback(char* contents, size_t size, size_t nmemb, void* userp)
-{
- ((std::string*)userp)->append((char*)contents, size * nmemb);
- return size * nmemb;
-}
-
-void MasterServerManager::AuthenticateOriginWithMasterServer(char* uid, char* originToken)
-{
- if (m_bOriginAuthWithMasterServerInProgress)
- return;
-
- // do this here so it's instantly set
- m_bOriginAuthWithMasterServerInProgress = true;
- std::string uidStr(uid);
- std::string tokenStr(originToken);
-
- std::thread requestThread(
- [this, uidStr, tokenStr]()
- {
- spdlog::info("Trying to authenticate with northstar masterserver for user {}", uidStr);
-
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
- std::string readBuffer;
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format("{}/client/origin_auth?id={}&token={}", Cvar_ns_masterserver_hostname->GetString(), uidStr, tokenStr).c_str());
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- {
- m_successfullyConnected = true;
-
- rapidjson_document originAuthInfo;
- originAuthInfo.Parse(readBuffer.c_str());
-
- if (originAuthInfo.HasParseError())
- {
- spdlog::error(
- "Failed reading origin auth info response: encountered parse error \"{}\"",
- rapidjson::GetParseError_En(originAuthInfo.GetParseError()));
- goto REQUEST_END_CLEANUP;
- }
-
- if (!originAuthInfo.IsObject() || !originAuthInfo.HasMember("success"))
- {
- spdlog::error("Failed reading origin auth info response: malformed response object {}", readBuffer);
- goto REQUEST_END_CLEANUP;
- }
-
- if (originAuthInfo["success"].IsTrue() && originAuthInfo.HasMember("token") && originAuthInfo["token"].IsString())
- {
- strncpy(m_ownClientAuthToken, originAuthInfo["token"].GetString(), sizeof(m_ownClientAuthToken));
- m_ownClientAuthToken[sizeof(m_ownClientAuthToken) - 1] = 0;
- spdlog::info("Northstar origin authentication completed successfully!");
- }
- else
- spdlog::error("Northstar origin authentication failed");
- }
- else
- {
- spdlog::error("Failed performing northstar origin auth: error {}", curl_easy_strerror(result));
- m_successfullyConnected = false;
- }
-
- // we goto this instead of returning so we always hit this
- REQUEST_END_CLEANUP:
- m_bOriginAuthWithMasterServerInProgress = false;
- m_bOriginAuthWithMasterServerDone = true;
- curl_easy_cleanup(curl);
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::RequestServerList()
-{
- // do this here so it's instantly set on call for scripts
- m_scriptRequestingServerList = true;
-
- std::thread requestThread(
- [this]()
- {
- // make sure we never have 2 threads writing at once
- // i sure do hope this is actually threadsafe
- while (m_requestingServerList)
- Sleep(100);
-
- m_requestingServerList = true;
- m_scriptRequestingServerList = true;
-
- spdlog::info("Requesting server list from {}", Cvar_ns_masterserver_hostname->GetString());
-
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(curl, CURLOPT_URL, fmt::format("{}/client/servers", Cvar_ns_masterserver_hostname->GetString()).c_str());
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- {
- m_successfullyConnected = true;
-
- rapidjson_document serverInfoJson;
- serverInfoJson.Parse(readBuffer.c_str());
-
- if (serverInfoJson.HasParseError())
- {
- spdlog::error(
- "Failed reading masterserver response: encountered parse error \"{}\"",
- rapidjson::GetParseError_En(serverInfoJson.GetParseError()));
- goto REQUEST_END_CLEANUP;
- }
-
- if (serverInfoJson.IsObject() && serverInfoJson.HasMember("error"))
- {
- spdlog::error("Failed reading masterserver response: got fastify error response");
- spdlog::error(readBuffer);
- goto REQUEST_END_CLEANUP;
- }
-
- if (!serverInfoJson.IsArray())
- {
- spdlog::error("Failed reading masterserver response: root object is not an array");
- goto REQUEST_END_CLEANUP;
- }
-
- rapidjson::GenericArray<false, rapidjson_document::GenericValue> serverArray = serverInfoJson.GetArray();
-
- spdlog::info("Got {} servers", serverArray.Size());
-
- for (auto& serverObj : serverArray)
- {
- if (!serverObj.IsObject())
- {
- spdlog::error("Failed reading masterserver response: member of server array is not an object");
- goto REQUEST_END_CLEANUP;
- }
-
- // todo: verify json props are fine before adding to m_remoteServers
- if (!serverObj.HasMember("id") || !serverObj["id"].IsString() || !serverObj.HasMember("name") ||
- !serverObj["name"].IsString() || !serverObj.HasMember("description") || !serverObj["description"].IsString() ||
- !serverObj.HasMember("map") || !serverObj["map"].IsString() || !serverObj.HasMember("playlist") ||
- !serverObj["playlist"].IsString() || !serverObj.HasMember("playerCount") || !serverObj["playerCount"].IsNumber() ||
- !serverObj.HasMember("maxPlayers") || !serverObj["maxPlayers"].IsNumber() || !serverObj.HasMember("hasPassword") ||
- !serverObj["hasPassword"].IsBool() || !serverObj.HasMember("modInfo") || !serverObj["modInfo"].HasMember("Mods") ||
- !serverObj["modInfo"]["Mods"].IsArray())
- {
- spdlog::error("Failed reading masterserver response: malformed server object");
- continue;
- };
-
- const char* id = serverObj["id"].GetString();
-
- RemoteServerInfo* newServer = nullptr;
-
- bool createNewServerInfo = true;
- for (RemoteServerInfo& server : m_remoteServers)
- {
- // if server already exists, update info rather than adding to it
- if (!strncmp((const char*)server.id, id, 32))
- {
- server = RemoteServerInfo(
- id,
- serverObj["name"].GetString(),
- serverObj["description"].GetString(),
- serverObj["map"].GetString(),
- serverObj["playlist"].GetString(),
- serverObj["playerCount"].GetInt(),
- serverObj["maxPlayers"].GetInt(),
- serverObj["hasPassword"].IsTrue());
- newServer = &server;
- createNewServerInfo = false;
- break;
- }
- }
-
- // server didn't exist
- if (createNewServerInfo)
- newServer = &m_remoteServers.emplace_back(
- id,
- serverObj["name"].GetString(),
- serverObj["description"].GetString(),
- serverObj["map"].GetString(),
- serverObj["playlist"].GetString(),
- serverObj["playerCount"].GetInt(),
- serverObj["maxPlayers"].GetInt(),
- serverObj["hasPassword"].IsTrue());
-
- newServer->requiredMods.clear();
- for (auto& requiredMod : serverObj["modInfo"]["Mods"].GetArray())
- {
- RemoteModInfo modInfo;
-
- if (!requiredMod.HasMember("RequiredOnClient") || !requiredMod["RequiredOnClient"].IsTrue())
- continue;
-
- if (!requiredMod.HasMember("Name") || !requiredMod["Name"].IsString())
- continue;
- modInfo.Name = requiredMod["Name"].GetString();
-
- if (!requiredMod.HasMember("Version") || !requiredMod["Version"].IsString())
- continue;
- modInfo.Version = requiredMod["Version"].GetString();
-
- newServer->requiredMods.push_back(modInfo);
- }
- // Can probably re-enable this later with a -verbose flag, but slows down loading of the server browser quite a bit as
- // is
- // spdlog::info(
- // "Server {} on map {} with playlist {} has {}/{} players", serverObj["name"].GetString(),
- // serverObj["map"].GetString(), serverObj["playlist"].GetString(), serverObj["playerCount"].GetInt(),
- // serverObj["maxPlayers"].GetInt());
- }
-
- std::sort(
- m_remoteServers.begin(),
- m_remoteServers.end(),
- [](RemoteServerInfo& a, RemoteServerInfo& b) { return a.playerCount > b.playerCount; });
- }
- else
- {
- spdlog::error("Failed requesting servers: error {}", curl_easy_strerror(result));
- m_successfullyConnected = false;
- }
-
- // we goto this instead of returning so we always hit this
- REQUEST_END_CLEANUP:
- m_requestingServerList = false;
- m_scriptRequestingServerList = false;
- curl_easy_cleanup(curl);
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::RequestMainMenuPromos()
-{
- m_bHasMainMenuPromoData = false;
-
- std::thread requestThread(
- [this]()
- {
- while (m_bOriginAuthWithMasterServerInProgress || !m_bOriginAuthWithMasterServerDone)
- Sleep(500);
-
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(
- curl, CURLOPT_URL, fmt::format("{}/client/mainmenupromos", Cvar_ns_masterserver_hostname->GetString()).c_str());
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- {
- m_successfullyConnected = true;
-
- rapidjson_document mainMenuPromoJson;
- mainMenuPromoJson.Parse(readBuffer.c_str());
-
- if (mainMenuPromoJson.HasParseError())
- {
- spdlog::error(
- "Failed reading masterserver main menu promos response: encountered parse error \"{}\"",
- rapidjson::GetParseError_En(mainMenuPromoJson.GetParseError()));
- goto REQUEST_END_CLEANUP;
- }
-
- if (!mainMenuPromoJson.IsObject())
- {
- spdlog::error("Failed reading masterserver main menu promos response: root object is not an object");
- goto REQUEST_END_CLEANUP;
- }
-
- if (mainMenuPromoJson.HasMember("error"))
- {
- spdlog::error("Failed reading masterserver response: got fastify error response");
- spdlog::error(readBuffer);
- goto REQUEST_END_CLEANUP;
- }
-
- if (!mainMenuPromoJson.HasMember("newInfo") || !mainMenuPromoJson["newInfo"].IsObject() ||
- !mainMenuPromoJson["newInfo"].HasMember("Title1") || !mainMenuPromoJson["newInfo"]["Title1"].IsString() ||
- !mainMenuPromoJson["newInfo"].HasMember("Title2") || !mainMenuPromoJson["newInfo"]["Title2"].IsString() ||
- !mainMenuPromoJson["newInfo"].HasMember("Title3") || !mainMenuPromoJson["newInfo"]["Title3"].IsString() ||
-
- !mainMenuPromoJson.HasMember("largeButton") || !mainMenuPromoJson["largeButton"].IsObject() ||
- !mainMenuPromoJson["largeButton"].HasMember("Title") || !mainMenuPromoJson["largeButton"]["Title"].IsString() ||
- !mainMenuPromoJson["largeButton"].HasMember("Text") || !mainMenuPromoJson["largeButton"]["Text"].IsString() ||
- !mainMenuPromoJson["largeButton"].HasMember("Url") || !mainMenuPromoJson["largeButton"]["Url"].IsString() ||
- !mainMenuPromoJson["largeButton"].HasMember("ImageIndex") ||
- !mainMenuPromoJson["largeButton"]["ImageIndex"].IsNumber() ||
-
- !mainMenuPromoJson.HasMember("smallButton1") || !mainMenuPromoJson["smallButton1"].IsObject() ||
- !mainMenuPromoJson["smallButton1"].HasMember("Title") || !mainMenuPromoJson["smallButton1"]["Title"].IsString() ||
- !mainMenuPromoJson["smallButton1"].HasMember("Url") || !mainMenuPromoJson["smallButton1"]["Url"].IsString() ||
- !mainMenuPromoJson["smallButton1"].HasMember("ImageIndex") ||
- !mainMenuPromoJson["smallButton1"]["ImageIndex"].IsNumber() ||
-
- !mainMenuPromoJson.HasMember("smallButton2") || !mainMenuPromoJson["smallButton2"].IsObject() ||
- !mainMenuPromoJson["smallButton2"].HasMember("Title") || !mainMenuPromoJson["smallButton2"]["Title"].IsString() ||
- !mainMenuPromoJson["smallButton2"].HasMember("Url") || !mainMenuPromoJson["smallButton2"]["Url"].IsString() ||
- !mainMenuPromoJson["smallButton2"].HasMember("ImageIndex") ||
- !mainMenuPromoJson["smallButton2"]["ImageIndex"].IsNumber())
- {
- spdlog::error("Failed reading masterserver main menu promos response: malformed json object");
- goto REQUEST_END_CLEANUP;
- }
-
- m_MainMenuPromoData.newInfoTitle1 = mainMenuPromoJson["newInfo"]["Title1"].GetString();
- m_MainMenuPromoData.newInfoTitle2 = mainMenuPromoJson["newInfo"]["Title2"].GetString();
- m_MainMenuPromoData.newInfoTitle3 = mainMenuPromoJson["newInfo"]["Title3"].GetString();
-
- m_MainMenuPromoData.largeButtonTitle = mainMenuPromoJson["largeButton"]["Title"].GetString();
- m_MainMenuPromoData.largeButtonText = mainMenuPromoJson["largeButton"]["Text"].GetString();
- m_MainMenuPromoData.largeButtonUrl = mainMenuPromoJson["largeButton"]["Url"].GetString();
- m_MainMenuPromoData.largeButtonImageIndex = mainMenuPromoJson["largeButton"]["ImageIndex"].GetInt();
-
- m_MainMenuPromoData.smallButton1Title = mainMenuPromoJson["smallButton1"]["Title"].GetString();
- m_MainMenuPromoData.smallButton1Url = mainMenuPromoJson["smallButton1"]["Url"].GetString();
- m_MainMenuPromoData.smallButton1ImageIndex = mainMenuPromoJson["smallButton1"]["ImageIndex"].GetInt();
-
- m_MainMenuPromoData.smallButton2Title = mainMenuPromoJson["smallButton2"]["Title"].GetString();
- m_MainMenuPromoData.smallButton2Url = mainMenuPromoJson["smallButton2"]["Url"].GetString();
- m_MainMenuPromoData.smallButton2ImageIndex = mainMenuPromoJson["smallButton2"]["ImageIndex"].GetInt();
-
- m_bHasMainMenuPromoData = true;
- }
- else
- {
- spdlog::error("Failed requesting main menu promos: error {}", curl_easy_strerror(result));
- m_successfullyConnected = false;
- }
-
- REQUEST_END_CLEANUP:
- // nothing lol
- curl_easy_cleanup(curl);
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::AuthenticateWithOwnServer(char* uid, char* playerToken)
-{
- // dont wait, just stop if we're trying to do 2 auth requests at once
- if (m_authenticatingWithGameServer)
- return;
-
- m_authenticatingWithGameServer = true;
- m_scriptAuthenticatingWithGameServer = true;
- m_successfullyAuthenticatedWithGameServer = false;
-
- std::string uidStr(uid);
- std::string tokenStr(playerToken);
-
- std::thread requestThread(
- [this, uidStr, tokenStr]()
- {
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format("{}/client/auth_with_self?id={}&playerToken={}", Cvar_ns_masterserver_hostname->GetString(), uidStr, tokenStr)
- .c_str());
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- {
- m_successfullyConnected = true;
-
- rapidjson_document authInfoJson;
- authInfoJson.Parse(readBuffer.c_str());
-
- if (authInfoJson.HasParseError())
- {
- spdlog::error(
- "Failed reading masterserver authentication response: encountered parse error \"{}\"",
- rapidjson::GetParseError_En(authInfoJson.GetParseError()));
- goto REQUEST_END_CLEANUP;
- }
-
- if (!authInfoJson.IsObject())
- {
- spdlog::error("Failed reading masterserver authentication response: root object is not an object");
- goto REQUEST_END_CLEANUP;
- }
-
- if (authInfoJson.HasMember("error"))
- {
- spdlog::error("Failed reading masterserver response: got fastify error response");
- spdlog::error(readBuffer);
- goto REQUEST_END_CLEANUP;
- }
-
- if (!authInfoJson["success"].IsTrue())
- {
- spdlog::error("Authentication with masterserver failed: \"success\" is not true");
- goto REQUEST_END_CLEANUP;
- }
-
- if (!authInfoJson.HasMember("success") || !authInfoJson.HasMember("id") || !authInfoJson["id"].IsString() ||
- !authInfoJson.HasMember("authToken") || !authInfoJson["authToken"].IsString() ||
- !authInfoJson.HasMember("persistentData") || !authInfoJson["persistentData"].IsArray())
- {
- spdlog::error("Failed reading masterserver authentication response: malformed json object");
- goto REQUEST_END_CLEANUP;
- }
-
- AuthData newAuthData {};
- strncpy(newAuthData.uid, authInfoJson["id"].GetString(), sizeof(newAuthData.uid));
- newAuthData.uid[sizeof(newAuthData.uid) - 1] = 0;
-
- newAuthData.pdataSize = authInfoJson["persistentData"].GetArray().Size();
- newAuthData.pdata = new char[newAuthData.pdataSize];
- // memcpy(newAuthData.pdata, authInfoJson["persistentData"].GetString(), newAuthData.pdataSize);
-
- int i = 0;
- // note: persistentData is a uint8array because i had problems getting strings to behave, it sucks but it's just how it be
- // unfortunately potentially refactor later
- for (auto& byte : authInfoJson["persistentData"].GetArray())
- {
- if (!byte.IsUint() || byte.GetUint() > 255)
- {
- spdlog::error("Failed reading masterserver authentication response: malformed json object");
- goto REQUEST_END_CLEANUP;
- }
-
- newAuthData.pdata[i++] = static_cast<char>(byte.GetUint());
- }
-
- std::lock_guard<std::mutex> guard(g_ServerAuthenticationManager->m_authDataMutex);
- g_ServerAuthenticationManager->m_authData.clear();
- g_ServerAuthenticationManager->m_authData.insert(std::make_pair(authInfoJson["authToken"].GetString(), newAuthData));
-
- m_successfullyAuthenticatedWithGameServer = true;
- }
- else
- {
- spdlog::error("Failed authenticating with own server: error {}", curl_easy_strerror(result));
- m_successfullyConnected = false;
- m_successfullyAuthenticatedWithGameServer = false;
- m_scriptAuthenticatingWithGameServer = false;
- }
-
- REQUEST_END_CLEANUP:
- m_authenticatingWithGameServer = false;
- m_scriptAuthenticatingWithGameServer = false;
-
- if (m_bNewgameAfterSelfAuth)
- {
- // pretty sure this is threadsafe?
- Cbuf_AddText(Cbuf_GetCurrentPlayer(), "ns_end_reauth_and_leave_to_lobby", cmd_source_t::kCommandSrcCode);
- m_bNewgameAfterSelfAuth = false;
- }
-
- curl_easy_cleanup(curl);
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::AuthenticateWithServer(char* uid, char* playerToken, char* serverId, char* password)
-{
- // dont wait, just stop if we're trying to do 2 auth requests at once
- if (m_authenticatingWithGameServer)
- return;
-
- m_authenticatingWithGameServer = true;
- m_scriptAuthenticatingWithGameServer = true;
- m_successfullyAuthenticatedWithGameServer = false;
-
- std::string uidStr(uid);
- std::string tokenStr(playerToken);
- std::string serverIdStr(serverId);
- std::string passwordStr(password);
-
- std::thread requestThread(
- [this, uidStr, tokenStr, serverIdStr, passwordStr]()
- {
- // esnure that any persistence saving is done, so we know masterserver has newest
- while (m_savingPersistentData)
- Sleep(100);
-
- spdlog::info("Attempting authentication with server of id \"{}\"", serverIdStr);
-
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
-
- {
- char* escapedPassword = curl_easy_escape(curl, passwordStr.c_str(), passwordStr.length());
-
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format(
- "{}/client/auth_with_server?id={}&playerToken={}&server={}&password={}",
- Cvar_ns_masterserver_hostname->GetString(),
- uidStr,
- tokenStr,
- serverIdStr,
- escapedPassword)
- .c_str());
-
- curl_free(escapedPassword);
- }
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- {
- m_successfullyConnected = true;
-
- rapidjson_document connectionInfoJson;
- connectionInfoJson.Parse(readBuffer.c_str());
-
- if (connectionInfoJson.HasParseError())
- {
- spdlog::error(
- "Failed reading masterserver authentication response: encountered parse error \"{}\"",
- rapidjson::GetParseError_En(connectionInfoJson.GetParseError()));
- goto REQUEST_END_CLEANUP;
- }
-
- if (!connectionInfoJson.IsObject())
- {
- spdlog::error("Failed reading masterserver authentication response: root object is not an object");
- goto REQUEST_END_CLEANUP;
- }
-
- if (connectionInfoJson.HasMember("error"))
- {
- spdlog::error("Failed reading masterserver response: got fastify error response");
- spdlog::error(readBuffer);
- goto REQUEST_END_CLEANUP;
- }
-
- if (!connectionInfoJson["success"].IsTrue())
- {
- spdlog::error("Authentication with masterserver failed: \"success\" is not true");
- goto REQUEST_END_CLEANUP;
- }
-
- if (!connectionInfoJson.HasMember("success") || !connectionInfoJson.HasMember("ip") ||
- !connectionInfoJson["ip"].IsString() || !connectionInfoJson.HasMember("port") ||
- !connectionInfoJson["port"].IsNumber() || !connectionInfoJson.HasMember("authToken") ||
- !connectionInfoJson["authToken"].IsString())
- {
- spdlog::error("Failed reading masterserver authentication response: malformed json object");
- goto REQUEST_END_CLEANUP;
- }
-
- m_pendingConnectionInfo.ip.S_un.S_addr = inet_addr(connectionInfoJson["ip"].GetString());
- m_pendingConnectionInfo.port = (unsigned short)connectionInfoJson["port"].GetUint();
-
- strncpy(m_pendingConnectionInfo.authToken, connectionInfoJson["authToken"].GetString(), 31);
- m_pendingConnectionInfo.authToken[31] = 0;
-
- m_hasPendingConnectionInfo = true;
- m_successfullyAuthenticatedWithGameServer = true;
- }
- else
- {
- spdlog::error("Failed authenticating with server: error {}", curl_easy_strerror(result));
- m_successfullyConnected = false;
- m_successfullyAuthenticatedWithGameServer = false;
- m_scriptAuthenticatingWithGameServer = false;
- }
-
- REQUEST_END_CLEANUP:
- m_authenticatingWithGameServer = false;
- m_scriptAuthenticatingWithGameServer = false;
- curl_easy_cleanup(curl);
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::AddSelfToServerList(
- int port, int authPort, char* name, char* description, char* map, char* playlist, int maxPlayers, char* password)
-{
- if (!Cvar_ns_report_server_to_masterserver->GetBool())
- return;
-
- if (!Cvar_ns_report_sp_server_to_masterserver->GetBool() && !strncmp(map, "sp_", 3))
- {
- m_bRequireClientAuth = false;
- return;
- }
-
- m_bRequireClientAuth = true;
-
- std::string strName(name);
- std::string strDescription(description);
- std::string strMap(map);
- std::string strPlaylist(playlist);
- std::string strPassword(password);
-
- std::thread requestThread(
- [this, port, authPort, strName, strDescription, strMap, strPlaylist, maxPlayers, strPassword]
- {
- m_ownServerId[0] = 0;
- m_ownServerAuthToken[0] = 0;
-
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(curl, CURLOPT_POST, 1L);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
-
- curl_mime* mime = curl_mime_init(curl);
- curl_mimepart* part = curl_mime_addpart(mime);
-
- curl_mime_data(part, m_ownModInfoJson.c_str(), m_ownModInfoJson.size());
- curl_mime_name(part, "modinfo");
- curl_mime_filename(part, "modinfo.json");
- curl_mime_type(part, "application/json");
-
- curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
-
- // format every paramter because computers hate me
- {
- char* nameEscaped = curl_easy_escape(curl, strName.c_str(), strName.length());
- char* descEscaped = curl_easy_escape(curl, strDescription.c_str(), strDescription.length());
- char* mapEscaped = curl_easy_escape(curl, strMap.c_str(), strMap.length());
- char* playlistEscaped = curl_easy_escape(curl, strPlaylist.c_str(), strPlaylist.length());
- char* passwordEscaped = curl_easy_escape(curl, strPassword.c_str(), strPassword.length());
-
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format(
- "{}/server/add_server?port={}&authPort={}&name={}&description={}&map={}&playlist={}&maxPlayers={}&password={}",
- Cvar_ns_masterserver_hostname->GetString(),
- port,
- authPort,
- nameEscaped,
- descEscaped,
- mapEscaped,
- playlistEscaped,
- maxPlayers,
- passwordEscaped)
- .c_str());
-
- curl_free(nameEscaped);
- curl_free(descEscaped);
- curl_free(mapEscaped);
- curl_free(playlistEscaped);
- curl_free(passwordEscaped);
- }
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- {
- m_successfullyConnected = true;
-
- rapidjson_document serverAddedJson;
- serverAddedJson.Parse(readBuffer.c_str());
-
- if (serverAddedJson.HasParseError())
- {
- spdlog::error(
- "Failed reading masterserver authentication response: encountered parse error \"{}\"",
- rapidjson::GetParseError_En(serverAddedJson.GetParseError()));
- goto REQUEST_END_CLEANUP;
- }
-
- if (!serverAddedJson.IsObject())
- {
- spdlog::error("Failed reading masterserver authentication response: root object is not an object");
- goto REQUEST_END_CLEANUP;
- }
-
- if (serverAddedJson.HasMember("error"))
- {
- spdlog::error("Failed reading masterserver response: got fastify error response");
- spdlog::error(readBuffer);
- goto REQUEST_END_CLEANUP;
- }
-
- if (!serverAddedJson["success"].IsTrue())
- {
- spdlog::error("Adding server to masterserver failed: \"success\" is not true");
- goto REQUEST_END_CLEANUP;
- }
-
- if (!serverAddedJson.HasMember("id") || !serverAddedJson["id"].IsString() ||
- !serverAddedJson.HasMember("serverAuthToken") || !serverAddedJson["serverAuthToken"].IsString())
- {
- spdlog::error("Failed reading masterserver response: malformed json object");
- goto REQUEST_END_CLEANUP;
- }
-
- strncpy(m_ownServerId, serverAddedJson["id"].GetString(), sizeof(m_ownServerId));
- m_ownServerId[sizeof(m_ownServerId) - 1] = 0;
-
- strncpy(m_ownServerAuthToken, serverAddedJson["serverAuthToken"].GetString(), sizeof(m_ownServerAuthToken));
- m_ownServerAuthToken[sizeof(m_ownServerAuthToken) - 1] = 0;
-
- // heartbeat thread
- // ideally this should actually be done in main thread, rather than on it's own thread, so it'd stop if server freezes
- std::thread heartbeatThread(
- [this]
- {
- Sleep(5000);
-
- // defensive check, as m_ownServer could be set to null during the Sleep(5000) above
- if (!*m_ownServerId)
- return;
-
- do
- {
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
-
- // send all registration info so we have all necessary info to reregister our server if masterserver goes down,
- // without a restart this isn't threadsafe :terror:
- {
- char* escapedNameNew = curl_easy_escape(curl, g_MasterServerManager->ns_auth_srvName.c_str(), NULL);
- char* escapedDescNew = curl_easy_escape(curl, g_MasterServerManager->ns_auth_srvDesc.c_str(), NULL);
- char* escapedMapNew = curl_easy_escape(curl, g_pHostState->m_levelName, NULL);
- char* escapedPlaylistNew = curl_easy_escape(curl, GetCurrentPlaylistName(), NULL);
- char* escapedPasswordNew = curl_easy_escape(curl, Cvar_ns_server_password->GetString(), NULL);
-
- int maxPlayers = 6;
- char* maxPlayersVar = GetCurrentPlaylistVar("max_players", false);
- if (maxPlayersVar) // GetCurrentPlaylistVar can return null so protect against this
- maxPlayers = std::stoi(maxPlayersVar);
-
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format(
- "{}/server/"
- "update_values?id={}&port={}&authPort={}&name={}&description={}&map={}&playlist={}&playerCount={}&"
- "maxPlayers={}&password={}",
- Cvar_ns_masterserver_hostname->GetString(),
- m_ownServerId,
- Cvar_hostport->GetInt(),
- Cvar_ns_player_auth_port->GetInt(),
- escapedNameNew,
- escapedDescNew,
- escapedMapNew,
- escapedPlaylistNew,
- g_ServerAuthenticationManager->m_additionalPlayerData.size(),
- maxPlayers,
- escapedPasswordNew)
- .c_str());
-
- curl_free(escapedNameNew);
- curl_free(escapedDescNew);
- curl_free(escapedMapNew);
- curl_free(escapedPlaylistNew);
- curl_free(escapedPasswordNew);
- }
-
- curl_mime* mime = curl_mime_init(curl);
- curl_mimepart* part = curl_mime_addpart(mime);
-
- curl_mime_data(part, m_ownModInfoJson.c_str(), m_ownModInfoJson.size());
- curl_mime_name(part, "modinfo");
- curl_mime_filename(part, "modinfo.json");
- curl_mime_type(part, "application/json");
-
- curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
-
- CURLcode result = curl_easy_perform(curl);
-
- // defensive check, as m_ownServerId could be set to null before this request gets processed
- if (!*m_ownServerId)
- return;
-
- if (result == CURLcode::CURLE_OK)
- {
- rapidjson_document serverAddedJson;
- serverAddedJson.Parse(readBuffer.c_str());
-
- if (!serverAddedJson.HasParseError() && serverAddedJson.IsObject())
- {
- if (serverAddedJson.HasMember("id") && serverAddedJson["id"].IsString())
- {
- strncpy(m_ownServerId, serverAddedJson["id"].GetString(), sizeof(m_ownServerId));
- m_ownServerId[sizeof(m_ownServerId) - 1] = 0;
- }
-
- if (serverAddedJson.HasMember("serverAuthToken") && serverAddedJson["serverAuthToken"].IsString())
- {
- strncpy(
- m_ownServerAuthToken,
- serverAddedJson["serverAuthToken"].GetString(),
- sizeof(m_ownServerAuthToken));
- m_ownServerAuthToken[sizeof(m_ownServerAuthToken) - 1] = 0;
- }
- }
- }
- else
- spdlog::warn("Heartbeat failed with error {}", curl_easy_strerror(result));
-
- curl_easy_cleanup(curl);
- Sleep(10000);
- } while (*m_ownServerId);
- });
-
- heartbeatThread.detach();
- }
- else
- {
- spdlog::error("Failed adding self to server list: error {}", curl_easy_strerror(result));
- m_successfullyConnected = false;
- }
-
- REQUEST_END_CLEANUP:
- curl_easy_cleanup(curl);
- curl_mime_free(mime);
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::UpdateServerMapAndPlaylist(char* map, char* playlist, int maxPlayers)
-{
- // dont call this if we don't have a server id
- if (!*m_ownServerId)
- return;
-
- std::string strMap(map);
- std::string strPlaylist(playlist);
-
- std::thread requestThread(
- [this, strMap, strPlaylist, maxPlayers]
- {
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
-
- // escape params
- {
- char* mapEscaped = curl_easy_escape(curl, strMap.c_str(), strMap.length());
- char* playlistEscaped = curl_easy_escape(curl, strPlaylist.c_str(), strPlaylist.length());
-
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format(
- "{}/server/update_values?id={}&map={}&playlist={}&maxPlayers={}",
- Cvar_ns_masterserver_hostname->GetString(),
- m_ownServerId,
- mapEscaped,
- playlistEscaped,
- maxPlayers)
- .c_str());
-
- curl_free(mapEscaped);
- curl_free(playlistEscaped);
- }
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- m_successfullyConnected = true;
- else
- m_successfullyConnected = false;
-
- curl_easy_cleanup(curl);
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::UpdateServerPlayerCount(int playerCount)
-{
- // dont call this if we don't have a server id
- if (!*m_ownServerId)
- return;
-
- std::thread requestThread(
- [this, playerCount]
- {
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format(
- "{}/server/update_values?id={}&playerCount={}", Cvar_ns_masterserver_hostname->GetString(), m_ownServerId, playerCount)
- .c_str());
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- m_successfullyConnected = true;
- else
- m_successfullyConnected = false;
-
- curl_easy_cleanup(curl);
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::WritePlayerPersistentData(char* playerId, char* pdata, size_t pdataSize)
-{
- // still call this if we don't have a server id, since lobbies that aren't port forwarded need to be able to call it
- m_savingPersistentData = true;
- if (!pdataSize)
- {
- spdlog::warn("attempted to write pdata of size 0!");
- return;
- }
-
- std::string strPlayerId(playerId);
- std::string strPdata(pdata, pdataSize);
-
- std::thread requestThread(
- [this, strPlayerId, strPdata, pdataSize]
- {
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format(
- "{}/accounts/write_persistence?id={}&serverId={}",
- Cvar_ns_masterserver_hostname->GetString(),
- strPlayerId,
- m_ownServerId)
- .c_str());
- curl_easy_setopt(curl, CURLOPT_POST, 1L);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
-
- curl_mime* mime = curl_mime_init(curl);
- curl_mimepart* part = curl_mime_addpart(mime);
-
- curl_mime_data(part, strPdata.c_str(), pdataSize);
- curl_mime_name(part, "pdata");
- curl_mime_filename(part, "file.pdata");
- curl_mime_type(part, "application/octet-stream");
-
- curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
-
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- m_successfullyConnected = true;
- else
- m_successfullyConnected = false;
-
- curl_easy_cleanup(curl);
-
- m_savingPersistentData = false;
- });
-
- requestThread.detach();
-}
-
-void MasterServerManager::RemoveSelfFromServerList()
-{
- // dont call this if we don't have a server id
- if (!*m_ownServerId || !Cvar_ns_report_server_to_masterserver->GetBool())
- return;
-
- std::thread requestThread(
- [this]
- {
- CURL* curl = curl_easy_init();
- SetCommonHttpClientOptions(curl);
-
- std::string readBuffer;
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteToStringBufferCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
- curl_easy_setopt(
- curl,
- CURLOPT_URL,
- fmt::format("{}/server/remove_server?id={}", Cvar_ns_masterserver_hostname->GetString(), m_ownServerId).c_str());
-
- *m_ownServerId = 0;
- CURLcode result = curl_easy_perform(curl);
-
- if (result == CURLcode::CURLE_OK)
- m_successfullyConnected = true;
- else
- m_successfullyConnected = false;
-
- curl_easy_cleanup(curl);
- });
-
- requestThread.detach();
-}
-
-void ConCommand_ns_fetchservers(const CCommand& args)
-{
- g_MasterServerManager->RequestServerList();
-}
-
-void CHostState__State_NewGameHook(CHostState* hostState)
-{
- Cbuf_AddText(Cbuf_GetCurrentPlayer(), "exec autoexec_ns_server", cmd_source_t::kCommandSrcCode);
- Cbuf_Execute();
-
- // need to do this to ensure we don't go to private match
- if (g_ServerAuthenticationManager->m_bNeedLocalAuthForNewgame)
- SetCurrentPlaylist("tdm");
-
- // net_data_block_enabled is required for sp, force it if we're on an sp map
- // sucks for security but just how it be
- if (!strncmp(g_pHostState->m_levelName, "sp_", 3))
- {
- Cbuf_AddText(Cbuf_GetCurrentPlayer(), "net_data_block_enabled 1", cmd_source_t::kCommandSrcCode);
- Cbuf_Execute();
- }
-
- CHostState__State_NewGame(hostState);
-
- int maxPlayers = 6;
- char* maxPlayersVar = GetCurrentPlaylistVar("max_players", false);
- if (maxPlayersVar) // GetCurrentPlaylistVar can return null so protect against this
- maxPlayers = std::stoi(maxPlayersVar);
-
- // Copy new server name cvar to source
- Cvar_hostname->SetValue(Cvar_ns_server_name->GetString());
- // This calls the function that converts unicode strings from servername and serverdesc to UTF-8
- UpdateServerInfoFromUnicodeToUTF8();
-
- g_MasterServerManager->AddSelfToServerList(
- Cvar_hostport->GetInt(),
- Cvar_ns_player_auth_port->GetInt(),
- (char*)Cvar_ns_server_name->GetString(),
- (char*)Cvar_ns_server_desc->GetString(),
- hostState->m_levelName,
- (char*)GetCurrentPlaylistName(),
- maxPlayers,
- (char*)Cvar_ns_server_password->GetString());
- g_ServerAuthenticationManager->StartPlayerAuthServer();
- g_ServerAuthenticationManager->m_bNeedLocalAuthForNewgame = false;
-}
-
-void CHostState__State_ChangeLevelMPHook(CHostState* hostState)
-{
- int maxPlayers = 6;
- char* maxPlayersVar = GetCurrentPlaylistVar("max_players", false);
- if (maxPlayersVar) // GetCurrentPlaylistVar can return null so protect against this
- maxPlayers = std::stoi(maxPlayersVar);
-
- // net_data_block_enabled is required for sp, force it if we're on an sp map
- // sucks for security but just how it be
- if (!strncmp(g_pHostState->m_levelName, "sp_", 3))
- {
- Cbuf_AddText(Cbuf_GetCurrentPlayer(), "net_data_block_enabled 1", cmd_source_t::kCommandSrcCode);
- Cbuf_Execute();
- }
-
- g_MasterServerManager->UpdateServerMapAndPlaylist(hostState->m_levelName, (char*)GetCurrentPlaylistName(), maxPlayers);
- CHostState__State_ChangeLevelMP(hostState);
-}
-
-void CHostState__State_ChangeLevelSPHook(CHostState* hostState)
-{
- // is this even called? genuinely i don't think so
- // from what i can tell, it's not called on mp=>sp change or sp=>sp change
- // so idk it's fucked
-
- int maxPlayers = 6;
- char* maxPlayersVar = GetCurrentPlaylistVar("max_players", false);
- if (maxPlayersVar) // GetCurrentPlaylistVar can return null so protect against this
- maxPlayers = std::stoi(maxPlayersVar);
-
- g_MasterServerManager->UpdateServerMapAndPlaylist(hostState->m_levelName, (char*)GetCurrentPlaylistName(), maxPlayers);
- CHostState__State_ChangeLevelSP(hostState);
-}
-
-void CHostState__State_GameShutdownHook(CHostState* hostState)
-{
- g_MasterServerManager->RemoveSelfFromServerList();
- g_ServerAuthenticationManager->StopPlayerAuthServer();
-
- CHostState__State_GameShutdown(hostState);
-}
-
-MasterServerManager::MasterServerManager() : m_pendingConnectionInfo {}, m_ownServerId {""}, m_ownClientAuthToken {""} {}
-
-void InitialiseSharedMasterServer(HMODULE baseAddress)
-{
- Cvar_ns_masterserver_hostname = new ConVar("ns_masterserver_hostname", "127.0.0.1", FCVAR_NONE, "");
- // unfortunately lib doesn't let us specify a port and still have https work
- // Cvar_ns_masterserver_port = new ConVar("ns_masterserver_port", "8080", FCVAR_NONE, "");
-
- Cvar_ns_server_name = new ConVar("ns_server_name", "Unnamed Northstar Server", FCVAR_GAMEDLL, "");
- Cvar_ns_server_desc = new ConVar("ns_server_desc", "Default server description", FCVAR_GAMEDLL, "");
- Cvar_ns_server_password = new ConVar("ns_server_password", "", FCVAR_GAMEDLL, "");
- Cvar_ns_report_server_to_masterserver = new ConVar("ns_report_server_to_masterserver", "1", FCVAR_GAMEDLL, "");
- Cvar_ns_report_sp_server_to_masterserver = new ConVar("ns_report_sp_server_to_masterserver", "0", FCVAR_GAMEDLL, "");
-
- Cvar_ns_curl_log_enable = new ConVar("ns_curl_log_enable", "0", FCVAR_NONE, "");
-
- Cvar_hostname = *(ConVar**)((char*)baseAddress + 0x1315bae8);
-
- g_MasterServerManager = new MasterServerManager;
-
- RegisterConCommand("ns_fetchservers", ConCommand_ns_fetchservers, "", FCVAR_CLIENTDLL);
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x16E7D0, CHostState__State_NewGameHook, reinterpret_cast<LPVOID*>(&CHostState__State_NewGame));
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x16E520,
- CHostState__State_ChangeLevelMPHook,
- reinterpret_cast<LPVOID*>(&CHostState__State_ChangeLevelMP));
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x16E5D0,
- CHostState__State_ChangeLevelSPHook,
- reinterpret_cast<LPVOID*>(&CHostState__State_ChangeLevelSP));
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x16E640,
- CHostState__State_GameShutdownHook,
- reinterpret_cast<LPVOID*>(&CHostState__State_GameShutdown));
-}
diff --git a/NorthstarDedicatedTest/masterserver.h b/NorthstarDedicatedTest/masterserver.h
deleted file mode 100644
index 10f91356..00000000
--- a/NorthstarDedicatedTest/masterserver.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#pragma once
-#include "convar.h"
-#include <WinSock2.h>
-#include <string>
-#include <cstring>
-struct RemoteModInfo
-{
- public:
- std::string Name;
- std::string Version;
-};
-
-class RemoteServerInfo
-{
- public:
- char id[33]; // 32 bytes + nullterminator
-
- // server info
- char name[64];
- std::string description;
- char map[32];
- char playlist[16];
- std::vector<RemoteModInfo> requiredMods;
-
- int playerCount;
- int maxPlayers;
-
- // connection stuff
- bool requiresPassword;
-
- public:
- RemoteServerInfo(
- const char* newId,
- const char* newName,
- const char* newDescription,
- const char* newMap,
- const char* newPlaylist,
- int newPlayerCount,
- int newMaxPlayers,
- bool newRequiresPassword);
-};
-
-struct RemoteServerConnectionInfo
-{
- public:
- char authToken[32];
-
- in_addr ip;
- unsigned short port;
-};
-
-struct MainMenuPromoData
-{
- public:
- std::string newInfoTitle1;
- std::string newInfoTitle2;
- std::string newInfoTitle3;
-
- std::string largeButtonTitle;
- std::string largeButtonText;
- std::string largeButtonUrl;
- int largeButtonImageIndex;
-
- std::string smallButton1Title;
- std::string smallButton1Url;
- int smallButton1ImageIndex;
-
- std::string smallButton2Title;
- std::string smallButton2Url;
- int smallButton2ImageIndex;
-};
-
-class MasterServerManager
-{
- private:
- bool m_requestingServerList = false;
- bool m_authenticatingWithGameServer = false;
-
- public:
- char m_ownServerId[33];
- char m_ownServerAuthToken[33];
- char m_ownClientAuthToken[33];
-
- std::string m_ownModInfoJson;
- std::string ns_auth_srvName; // Unicode unescaped version of Cvar_ns_auth_servername for support in cjk characters
- std::string ns_auth_srvDesc; // Unicode unescaped version of Cvar_ns_auth_serverdesc for support in cjk characters
-
- bool m_bOriginAuthWithMasterServerDone = false;
- bool m_bOriginAuthWithMasterServerInProgress = false;
-
- bool m_bRequireClientAuth = false;
- bool m_savingPersistentData = false;
-
- bool m_scriptRequestingServerList = false;
- bool m_successfullyConnected = true;
-
- bool m_bNewgameAfterSelfAuth = false;
- bool m_scriptAuthenticatingWithGameServer = false;
- bool m_successfullyAuthenticatedWithGameServer = false;
-
- bool m_hasPendingConnectionInfo = false;
- RemoteServerConnectionInfo m_pendingConnectionInfo;
-
- std::vector<RemoteServerInfo> m_remoteServers;
-
- bool m_bHasMainMenuPromoData = false;
- MainMenuPromoData m_MainMenuPromoData;
-
- private:
- void SetCommonHttpClientOptions(CURL* curl);
-
- public:
- MasterServerManager();
- void ClearServerList();
- void RequestServerList();
- void RequestMainMenuPromos();
- void AuthenticateOriginWithMasterServer(char* uid, char* originToken);
- void AuthenticateWithOwnServer(char* uid, char* playerToken);
- void AuthenticateWithServer(char* uid, char* playerToken, char* serverId, char* password);
- void
- AddSelfToServerList(int port, int authPort, char* name, char* description, char* map, char* playlist, int maxPlayers, char* password);
- void UpdateServerMapAndPlaylist(char* map, char* playlist, int playerCount);
- void UpdateServerPlayerCount(int playerCount);
- void WritePlayerPersistentData(char* playerId, char* pdata, size_t pdataSize);
- void RemoveSelfFromServerList();
-};
-std::string unescape_unicode(const std::string& str);
-void UpdateServerInfoFromUnicodeToUTF8();
-void InitialiseSharedMasterServer(HMODULE baseAddress);
-
-extern MasterServerManager* g_MasterServerManager;
-extern ConVar* Cvar_ns_masterserver_hostname;
-extern ConVar* Cvar_ns_server_password; \ No newline at end of file
diff --git a/NorthstarDedicatedTest/maxplayers.cpp b/NorthstarDedicatedTest/maxplayers.cpp
deleted file mode 100644
index 32f3b2ec..00000000
--- a/NorthstarDedicatedTest/maxplayers.cpp
+++ /dev/null
@@ -1,682 +0,0 @@
-#include "pch.h"
-#include "maxplayers.h"
-#include "gameutils.h"
-
-// never set this to anything below 32
-#define NEW_MAX_PLAYERS 64
-// dg note: the theoretical limit is actually 100, 76 works without entity issues, and 64 works without clientside prediction issues.
-
-#define PAD_NUMBER(number, boundary) (((number) + ((boundary)-1)) / (boundary)) * (boundary)
-
-// this is horrible
-constexpr int PlayerResource_Name_Start = 0; // Start of modded allocated space.
-constexpr int PlayerResource_Name_Size = ((NEW_MAX_PLAYERS + 1) * 8); // const char* m_szName[MAX_PLAYERS + 1];
-
-constexpr int PlayerResource_Ping_Start = PlayerResource_Name_Start + PlayerResource_Name_Size;
-constexpr int PlayerResource_Ping_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iPing[MAX_PLAYERS + 1];
-
-constexpr int PlayerResource_Team_Start = PlayerResource_Ping_Start + PlayerResource_Ping_Size;
-constexpr int PlayerResource_Team_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iTeam[MAX_PLAYERS + 1];
-
-constexpr int PlayerResource_PRHealth_Start = PlayerResource_Team_Start + PlayerResource_Team_Size;
-constexpr int PlayerResource_PRHealth_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iPRHealth[MAX_PLAYERS + 1];
-
-constexpr int PlayerResource_Connected_Start = PlayerResource_PRHealth_Start + PlayerResource_PRHealth_Size;
-constexpr int PlayerResource_Connected_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool) m_bConnected[MAX_PLAYERS + 1];
-
-constexpr int PlayerResource_Alive_Start = PlayerResource_Connected_Start + PlayerResource_Connected_Size;
-constexpr int PlayerResource_Alive_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool) m_bAlive[MAX_PLAYERS + 1];
-
-constexpr int PlayerResource_BoolStats_Start = PlayerResource_Alive_Start + PlayerResource_Alive_Size;
-constexpr int PlayerResource_BoolStats_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool idk) m_boolStats[MAX_PLAYERS + 1];
-
-constexpr int PlayerResource_KillStats_Start = PlayerResource_BoolStats_Start + PlayerResource_BoolStats_Size;
-constexpr int PlayerResource_KillStats_Length = PAD_NUMBER((NEW_MAX_PLAYERS + 1) * 6, 4);
-constexpr int PlayerResource_KillStats_Size = (PlayerResource_KillStats_Length * 6); // int m_killStats[MAX_PLAYERS + 1][6];
-
-constexpr int PlayerResource_ScoreStats_Start = PlayerResource_KillStats_Start + PlayerResource_KillStats_Size;
-constexpr int PlayerResource_ScoreStats_Length = PAD_NUMBER((NEW_MAX_PLAYERS + 1) * 5, 4);
-constexpr int PlayerResource_ScoreStats_Size = (PlayerResource_ScoreStats_Length * 4); // int m_scoreStats[MAX_PLAYERS + 1][5];
-
-// must be the usage of the last field to account for any possible paddings
-constexpr int PlayerResource_TotalSize = PlayerResource_ScoreStats_Start + PlayerResource_ScoreStats_Size;
-
-constexpr int Team_PlayerArray_AddedLength = NEW_MAX_PLAYERS - 32;
-constexpr int Team_PlayerArray_AddedSize = PAD_NUMBER(Team_PlayerArray_AddedLength * 8, 4);
-constexpr int Team_AddedSize = Team_PlayerArray_AddedSize;
-
-#include "NSMem.h"
-template <class T> void ChangeOffset(void* addr, unsigned int offset)
-{
- NSMem::BytePatch((uintptr_t)addr, (BYTE*)&offset, sizeof(T));
-}
-
-/*
-typedef bool(*MatchRecvPropsToSendProps_R_Type)(__int64 lookup, __int64 tableNameBroken, __int64 sendTable, __int64 recvTable);
-MatchRecvPropsToSendProps_R_Type MatchRecvPropsToSendProps_R_Original;
-
-bool MatchRecvPropsToSendProps_R_Hook(__int64 lookup, __int64 tableNameBroken, __int64 sendTable, __int64 recvTable)
-{
- const char* tableName = *(const char**)(sendTable + 0x118);
-
- spdlog::info("MatchRecvPropsToSendProps_R table name {}", tableName);
-
- bool orig = MatchRecvPropsToSendProps_R_Original(lookup, tableNameBroken, sendTable, recvTable);
- return orig;
-}
-
-typedef bool(*DataTable_SetupReceiveTableFromSendTable_Type)(__int64 sendTable, bool needsDecoder);
-DataTable_SetupReceiveTableFromSendTable_Type DataTable_SetupReceiveTableFromSendTable_Original;
-
-bool DataTable_SetupReceiveTableFromSendTable_Hook(__int64 sendTable, bool needsDecoder)
-{
- const char* tableName = *(const char**)(sendTable + 0x118);
-
- spdlog::info("DataTable_SetupReceiveTableFromSendTable table name {}", tableName);
- if (!strcmp(tableName, "m_bConnected")) {
- char f[64];
- sprintf_s(f, "%p", sendTable);
- MessageBoxA(0, f, "DataTable_SetupReceiveTableFromSendTable", 0);
- }
-
- return DataTable_SetupReceiveTableFromSendTable_Original(sendTable, needsDecoder);
-}
-*/
-
-typedef void* (*StringTables_CreateStringTable_Type)(
- __int64 thisptr, const char* name, int maxentries, int userdatafixedsize, int userdatanetworkbits, int flags);
-StringTables_CreateStringTable_Type StringTables_CreateStringTable_Original;
-
-void* StringTables_CreateStringTable_Hook(
- __int64 thisptr, const char* name, int maxentries, int userdatafixedsize, int userdatanetworkbits, int flags)
-{
- // Change the amount of entries to account for a bigger player amount
- if (!strcmp(name, "userinfo"))
- {
- int maxPlayersPowerOf2 = 1;
- while (maxPlayersPowerOf2 < NEW_MAX_PLAYERS)
- maxPlayersPowerOf2 <<= 1;
-
- maxentries = maxPlayersPowerOf2;
- }
-
- return StringTables_CreateStringTable_Original(thisptr, name, maxentries, userdatafixedsize, userdatanetworkbits, flags);
-}
-
-bool MaxPlayersIncreaseEnabled()
-{
- return CommandLine() && CommandLine()->CheckParm("-experimentalmaxplayersincrease");
-}
-
-void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress)
-{
- if (!MaxPlayersIncreaseEnabled())
- return;
-
- // patch GetPlayerLimits to ignore the boundary limit
- ChangeOffset<unsigned char>((char*)baseAddress + 0x116458, 0xEB); // jle => jmp
-
- // patch ED_Alloc to change nFirstIndex
- ChangeOffset<int>((char*)baseAddress + 0x18F46C + 1, NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1)
-
- // patch CGameServer::SpawnServer to change GetMaxClients inline
- ChangeOffset<int>((char*)baseAddress + 0x119543 + 2, NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1)
-
- // patch CGameServer::SpawnServer to change for loop
- ChangeOffset<unsigned char>((char*)baseAddress + 0x11957F + 2, NEW_MAX_PLAYERS); // original: 32
-
- // patch CGameServer::SpawnServer to change for loop (there are two)
- ChangeOffset<unsigned char>((char*)baseAddress + 0x119586 + 2, NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1)
-
- // patch max players somewhere in CClientState
- ChangeOffset<unsigned char>((char*)baseAddress + 0x1A162C + 2, NEW_MAX_PLAYERS - 1); // original: 31 (32 - 1)
-
- // patch max players in userinfo stringtable creation
- /*{
- int maxPlayersPowerOf2 = 1;
- while (maxPlayersPowerOf2 < NEW_MAX_PLAYERS)
- maxPlayersPowerOf2 <<= 1;
- ChangeOffset<unsigned char>((char*)baseAddress + 0x114B79 + 3, maxPlayersPowerOf2); // original: 32
- }*/
- // this is not supposed to work at all but it does on 64 players (how)
- // proper fix below
-
- // patch max players in userinfo stringtable creation loop
- ChangeOffset<unsigned char>((char*)baseAddress + 0x114C48 + 2, NEW_MAX_PLAYERS); // original: 32
-
- // do not load prebaked SendTable message list
- ChangeOffset<unsigned char>((char*)baseAddress + 0x75859, 0xEB); // jnz -> jmp
-
- HookEnabler hook;
-
- // ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x209000, &MatchRecvPropsToSendProps_R_Hook,
- // reinterpret_cast<LPVOID*>(&MatchRecvPropsToSendProps_R_Original)); ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1FACD0,
- // &DataTable_SetupReceiveTableFromSendTable_Hook, reinterpret_cast<LPVOID*>(&DataTable_SetupReceiveTableFromSendTable_Original));
-
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x22E220,
- &StringTables_CreateStringTable_Hook,
- reinterpret_cast<LPVOID*>(&StringTables_CreateStringTable_Original));
-}
-
-typedef void (*RunUserCmds_Type)(bool a1, float a2);
-RunUserCmds_Type RunUserCmds_Original;
-
-HMODULE serverBase = 0;
-auto RandomIntZeroMax = (__int64(__fastcall*)())0;
-
-// lazy rebuild
-void RunUserCmds_Hook(bool a1, float a2)
-{
- unsigned char v3; // bl
- int v5; // er14
- int i; // edi
- __int64 v7; // rax
- DWORD* v8; // rbx
- int v9; // edi
- __int64* v10; // rsi
- __int64 v11; // rax
- int v12; // er12
- __int64 v13; // rdi
- int v14; // ebx
- int v15; // eax
- __int64 v16; // r8
- int v17; // edx
- char v18; // r15
- char v19; // bp
- int v20; // esi
- __int64* v21; // rdi
- __int64 v22; // rcx
- bool v23; // al
- __int64 v24; // rax
- __int64 v25[NEW_MAX_PLAYERS]; // [rsp+20h] [rbp-138h] BYREF
-
- uintptr_t base = (__int64)serverBase;
- auto g_pGlobals = *(__int64*)(base + 0xBFBE08);
- __int64 globals = g_pGlobals;
-
- auto g_pEngineServer = *(__int64*)(base + 0xBFBD98);
-
- auto qword_1814D9648 = *(__int64*)(base + 0x14D9648);
- auto qword_1814DA408 = *(__int64*)(base + 0x14DA408);
- auto qword_1812107E8 = *(__int64*)(base + 0x12107E8);
- auto qword_1812105A8 = *(__int64*)(base + 0x12105A8);
-
- auto UTIL_PlayerByIndex = (__int64(__fastcall*)(int index))(base + 0x26AA10);
- auto sub_180485590 = (void(__fastcall*)(__int64))(base + 0x485590);
- auto sub_18058CD80 = (void(__fastcall*)(__int64))(base + 0x58CD80);
- auto sub_1805A6D90 = (void(__fastcall*)(__int64))(base + 0x5A6D90);
- auto sub_1805A6E50 = (bool(__fastcall*)(__int64, int, char))(base + 0x5A6E50);
- auto sub_1805A6C20 = (void(__fastcall*)(__int64))(base + 0x5A6C20);
-
- v3 = *(unsigned char*)(g_pGlobals + 73);
- if (*(DWORD*)(qword_1814D9648 + 92) &&
- ((*(unsigned __int8(__fastcall**)(__int64))(*(__int64*)g_pEngineServer + 32i64))(g_pEngineServer) ||
- !*(DWORD*)(qword_1814DA408 + 92)) &&
- v3)
- {
- globals = g_pGlobals;
- v5 = 1;
- for (i = 1; i <= *(DWORD*)(g_pGlobals + 52); ++i)
- {
- v7 = UTIL_PlayerByIndex(i);
- v8 = (DWORD*)v7;
- if (v7)
- {
- *(__int64*)(base + 0x1210420) = v7;
- *(float*)(g_pGlobals + 16) = a2;
- if (!a1)
- sub_18058CD80(v7);
- sub_1805A6D90((__int64)v8);
- }
- globals = g_pGlobals;
- }
- memset(v25, 0, sizeof(v25));
- v9 = 0;
- if (*(int*)(globals + 52) > 0)
- {
- v10 = v25;
- do
- {
- v11 = UTIL_PlayerByIndex(++v9);
- globals = g_pGlobals;
- *v10++ = v11;
- } while (v9 < *(DWORD*)(globals + 52));
- }
- v12 = *(DWORD*)(qword_1812107E8 + 92);
- if (*(DWORD*)(qword_1812105A8 + 92))
- {
- v13 = *(DWORD*)(globals + 52) - 1;
- if (v13 >= 1)
- {
- v14 = *(DWORD*)(globals + 52);
- do
- {
- v15 = RandomIntZeroMax();
- v16 = v25[v13--];
- v17 = v15 % v14--;
- v25[v13 + 1] = v25[v17];
- v25[v17] = v16;
- } while (v13 >= 1);
- globals = g_pGlobals;
- }
- }
- v18 = 1;
- do
- {
- v19 = 0;
- v20 = 0;
- if (*(int*)(globals + 52) > 0)
- {
- v21 = v25;
- do
- {
- v22 = *v21;
- if (*v21)
- {
- *(__int64*)(base + 0x1210420) = *v21;
- *(float*)(globals + 16) = a2;
- v23 = sub_1805A6E50(v22, v12, v18);
- globals = g_pGlobals;
- if (v23)
- v19 = 1;
- else
- *v21 = 0i64;
- }
- ++v20;
- ++v21;
- } while (v20 < *(DWORD*)(globals + 52));
- }
- v18 = 0;
- } while (v19);
- if (*(int*)(globals + 52) >= 1)
- {
- do
- {
- v24 = UTIL_PlayerByIndex(v5);
- if (v24)
- {
- *(__int64*)(base + 0x1210420) = v24;
- *(float*)(g_pGlobals + 16) = a2;
- sub_1805A6C20(v24);
- }
- ++v5;
- } while (v5 <= *(DWORD*)(g_pGlobals + 52));
- }
- sub_180485590(*(__int64*)(base + 0xB7B2D8));
- }
-}
-
-typedef __int64 (*SendPropArray2_Type)(__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn, unsigned char unk1);
-SendPropArray2_Type SendPropArray2_Original;
-
-__int64 __fastcall SendPropArray2_Hook(__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn, unsigned char unk1)
-{
- // Change the amount of elements to account for a bigger player amount
- if (!strcmp(name, "\"player_array\""))
- elements = NEW_MAX_PLAYERS;
-
- return SendPropArray2_Original(recvProp, elements, flags, name, proxyFn, unk1);
-}
-
-void InitialiseMaxPlayersOverride_Server(HMODULE baseAddress)
-{
- if (!MaxPlayersIncreaseEnabled())
- return;
-
- // get required data
- serverBase = GetModuleHandleA("server.dll");
- RandomIntZeroMax = (decltype(RandomIntZeroMax))(GetProcAddress(GetModuleHandleA("vstdlib.dll"), "RandomIntZeroMax"));
-
- // patch max players amount
- ChangeOffset<unsigned char>((char*)baseAddress + 0x9A44D + 3, NEW_MAX_PLAYERS); // 0x20 (32) => 0x80 (128)
-
- // patch SpawnGlobalNonRewinding to change forced edict index
- ChangeOffset<unsigned char>((char*)baseAddress + 0x2BC403 + 2, NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1)
-
- constexpr int CPlayerResource_OriginalSize = 4776;
- constexpr int CPlayerResource_AddedSize = PlayerResource_TotalSize;
- constexpr int CPlayerResource_ModifiedSize = CPlayerResource_OriginalSize + CPlayerResource_AddedSize;
-
- // CPlayerResource class allocation function - allocate a bigger amount to fit all new max player data
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C560A + 1, CPlayerResource_ModifiedSize);
-
- // DT_PlayerResource::m_iPing SendProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5059 + 2, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C50A8 + 2, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C50E2 + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_iPing DataMap
- ChangeOffset<unsigned int>((char*)baseAddress + 0xB94598, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB9459C, NEW_MAX_PLAYERS + 1);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB945C0, PlayerResource_Ping_Size);
-
- // DT_PlayerResource::m_iTeam SendProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5110 + 2, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C519C + 2, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C517E + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_iTeam DataMap
- ChangeOffset<unsigned int>((char*)baseAddress + 0xB94600, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB94604, NEW_MAX_PLAYERS + 1);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB94628, PlayerResource_Team_Size);
-
- // DT_PlayerResource::m_iPRHealth SendProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C51C0 + 2, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5204 + 2, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C523E + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_iPRHealth DataMap
- ChangeOffset<unsigned int>((char*)baseAddress + 0xB94668, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB9466C, NEW_MAX_PLAYERS + 1);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB94690, PlayerResource_PRHealth_Size);
-
- // DT_PlayerResource::m_bConnected SendProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C526C + 2, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C52B4 + 2, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C52EE + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_bConnected DataMap
- ChangeOffset<unsigned int>((char*)baseAddress + 0xB946D0, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB946D4, NEW_MAX_PLAYERS + 1);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB946F8, PlayerResource_Connected_Size);
-
- // DT_PlayerResource::m_bAlive SendProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5321 + 2, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5364 + 2, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C539E + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_bAlive DataMap
- ChangeOffset<unsigned int>((char*)baseAddress + 0xB94738, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB9473C, NEW_MAX_PLAYERS + 1);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB94760, PlayerResource_Alive_Size);
-
- // DT_PlayerResource::m_boolStats SendProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C53CC + 2, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5414 + 2, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C544E + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_boolStats DataMap
- ChangeOffset<unsigned int>((char*)baseAddress + 0xB947A0, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB947A4, NEW_MAX_PLAYERS + 1);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB947C8, PlayerResource_BoolStats_Size);
-
- // DT_PlayerResource::m_killStats SendProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C547C + 2, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C54E2 + 2, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C54FE + 4, PlayerResource_KillStats_Length);
-
- // DT_PlayerResource::m_killStats DataMap
- ChangeOffset<unsigned int>((char*)baseAddress + 0xB94808, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB9480C, PlayerResource_KillStats_Length);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB94830, PlayerResource_KillStats_Size);
-
- // DT_PlayerResource::m_scoreStats SendProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5528 + 2, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5576 + 2, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C5584 + 4, PlayerResource_ScoreStats_Length);
-
- // DT_PlayerResource::m_scoreStats DataMap
- ChangeOffset<unsigned int>((char*)baseAddress + 0xB94870, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB94874, PlayerResource_ScoreStats_Length);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xB94898, PlayerResource_ScoreStats_Size);
-
- // CPlayerResource::UpdatePlayerData - m_bConnected
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C66EE + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C672E + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
-
- // CPlayerResource::UpdatePlayerData - m_iPing
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C6394 + 4, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C63DB + 4, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
-
- // CPlayerResource::UpdatePlayerData - m_iTeam
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C63FD + 4, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C6442 + 4, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
-
- // CPlayerResource::UpdatePlayerData - m_iPRHealth
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C645B + 4, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C64A0 + 4, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
-
- // CPlayerResource::UpdatePlayerData - m_bConnected
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C64AA + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C64F0 + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
-
- // CPlayerResource::UpdatePlayerData - m_bAlive
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C650A + 4, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C654F + 4, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
-
- // CPlayerResource::UpdatePlayerData - m_boolStats
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C6557 + 4, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C65A5 + 4, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
-
- // CPlayerResource::UpdatePlayerData - m_scoreStats
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C65C2 + 3, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C65E3 + 4, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
-
- // CPlayerResource::UpdatePlayerData - m_killStats
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C6654 + 3, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x5C665B + 3, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
-
- // GameLoop::RunUserCmds - rebuild
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x483D10, &RunUserCmds_Hook, reinterpret_cast<LPVOID*>(&RunUserCmds_Original));
-
- *(DWORD*)((char*)baseAddress + 0x14E7390) = 0;
- auto DT_PlayerResource_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x5C4FE0);
- DT_PlayerResource_Construct();
-
- constexpr int CTeam_OriginalSize = 3336;
- constexpr int CTeam_AddedSize = Team_AddedSize;
- constexpr int CTeam_ModifiedSize = CTeam_OriginalSize + CTeam_AddedSize;
-
- // CTeam class allocation function - allocate a bigger amount to fit all new team player data
- ChangeOffset<unsigned int>((char*)baseAddress + 0x23924A + 1, CTeam_ModifiedSize);
-
- // CTeam::CTeam - increase memset length to clean newly allocated data
- ChangeOffset<unsigned int>((char*)baseAddress + 0x2395AE + 2, 256 + CTeam_AddedSize);
-
- // hook required to change the size of DT_Team::"player_array"
- HookEnabler hook2;
- ENABLER_CREATEHOOK(hook2, (char*)baseAddress + 0x12B130, &SendPropArray2_Hook, reinterpret_cast<LPVOID*>(&SendPropArray2_Original));
- hook2.~HookEnabler(); // force hook before calling construct function
-
- *(DWORD*)((char*)baseAddress + 0xC945A0) = 0;
- auto DT_Team_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x238F50);
- DT_Team_Construct();
-}
-
-typedef __int64 (*RecvPropArray2_Type)(__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn);
-RecvPropArray2_Type RecvPropArray2_Original;
-
-__int64 __fastcall RecvPropArray2_Hook(__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn)
-{
- // Change the amount of elements to account for a bigger player amount
- if (!strcmp(name, "\"player_array\""))
- elements = NEW_MAX_PLAYERS;
-
- return RecvPropArray2_Original(recvProp, elements, flags, name, proxyFn);
-}
-
-void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress)
-{
- if (!MaxPlayersIncreaseEnabled())
- return;
-
- constexpr int C_PlayerResource_OriginalSize = 5768;
- constexpr int C_PlayerResource_AddedSize = PlayerResource_TotalSize;
- constexpr int C_PlayerResource_ModifiedSize = C_PlayerResource_OriginalSize + C_PlayerResource_AddedSize;
-
- // C_PlayerResource class allocation function - allocate a bigger amount to fit all new max player data
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164C41 + 1, C_PlayerResource_ModifiedSize);
-
- // C_PlayerResource::C_PlayerResource - change loop end value
- ChangeOffset<unsigned char>((char*)baseAddress + 0x1640C4 + 2, NEW_MAX_PLAYERS - 32);
-
- // C_PlayerResource::C_PlayerResource - change m_szName address
- ChangeOffset<unsigned int>(
- (char*)baseAddress + 0x1640D0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class
-
- // C_PlayerResource::C_PlayerResource - change m_szName address
- ChangeOffset<unsigned int>(
- (char*)baseAddress + 0x1640D0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class
-
- // C_PlayerResource::C_PlayerResource - increase memset length to clean newly allocated data
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1640D0 + 3, 2244 + C_PlayerResource_AddedSize);
-
- // C_PlayerResource::UpdatePlayerName - change m_szName address
- ChangeOffset<unsigned int>((char*)baseAddress + 0x16431F + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName - change m_szName address 1
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1645B1 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName - change m_szName address 2
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1645C0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName - change m_szName address 3
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1645DD + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName internal func - change m_szName address 1
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164B71 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName internal func - change m_szName address 2
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164B9B + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 1
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164641 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 2
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164650 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 3
- ChangeOffset<unsigned int>((char*)baseAddress + 0x16466D + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 1
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164BA3 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 2
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164BCE + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 3
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164BE7 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
-
- // C_PlayerResource::m_szName
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc350f8, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc350f8 + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource size
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163415 + 6, C_PlayerResource_ModifiedSize);
-
- // DT_PlayerResource::m_iPing RecvProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163492 + 2, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1634D6 + 2, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163515 + 5, NEW_MAX_PLAYERS + 1);
-
- // C_PlayerResource::m_iPing
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc35170, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc35170 + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_iTeam RecvProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163549 + 2, C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1635C8 + 2, C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1635AD + 5, NEW_MAX_PLAYERS + 1);
-
- // C_PlayerResource::m_iTeam
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc351e8, C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc351e8 + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_iPRHealth RecvProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1635F9 + 2, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163625 + 2, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163675 + 5, NEW_MAX_PLAYERS + 1);
-
- // C_PlayerResource::m_iPRHealth
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc35260, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc35260 + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_bConnected RecvProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1636A9 + 2, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1636D5 + 2, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163725 + 5, NEW_MAX_PLAYERS + 1);
-
- // C_PlayerResource::m_bConnected
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc352d8, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc352d8 + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_bAlive RecvProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163759 + 2, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163785 + 2, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1637D5 + 5, NEW_MAX_PLAYERS + 1);
-
- // C_PlayerResource::m_bAlive
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc35350, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc35350 + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_boolStats RecvProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163809 + 2, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163835 + 2, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163885 + 5, NEW_MAX_PLAYERS + 1);
-
- // C_PlayerResource::m_boolStats
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc353c8, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc353c8 + 4, NEW_MAX_PLAYERS + 1);
-
- // DT_PlayerResource::m_killStats RecvProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1638B3 + 2, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1638E5 + 2, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163935 + 5, PlayerResource_KillStats_Length);
-
- // C_PlayerResource::m_killStats
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc35440, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc35440 + 4, PlayerResource_KillStats_Length);
-
- // DT_PlayerResource::m_scoreStats RecvProp
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163969 + 2, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x163995 + 2, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1639E5 + 5, PlayerResource_ScoreStats_Length);
-
- // C_PlayerResource::m_scoreStats
- ChangeOffset<unsigned int>((char*)baseAddress + 0xc354b8, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
- ChangeOffset<unsigned short>((char*)baseAddress + 0xc354b8 + 4, PlayerResource_ScoreStats_Length);
-
- // C_PlayerResource::GetPlayerName - change m_bConnected address
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164599 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
-
- // C_PlayerResource::GetPlayerName2 (?) - change m_bConnected address
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164629 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
-
- // C_PlayerResource::GetPlayerName internal func - change m_bConnected address
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164B13 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
-
- // Some other get name func (that seems to be unused) - change m_bConnected address
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164860 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
-
- // Some other get name func 2 (that seems to be unused too) - change m_bConnected address
- ChangeOffset<unsigned int>((char*)baseAddress + 0x164834 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
-
- *(DWORD*)((char*)baseAddress + 0xC35068) = 0;
- auto DT_PlayerResource_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x163400);
- DT_PlayerResource_Construct();
-
- constexpr int C_Team_OriginalSize = 3200;
- constexpr int C_Team_AddedSize = Team_AddedSize;
- constexpr int C_Team_ModifiedSize = C_Team_OriginalSize + C_Team_AddedSize;
-
- // C_Team class allocation function - allocate a bigger amount to fit all new team player data
- ChangeOffset<unsigned int>((char*)baseAddress + 0x182321 + 1, C_Team_ModifiedSize);
-
- // C_Team::C_Team - increase memset length to clean newly allocated data
- ChangeOffset<unsigned int>((char*)baseAddress + 0x1804A2 + 2, 256 + C_Team_AddedSize);
-
- // DT_Team size
- ChangeOffset<unsigned int>((char*)baseAddress + 0xC3AA0C, C_Team_ModifiedSize);
-
- // hook required to change the size of DT_Team::"player_array"
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1CEDA0, &RecvPropArray2_Hook, reinterpret_cast<LPVOID*>(&RecvPropArray2_Original));
- hook.~HookEnabler(); // force hook before calling construct function
-
- *(DWORD*)((char*)baseAddress + 0xC3AFF8) = 0;
- auto DT_Team_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x17F950);
- DT_Team_Construct();
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/maxplayers.h b/NorthstarDedicatedTest/maxplayers.h
deleted file mode 100644
index cd191fc8..00000000
--- a/NorthstarDedicatedTest/maxplayers.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress);
-void InitialiseMaxPlayersOverride_Server(HMODULE baseAddress);
-void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/miscclientfixes.cpp b/NorthstarDedicatedTest/miscclientfixes.cpp
deleted file mode 100644
index 62ffd4a4..00000000
--- a/NorthstarDedicatedTest/miscclientfixes.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "pch.h"
-#include "miscclientfixes.h"
-#include "hookutils.h"
-#include "dedicated.h"
-
-typedef void* (*CrashingWeaponActivityFuncType)(void* a1);
-CrashingWeaponActivityFuncType CrashingWeaponActivityFunc0;
-CrashingWeaponActivityFuncType CrashingWeaponActivityFunc1;
-
-void* CrashingWeaponActivityFunc0Hook(void* a1)
-{
- // this return is safe, other functions that use this value seemingly dont care about it being null
- if (!a1)
- return 0;
-
- return CrashingWeaponActivityFunc0(a1);
-}
-
-void* CrashingWeaponActivityFunc1Hook(void* a1)
-{
- // this return is safe, other functions that use this value seemingly dont care about it being null
- if (!a1)
- return 0;
-
- return CrashingWeaponActivityFunc1(a1);
-}
-
-void InitialiseMiscClientFixes(HMODULE baseAddress)
-{
- if (IsDedicated())
- return;
-
- HookEnabler hook;
-
- // these functions will occasionally pass a null pointer on respawn, unsure what causes this but seems easiest just to return null if
- // null, which seems to work fine fucking sucks this has to be fixed like this but unsure what exactly causes this serverside, breaks
- // vanilla compatibility to a degree tho will say i have about 0 clue what exactly these functions do, testing this it doesn't even seem
- // like they do much of anything i can see tbh
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x5A92D0, &CrashingWeaponActivityFunc0Hook, reinterpret_cast<LPVOID*>(&CrashingWeaponActivityFunc0));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x5A9310, &CrashingWeaponActivityFunc1Hook, reinterpret_cast<LPVOID*>(&CrashingWeaponActivityFunc1));
-
- // experimental: allow cl_extrapolate to be enabled without cheats
- {
- void* ptr = (char*)baseAddress + 0x275F9D9;
- *((char*)ptr) = (char)0;
- }
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/miscclientfixes.h b/NorthstarDedicatedTest/miscclientfixes.h
deleted file mode 100644
index 1f0ad807..00000000
--- a/NorthstarDedicatedTest/miscclientfixes.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void InitialiseMiscClientFixes(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/misccommands.cpp b/NorthstarDedicatedTest/misccommands.cpp
deleted file mode 100644
index df2f4a3d..00000000
--- a/NorthstarDedicatedTest/misccommands.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "pch.h"
-#include "misccommands.h"
-#include "concommand.h"
-#include "gameutils.h"
-#include "masterserver.h"
-#include "serverauthentication.h"
-#include "squirrel.h"
-
-void AddMiscConCommands()
-{
- MAKE_CONCMD(
- "force_newgame",
- "forces a map load through directly setting g_pHostState->m_iNextState to HS_NEW_GAME",
- FCVAR_NONE,
- [](const CCommand& arg)
- {
- if (arg.ArgC() < 2)
- return;
-
- g_pHostState->m_iNextState = HS_NEW_GAME;
- strncpy(g_pHostState->m_levelName, arg.Arg(1), sizeof(g_pHostState->m_levelName));
- });
-
- MAKE_CONCMD(
- "ns_start_reauth_and_leave_to_lobby",
- "called by the server, used to reauth and return the player to lobby when leaving a game",
- FCVAR_SERVER_CAN_EXECUTE,
- [](const CCommand& arg)
- {
- // hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect
- g_MasterServerManager->m_bNewgameAfterSelfAuth = true;
- g_MasterServerManager->AuthenticateWithOwnServer(g_LocalPlayerUserID, g_MasterServerManager->m_ownClientAuthToken);
- });
-
- // this is a concommand because we make a deferred call to it from another thread
- MAKE_CONCMD(
- "ns_end_reauth_and_leave_to_lobby",
- "",
- FCVAR_NONE,
- [](const CCommand& arg)
- {
- Cbuf_AddText(
- Cbuf_GetCurrentPlayer(),
- fmt::format("serverfilter {}", g_ServerAuthenticationManager->m_authData.begin()->first).c_str(),
- cmd_source_t::kCommandSrcCode);
- Cbuf_Execute();
-
- // weird way of checking, but check if client script vm is initialised, mainly just to allow players to cancel this
- if (g_ClientSquirrelManager->sqvm)
- {
- g_ServerAuthenticationManager->m_bNeedLocalAuthForNewgame = true;
-
- // this won't set playlist correctly on remote clients, don't think they can set playlist until they've left which sorta
- // fucks things should maybe set this in HostState_NewGame?
- SetCurrentPlaylist("tdm");
- strcpy(g_pHostState->m_levelName, "mp_lobby");
- g_pHostState->m_iNextState = HS_NEW_GAME;
- }
- });
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/misccommands.h b/NorthstarDedicatedTest/misccommands.h
deleted file mode 100644
index cbd1df65..00000000
--- a/NorthstarDedicatedTest/misccommands.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void AddMiscConCommands(); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/miscserverfixes.cpp b/NorthstarDedicatedTest/miscserverfixes.cpp
deleted file mode 100644
index 30cd5777..00000000
--- a/NorthstarDedicatedTest/miscserverfixes.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "pch.h"
-#include "miscserverfixes.h"
-#include "hookutils.h"
-
-#include "NSMem.h"
-
-void InitialiseMiscServerFixes(HMODULE baseAddress)
-{
- uintptr_t ba = (uintptr_t)baseAddress;
-
- // ret at the start of the concommand GenerateObjFile as it can crash servers
- {
- NSMem::BytePatch(ba + 0x38D920, "C3");
- }
-
- // nop out call to VGUI shutdown since it crashes the game when quitting from the console
- {
- NSMem::NOP(ba + 0x154A96, 5);
- }
-
- // ret at the start of CServerGameClients::ClientCommandKeyValues as it has no benefit and is forwarded to client (i.e. security issue)
- // this prevents the attack vector of client=>server=>client, however server=>client also has clientside patches
- {
- NSMem::BytePatch(ba + 0x153920, "C3");
- }
-}
-
-void InitialiseMiscEngineServerFixes(HMODULE baseAddress) {} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/miscserverfixes.h b/NorthstarDedicatedTest/miscserverfixes.h
deleted file mode 100644
index d1c05a6b..00000000
--- a/NorthstarDedicatedTest/miscserverfixes.h
+++ /dev/null
@@ -1 +0,0 @@
-void InitialiseMiscServerFixes(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/miscserverscript.cpp b/NorthstarDedicatedTest/miscserverscript.cpp
deleted file mode 100644
index b2bf52ec..00000000
--- a/NorthstarDedicatedTest/miscserverscript.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "pch.h"
-#include "miscserverscript.h"
-#include "squirrel.h"
-#include "masterserver.h"
-#include "serverauthentication.h"
-#include "gameutils.h"
-
-// annoying helper function because i can't figure out getting players or entities from sqvm rn
-// wish i didn't have to do it like this, but here we are
-void* GetPlayerByIndex(int playerIndex)
-{
- const int PLAYER_ARRAY_OFFSET = 0x12A53F90;
- const int PLAYER_SIZE = 0x2D728;
-
- void* playerArrayBase = (char*)GetModuleHandleA("engine.dll") + PLAYER_ARRAY_OFFSET;
- void* player = (char*)playerArrayBase + (playerIndex * PLAYER_SIZE);
-
- return player;
-}
-
-// void function NSEarlyWritePlayerIndexPersistenceForLeave( int playerIndex )
-SQRESULT SQ_EarlyWritePlayerIndexPersistenceForLeave(void* sqvm)
-{
- int playerIndex = ServerSq_getinteger(sqvm, 1);
- void* player = GetPlayerByIndex(playerIndex);
-
- if (!g_ServerAuthenticationManager->m_additionalPlayerData.count(player))
- {
- ServerSq_pusherror(sqvm, fmt::format("Invalid playerindex {}", playerIndex).c_str());
- return SQRESULT_ERROR;
- }
-
- g_ServerAuthenticationManager->m_additionalPlayerData[player].needPersistenceWriteOnLeave = false;
- g_ServerAuthenticationManager->WritePersistentData(player);
- return SQRESULT_NULL;
-}
-
-// bool function NSIsWritingPlayerPersistence()
-SQRESULT SQ_IsWritingPlayerPersistence(void* sqvm)
-{
- ServerSq_pushbool(sqvm, g_MasterServerManager->m_savingPersistentData);
- return SQRESULT_NOTNULL;
-}
-
-// bool function NSIsPlayerIndexLocalPlayer( int playerIndex )
-SQRESULT SQ_IsPlayerIndexLocalPlayer(void* sqvm)
-{
- int playerIndex = ServerSq_getinteger(sqvm, 1);
- void* player = GetPlayerByIndex(playerIndex);
- if (!g_ServerAuthenticationManager->m_additionalPlayerData.count(player))
- {
- ServerSq_pusherror(sqvm, fmt::format("Invalid playerindex {}", playerIndex).c_str());
- return SQRESULT_ERROR;
- }
-
- ServerSq_pushbool(sqvm, !strcmp(g_LocalPlayerUserID, (char*)player + 0xF500));
- return SQRESULT_NOTNULL;
-}
-
-void InitialiseMiscServerScriptCommand(HMODULE baseAddress)
-{
- g_ServerSquirrelManager->AddFuncRegistration(
- "void", "NSEarlyWritePlayerIndexPersistenceForLeave", "int playerIndex", "", SQ_EarlyWritePlayerIndexPersistenceForLeave);
- g_ServerSquirrelManager->AddFuncRegistration("bool", "NSIsWritingPlayerPersistence", "", "", SQ_IsWritingPlayerPersistence);
- g_ServerSquirrelManager->AddFuncRegistration("bool", "NSIsPlayerIndexLocalPlayer", "int playerIndex", "", SQ_IsPlayerIndexLocalPlayer);
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/miscserverscript.h b/NorthstarDedicatedTest/miscserverscript.h
deleted file mode 100644
index 8197e502..00000000
--- a/NorthstarDedicatedTest/miscserverscript.h
+++ /dev/null
@@ -1,2 +0,0 @@
-void InitialiseMiscServerScriptCommand(HMODULE baseAddress);
-void* GetPlayerByIndex(int playerIndex); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/modlocalisation.cpp b/NorthstarDedicatedTest/modlocalisation.cpp
deleted file mode 100644
index a3c45e40..00000000
--- a/NorthstarDedicatedTest/modlocalisation.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#include "pch.h"
-#include "modlocalisation.h"
-#include "hookutils.h"
-#include "modmanager.h"
-
-typedef bool (*AddLocalisationFileType)(void* g_pVguiLocalize, const char* path, const char* pathId, char unknown);
-AddLocalisationFileType AddLocalisationFile;
-
-bool loadModLocalisationFiles = true;
-
-bool AddLocalisationFileHook(void* g_pVguiLocalize, const char* path, const char* pathId, char unknown)
-{
- bool ret = AddLocalisationFile(g_pVguiLocalize, path, pathId, unknown);
-
- if (ret)
- spdlog::info("Loaded localisation file {} successfully", path);
-
- if (!loadModLocalisationFiles)
- return ret;
-
- loadModLocalisationFiles = false;
-
- for (Mod mod : g_ModManager->m_loadedMods)
- if (mod.Enabled)
- for (std::string& localisationFile : mod.LocalisationFiles)
- AddLocalisationFile(g_pVguiLocalize, localisationFile.c_str(), pathId, unknown);
-
- loadModLocalisationFiles = true;
-
- return ret;
-}
-
-void InitialiseModLocalisation(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x6D80, AddLocalisationFileHook, reinterpret_cast<LPVOID*>(&AddLocalisationFile));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/modlocalisation.h b/NorthstarDedicatedTest/modlocalisation.h
deleted file mode 100644
index b7d9cd50..00000000
--- a/NorthstarDedicatedTest/modlocalisation.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseModLocalisation(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/playlist.cpp b/NorthstarDedicatedTest/playlist.cpp
deleted file mode 100644
index fdb23893..00000000
--- a/NorthstarDedicatedTest/playlist.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "pch.h"
-#include "playlist.h"
-#include "concommand.h"
-#include "convar.h"
-#include "gameutils.h"
-#include "hookutils.h"
-#include "squirrel.h"
-
-typedef char (*Onclc_SetPlaylistVarOverrideType)(void* a1, void* a2);
-Onclc_SetPlaylistVarOverrideType Onclc_SetPlaylistVarOverride;
-
-typedef int (*GetCurrentGamemodeMaxPlayersType)();
-GetCurrentGamemodeMaxPlayersType GetCurrentGamemodeMaxPlayers;
-
-// function type defined in gameutils.h
-SetPlaylistVarOverrideType SetPlaylistVarOverrideOriginal;
-GetCurrentPlaylistVarType GetCurrentPlaylistVarOriginal;
-
-ConVar* Cvar_ns_use_clc_SetPlaylistVarOverride;
-
-void SetPlaylistCommand(const CCommand& args)
-{
- if (args.ArgC() < 2)
- return;
-
- SetCurrentPlaylist(args.Arg(1));
-}
-
-void SetPlaylistVarOverrideCommand(const CCommand& args)
-{
- if (args.ArgC() < 3)
- return;
-
- for (int i = 1; i < args.ArgC(); i += 2)
- SetPlaylistVarOverride(args.Arg(i), args.Arg(i + 1));
-}
-
-char Onclc_SetPlaylistVarOverrideHook(void* a1, void* a2)
-{
- // the private_match playlist is the only situation where there should be any legitimate sending of this netmessage
- // todo: check mp_lobby here too
- if (!Cvar_ns_use_clc_SetPlaylistVarOverride->GetBool() || strcmp(GetCurrentPlaylistName(), "private_match"))
- return 1;
-
- return Onclc_SetPlaylistVarOverride(a1, a2);
-}
-
-void SetPlaylistVarOverrideHook(const char* varName, const char* value)
-{
- if (strlen(value) >= 64)
- return;
-
- SetPlaylistVarOverrideOriginal(varName, value);
-}
-
-char* GetCurrentPlaylistVarHook(const char* varName, bool useOverrides)
-{
- if (!useOverrides && !strcmp(varName, "max_players"))
- useOverrides = true;
-
- return GetCurrentPlaylistVarOriginal(varName, useOverrides);
-}
-
-int GetCurrentGamemodeMaxPlayersHook()
-{
- char* maxPlayersStr = GetCurrentPlaylistVar("max_players", 0);
- if (!maxPlayersStr)
- return GetCurrentGamemodeMaxPlayers();
-
- int maxPlayers = atoi(maxPlayersStr);
- return maxPlayers;
-}
-
-#include "NSMem.h"
-void InitialisePlaylistHooks(HMODULE baseAddress)
-{
- RegisterConCommand("setplaylist", SetPlaylistCommand, "Sets the current playlist", FCVAR_NONE);
- RegisterConCommand("setplaylistvaroverrides", SetPlaylistVarOverrideCommand, "sets a playlist var override", FCVAR_NONE);
- // note: clc_SetPlaylistVarOverride is pretty insecure, since it allows for entirely arbitrary playlist var overrides to be sent to the
- // server this is somewhat restricted on custom servers to prevent it being done outside of private matches, but ideally it should be
- // disabled altogether, since the custom menus won't use it anyway this should only really be accepted if you want vanilla client
- // compatibility
- Cvar_ns_use_clc_SetPlaylistVarOverride = new ConVar(
- "ns_use_clc_SetPlaylistVarOverride", "0", FCVAR_GAMEDLL, "Whether the server should accept clc_SetPlaylistVarOverride messages");
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x222180, &Onclc_SetPlaylistVarOverrideHook, reinterpret_cast<LPVOID*>(&Onclc_SetPlaylistVarOverride));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x18ED00, &SetPlaylistVarOverrideHook, reinterpret_cast<LPVOID*>(&SetPlaylistVarOverrideOriginal));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x18C680, &GetCurrentPlaylistVarHook, reinterpret_cast<LPVOID*>(&GetCurrentPlaylistVarOriginal));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x18C430, &GetCurrentGamemodeMaxPlayersHook, reinterpret_cast<LPVOID*>(&GetCurrentGamemodeMaxPlayers));
-
- uintptr_t ba = (uintptr_t)baseAddress;
-
- // patch to prevent clc_SetPlaylistVarOverride from being able to crash servers if we reach max overrides due to a call to Error (why is
- // this possible respawn, wtf) todo: add a warning for this
- {
- NSMem::BytePatch(ba + 0x18ED8D, "C3");
- }
-
- // patch to allow setplaylistvaroverride to be called before map init on dedicated and private match launched through the game
- NSMem::NOP(ba + 0x18ED17, 6);
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/playlist.h b/NorthstarDedicatedTest/playlist.h
deleted file mode 100644
index bf827ff4..00000000
--- a/NorthstarDedicatedTest/playlist.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void InitialisePlaylistHooks(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/rpakfilesystem.cpp b/NorthstarDedicatedTest/rpakfilesystem.cpp
deleted file mode 100644
index d52f9ef1..00000000
--- a/NorthstarDedicatedTest/rpakfilesystem.cpp
+++ /dev/null
@@ -1,246 +0,0 @@
-#include "pch.h"
-#include "rpakfilesystem.h"
-#include "hookutils.h"
-#include "modmanager.h"
-#include "dedicated.h"
-
-typedef void* (*LoadCommonPaksForMapType)(char* map);
-LoadCommonPaksForMapType LoadCommonPaksForMap;
-
-typedef void* (*LoadPakSyncType)(const char* path, void* unknownSingleton, int flags);
-typedef int (*LoadPakAsyncType)(const char* path, void* unknownSingleton, int flags, void* callback0, void* callback1);
-typedef void* (*UnloadPakType)(int pakHandle, void* callback);
-typedef void* (*ReadFullFileFromDiskType)(const char* requestedPath, void* a2);
-
-// there are more i'm just too lazy to add
-struct PakLoadFuncs
-{
- void* unk0[2];
- LoadPakSyncType LoadPakSync;
- LoadPakAsyncType LoadPakAsync;
- void* unk1[2];
- UnloadPakType UnloadPak;
- void* unk2[17];
- ReadFullFileFromDiskType ReadFullFileFromDisk;
-};
-
-PakLoadFuncs* g_pakLoadApi;
-void** pUnknownPakLoadSingleton;
-
-PakLoadManager* g_PakLoadManager;
-void PakLoadManager::LoadPakSync(const char* path)
-{
- g_pakLoadApi->LoadPakSync(path, *pUnknownPakLoadSingleton, 0);
-}
-void PakLoadManager::LoadPakAsync(const char* path, bool bMarkForUnload)
-{
- int handle = g_pakLoadApi->LoadPakAsync(path, *pUnknownPakLoadSingleton, 2, nullptr, nullptr);
-
- if (bMarkForUnload)
- m_pakHandlesToUnload.push_back(handle);
-}
-
-void PakLoadManager::UnloadPaks()
-{
- for (int pakHandle : m_pakHandlesToUnload)
- g_pakLoadApi->UnloadPak(pakHandle, nullptr);
-
- m_pakHandlesToUnload.clear();
-}
-
-void HandlePakAliases(char** map)
-{
- // convert the pak being loaded to it's aliased one, e.g. aliasing mp_hub_timeshift => sp_hub_timeshift
- for (int64_t i = g_ModManager->m_loadedMods.size() - 1; i > -1; i--)
- {
- Mod* mod = &g_ModManager->m_loadedMods[i];
- if (!mod->Enabled)
- continue;
-
- if (mod->RpakAliases.find(*map) != mod->RpakAliases.end())
- {
- *map = &mod->RpakAliases[*map][0];
- return;
- }
- }
-}
-
-void LoadPreloadPaks()
-{
- // note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- // need to get a relative path of mod to mod folder
- fs::path modPakPath("./" / mod.ModDirectory / "paks");
-
- for (ModRpakEntry& pak : mod.Rpaks)
- if (pak.m_bAutoLoad)
- g_PakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakName).string().c_str(), false);
- }
-}
-
-void LoadCustomMapPaks(char** pakName, bool* bNeedToFreePakName)
-{
- // whether the vanilla game has this rpak
- bool bHasOriginalPak = fs::exists(fs::path("./r2/paks/Win64/") / *pakName);
-
- // note, loading from ./ is necessary otherwise paks will load from gamedir/r2/paks
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- // need to get a relative path of mod to mod folder
- fs::path modPakPath("./" / mod.ModDirectory / "paks");
-
- for (ModRpakEntry& pak : mod.Rpaks)
- {
- if (!pak.m_bAutoLoad && !pak.m_sPakName.compare(*pakName))
- {
- // if the game doesn't have the original pak, let it handle loading this one as if it was the one it was loading originally
- if (!bHasOriginalPak)
- {
- std::string path = (modPakPath / pak.m_sPakName).string();
- *pakName = new char[path.size() + 1];
- strcpy(*pakName, &path[0]);
- (*pakName)[path.size()] = '\0';
-
- bHasOriginalPak = true;
- *bNeedToFreePakName =
- true; // we can't free this memory until we're done with the pak, so let whatever's calling this deal with it
- }
- else
- g_PakLoadManager->LoadPakAsync((modPakPath / pak.m_sPakName).string().c_str(), true);
- }
- }
- }
-}
-
-LoadPakSyncType LoadPakSyncOriginal;
-void* LoadPakSyncHook(char* path, void* unknownSingleton, int flags)
-{
- HandlePakAliases(&path);
-
- bool bNeedToFreePakName = false;
-
- // note: we don't handle loading any preloaded custom paks synchronously since LoadPakSync is never actually called in retail, just load
- // them async instead
- static bool bShouldLoadPaks = true;
- if (bShouldLoadPaks)
- {
- // disable preloading while we're doing this
- bShouldLoadPaks = false;
-
- LoadPreloadPaks();
- LoadCustomMapPaks(&path, &bNeedToFreePakName);
-
- bShouldLoadPaks = true;
- }
-
- spdlog::info("LoadPakSync {}", path);
- void* ret = LoadPakSyncOriginal(path, unknownSingleton, flags);
-
- if (bNeedToFreePakName)
- delete[] path;
-
- return ret;
-}
-
-LoadPakAsyncType LoadPakAsyncOriginal;
-int LoadPakAsyncHook(char* path, void* unknownSingleton, int flags, void* callback0, void* callback1)
-{
- HandlePakAliases(&path);
-
- bool bNeedToFreePakName = false;
-
- static bool bShouldLoadPaks = true;
- if (bShouldLoadPaks)
- {
- // disable preloading while we're doing this
- bShouldLoadPaks = false;
-
- LoadPreloadPaks();
- LoadCustomMapPaks(&path, &bNeedToFreePakName);
-
- bShouldLoadPaks = true;
-
- // do this after custom paks load and in bShouldLoadPaks so we only ever call this on the root pakload call
- // todo: could probably add some way to flag custom paks to not be loaded on dedicated servers in rpak.json
- if (IsDedicated() && strncmp(path, "common", 6)) // dedicated only needs common and common_mp
- return -1;
- }
-
- int ret = LoadPakAsyncOriginal(path, unknownSingleton, flags, callback0, callback1);
- spdlog::info("LoadPakAsync {} {}", path, ret);
-
- if (bNeedToFreePakName)
- delete[] path;
-
- return ret;
-}
-
-UnloadPakType UnloadPakOriginal;
-void* UnloadPakHook(int pakHandle, void* callback)
-{
- static bool bShouldUnloadPaks = true;
- if (bShouldUnloadPaks)
- {
- bShouldUnloadPaks = false;
- g_PakLoadManager->UnloadPaks();
- bShouldUnloadPaks = true;
- }
-
- spdlog::info("UnloadPak {}", pakHandle);
- return UnloadPakOriginal(pakHandle, callback);
-}
-
-// we hook this exclusively for resolving stbsp paths, but seemingly it's also used for other stuff like vpk and rpak loads
-// possibly just async loading all together?
-ReadFullFileFromDiskType ReadFullFileFromDiskOriginal;
-void* ReadFullFileFromDiskHook(const char* requestedPath, void* a2)
-{
- fs::path path(requestedPath);
- char* allocatedNewPath = nullptr;
-
- if (path.extension() == ".stbsp")
- {
- fs::path filename = path.filename();
- spdlog::info("LoadStreamBsp: {}", filename.string());
-
- // resolve modded stbsp path so we can load mod stbsps
- auto modFile = g_ModManager->m_modFiles.find(fs::path("maps" / filename).lexically_normal().string());
- if (modFile != g_ModManager->m_modFiles.end())
- {
- // need to allocate a new string for this
- std::string newPath = (modFile->second.owningMod->ModDirectory / "mod" / modFile->second.path).string();
- allocatedNewPath = new char[newPath.size() + 1];
- strncpy(allocatedNewPath, newPath.c_str(), newPath.size());
- allocatedNewPath[newPath.size()] = '\0';
- requestedPath = allocatedNewPath;
- }
- }
-
- void* ret = ReadFullFileFromDiskOriginal(requestedPath, a2);
- if (allocatedNewPath)
- delete[] allocatedNewPath;
-
- return ret;
-}
-
-void InitialiseEngineRpakFilesystem(HMODULE baseAddress)
-{
- g_PakLoadManager = new PakLoadManager;
-
- g_pakLoadApi = *(PakLoadFuncs**)((char*)baseAddress + 0x5BED78);
- pUnknownPakLoadSingleton = (void**)((char*)baseAddress + 0x7C5E20);
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, g_pakLoadApi->LoadPakSync, &LoadPakSyncHook, reinterpret_cast<LPVOID*>(&LoadPakSyncOriginal));
- ENABLER_CREATEHOOK(hook, g_pakLoadApi->LoadPakAsync, &LoadPakAsyncHook, reinterpret_cast<LPVOID*>(&LoadPakAsyncOriginal));
- ENABLER_CREATEHOOK(hook, g_pakLoadApi->UnloadPak, &UnloadPakHook, reinterpret_cast<LPVOID*>(&UnloadPakOriginal));
- ENABLER_CREATEHOOK(
- hook, g_pakLoadApi->ReadFullFileFromDisk, &ReadFullFileFromDiskHook, reinterpret_cast<LPVOID*>(&ReadFullFileFromDiskOriginal));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/rpakfilesystem.h b/NorthstarDedicatedTest/rpakfilesystem.h
deleted file mode 100644
index 3c104822..00000000
--- a/NorthstarDedicatedTest/rpakfilesystem.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-void InitialiseEngineRpakFilesystem(HMODULE baseAddress);
-
-class PakLoadManager
-{
- public:
- void LoadPakSync(const char* path);
- void LoadPakAsync(const char* path, bool bMarkForUnload);
- void UnloadPaks();
-
- private:
- std::vector<int> m_pakHandlesToUnload;
-};
-
-extern PakLoadManager* g_PakLoadManager; \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptbrowserhooks.cpp b/NorthstarDedicatedTest/scriptbrowserhooks.cpp
deleted file mode 100644
index d90bc998..00000000
--- a/NorthstarDedicatedTest/scriptbrowserhooks.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "pch.h"
-#include "scriptbrowserhooks.h"
-#include "hookutils.h"
-
-typedef void (*OpenExternalWebBrowserType)(char* url, char flags);
-OpenExternalWebBrowserType OpenExternalWebBrowser;
-
-bool* bIsOriginOverlayEnabled;
-
-void OpenExternalWebBrowserHook(char* url, char flags)
-{
- bool bIsOriginOverlayEnabledOriginal = *bIsOriginOverlayEnabled;
- if (flags & 2 && !strncmp(url, "http", 4)) // custom force external browser flag
- *bIsOriginOverlayEnabled = false; // if this bool is false, game will use an external browser rather than the origin overlay one
-
- OpenExternalWebBrowser(url, flags);
- *bIsOriginOverlayEnabled = bIsOriginOverlayEnabledOriginal;
-}
-
-void InitialiseScriptExternalBrowserHooks(HMODULE baseAddress)
-{
- bIsOriginOverlayEnabled = (bool*)baseAddress + 0x13978255;
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x184E40, &OpenExternalWebBrowserHook, reinterpret_cast<LPVOID*>(&OpenExternalWebBrowser));
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptbrowserhooks.h b/NorthstarDedicatedTest/scriptbrowserhooks.h
deleted file mode 100644
index 919cc92e..00000000
--- a/NorthstarDedicatedTest/scriptbrowserhooks.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseScriptExternalBrowserHooks(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptmainmenupromos.cpp b/NorthstarDedicatedTest/scriptmainmenupromos.cpp
deleted file mode 100644
index c63d58d3..00000000
--- a/NorthstarDedicatedTest/scriptmainmenupromos.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "pch.h"
-#include "scriptmainmenupromos.h"
-#include "squirrel.h"
-#include "masterserver.h"
-
-// mirror this in script
-enum eMainMenuPromoDataProperty
-{
- newInfoTitle1,
- newInfoTitle2,
- newInfoTitle3,
-
- largeButtonTitle,
- largeButtonText,
- largeButtonUrl,
- largeButtonImageIndex,
-
- smallButton1Title,
- smallButton1Url,
- smallButton1ImageIndex,
-
- smallButton2Title,
- smallButton2Url,
- smallButton2ImageIndex
-};
-
-// void function NSRequestCustomMainMenuPromos()
-SQRESULT SQ_RequestCustomMainMenuPromos(void* sqvm)
-{
- g_MasterServerManager->RequestMainMenuPromos();
- return SQRESULT_NULL;
-}
-
-// bool function NSHasCustomMainMenuPromoData()
-SQRESULT SQ_HasCustomMainMenuPromoData(void* sqvm)
-{
- ClientSq_pushbool(sqvm, g_MasterServerManager->m_bHasMainMenuPromoData);
- return SQRESULT_NOTNULL;
-}
-
-// var function NSGetCustomMainMenuPromoData( int promoDataKey )
-SQRESULT SQ_GetCustomMainMenuPromoData(void* sqvm)
-{
- if (!g_MasterServerManager->m_bHasMainMenuPromoData)
- return SQRESULT_NULL;
-
- switch (ClientSq_getinteger(sqvm, 1))
- {
- case eMainMenuPromoDataProperty::newInfoTitle1:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.newInfoTitle1.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::newInfoTitle2:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.newInfoTitle2.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::newInfoTitle3:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.newInfoTitle3.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::largeButtonTitle:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.largeButtonTitle.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::largeButtonText:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.largeButtonText.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::largeButtonUrl:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.largeButtonUrl.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::largeButtonImageIndex:
- {
- ClientSq_pushinteger(sqvm, g_MasterServerManager->m_MainMenuPromoData.largeButtonImageIndex);
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton1Title:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.smallButton1Title.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton1Url:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.smallButton1Url.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton1ImageIndex:
- {
- ClientSq_pushinteger(sqvm, g_MasterServerManager->m_MainMenuPromoData.smallButton1ImageIndex);
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton2Title:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.smallButton2Title.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton2Url:
- {
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_MainMenuPromoData.smallButton2Url.c_str(), -1);
- break;
- }
-
- case eMainMenuPromoDataProperty::smallButton2ImageIndex:
- {
- ClientSq_pushinteger(sqvm, g_MasterServerManager->m_MainMenuPromoData.smallButton2ImageIndex);
- break;
- }
- }
-
- return SQRESULT_NOTNULL;
-}
-
-void InitialiseScriptMainMenuPromos(HMODULE baseAddress)
-{
- g_UISquirrelManager->AddFuncRegistration("void", "NSRequestCustomMainMenuPromos", "", "", SQ_RequestCustomMainMenuPromos);
- g_UISquirrelManager->AddFuncRegistration("bool", "NSHasCustomMainMenuPromoData", "", "", SQ_HasCustomMainMenuPromoData);
- g_UISquirrelManager->AddFuncRegistration("var", "NSGetCustomMainMenuPromoData", "int promoDataKey", "", SQ_GetCustomMainMenuPromoData);
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptmainmenupromos.h b/NorthstarDedicatedTest/scriptmainmenupromos.h
deleted file mode 100644
index 2719e647..00000000
--- a/NorthstarDedicatedTest/scriptmainmenupromos.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseScriptMainMenuPromos(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptmodmenu.cpp b/NorthstarDedicatedTest/scriptmodmenu.cpp
deleted file mode 100644
index ca3cfed4..00000000
--- a/NorthstarDedicatedTest/scriptmodmenu.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-#include "pch.h"
-#include "scriptmodmenu.h"
-#include "modmanager.h"
-#include "squirrel.h"
-
-// array<string> function NSGetModNames()
-SQRESULT SQ_GetModNames(void* sqvm)
-{
- ClientSq_newarray(sqvm, 0);
-
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- ClientSq_pushstring(sqvm, mod.Name.c_str(), -1);
- ClientSq_arrayappend(sqvm, -2);
- }
-
- return SQRESULT_NOTNULL;
-}
-
-// bool function NSIsModEnabled(string modName)
-SQRESULT SQ_IsModEnabled(void* sqvm)
-{
- const SQChar* modName = ClientSq_getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- ClientSq_pushbool(sqvm, mod.Enabled);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-// void function NSSetModEnabled(string modName, bool enabled)
-SQRESULT SQ_SetModEnabled(void* sqvm)
-{
- const SQChar* modName = ClientSq_getstring(sqvm, 1);
- const SQBool enabled = ClientSq_getbool(sqvm, 2);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- mod.Enabled = enabled;
- return SQRESULT_NULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-// string function NSGetModDescriptionByModName(string modName)
-SQRESULT SQ_GetModDescription(void* sqvm)
-{
- const SQChar* modName = ClientSq_getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- ClientSq_pushstring(sqvm, mod.Description.c_str(), -1);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-// string function NSGetModVersionByModName(string modName)
-SQRESULT SQ_GetModVersion(void* sqvm)
-{
- const SQChar* modName = ClientSq_getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- ClientSq_pushstring(sqvm, mod.Version.c_str(), -1);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-// string function NSGetModDownloadLinkByModName(string modName)
-SQRESULT SQ_GetModDownloadLink(void* sqvm)
-{
- const SQChar* modName = ClientSq_getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- ClientSq_pushstring(sqvm, mod.DownloadLink.c_str(), -1);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-// int function NSGetModLoadPriority(string modName)
-SQRESULT SQ_GetModLoadPriority(void* sqvm)
-{
- const SQChar* modName = ClientSq_getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- ClientSq_pushinteger(sqvm, mod.LoadPriority);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-// bool function NSIsModRequiredOnClient(string modName)
-SQRESULT SQ_IsModRequiredOnClient(void* sqvm)
-{
- const SQChar* modName = ClientSq_getstring(sqvm, 1);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- ClientSq_pushbool(sqvm, mod.RequiredOnClient);
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NULL;
-}
-
-// array<string> function NSGetModConvarsByModName(string modName)
-SQRESULT SQ_GetModConvars(void* sqvm)
-{
- const SQChar* modName = ClientSq_getstring(sqvm, 1);
- ClientSq_newarray(sqvm, 0);
-
- // manual lookup, not super performant but eh not a big deal
- for (Mod& mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Name.compare(modName))
- {
- for (ModConVar* cvar : mod.ConVars)
- {
- ClientSq_pushstring(sqvm, cvar->Name.c_str(), -1);
- ClientSq_arrayappend(sqvm, -2);
- }
-
- return SQRESULT_NOTNULL;
- }
- }
-
- return SQRESULT_NOTNULL; // return empty array
-}
-
-// void function NSReloadMods()
-SQRESULT SQ_ReloadMods(void* sqvm)
-{
- g_ModManager->LoadMods();
- return SQRESULT_NULL;
-}
-
-void InitialiseScriptModMenu(HMODULE baseAddress)
-{
- g_UISquirrelManager->AddFuncRegistration("array<string>", "NSGetModNames", "", "Returns the names of all loaded mods", SQ_GetModNames);
- g_UISquirrelManager->AddFuncRegistration(
- "bool", "NSIsModEnabled", "string modName", "Returns whether a given mod is enabled", SQ_IsModEnabled);
- g_UISquirrelManager->AddFuncRegistration(
- "void", "NSSetModEnabled", "string modName, bool enabled", "Sets whether a given mod is enabled", SQ_SetModEnabled);
- g_UISquirrelManager->AddFuncRegistration(
- "string", "NSGetModDescriptionByModName", "string modName", "Returns a given mod's description", SQ_GetModDescription);
- g_UISquirrelManager->AddFuncRegistration(
- "string", "NSGetModVersionByModName", "string modName", "Returns a given mod's version", SQ_GetModVersion);
- g_UISquirrelManager->AddFuncRegistration(
- "string", "NSGetModDownloadLinkByModName", "string modName", "Returns a given mod's download link", SQ_GetModDownloadLink);
- g_UISquirrelManager->AddFuncRegistration(
- "bool",
- "NSIsModRequiredOnClient",
- "string modName",
- "Returns whether a given mod is required on connecting clients",
- SQ_IsModRequiredOnClient);
- g_UISquirrelManager->AddFuncRegistration(
- "int", "NSGetModLoadPriority", "string modName", "Returns a given mod's load priority", SQ_GetModLoadPriority);
- g_UISquirrelManager->AddFuncRegistration(
- "array<string>", "NSGetModConvarsByModName", "string modName", "Returns the names of all a given mod's cvars", SQ_GetModConvars);
-
- g_UISquirrelManager->AddFuncRegistration("void", "NSReloadMods", "", "Reloads mods", SQ_ReloadMods);
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptmodmenu.h b/NorthstarDedicatedTest/scriptmodmenu.h
deleted file mode 100644
index 019346d3..00000000
--- a/NorthstarDedicatedTest/scriptmodmenu.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseScriptModMenu(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptserverbrowser.cpp b/NorthstarDedicatedTest/scriptserverbrowser.cpp
deleted file mode 100644
index aec47c3b..00000000
--- a/NorthstarDedicatedTest/scriptserverbrowser.cpp
+++ /dev/null
@@ -1,441 +0,0 @@
-#include "pch.h"
-#include "scriptserverbrowser.h"
-#include "squirrel.h"
-#include "masterserver.h"
-#include "gameutils.h"
-#include "serverauthentication.h"
-
-// functions for viewing server browser
-
-// bool function NSIsMasterServerAuthenticated()
-SQRESULT SQ_IsMasterServerAuthenticated(void* sqvm)
-{
- ClientSq_pushbool(sqvm, g_MasterServerManager->m_bOriginAuthWithMasterServerDone);
- return SQRESULT_NOTNULL;
-}
-
-// void function NSRequestServerList()
-SQRESULT SQ_RequestServerList(void* sqvm)
-{
- g_MasterServerManager->RequestServerList();
- return SQRESULT_NULL;
-}
-
-// bool function NSIsRequestingServerList()
-SQRESULT SQ_IsRequestingServerList(void* sqvm)
-{
- ClientSq_pushbool(sqvm, g_MasterServerManager->m_scriptRequestingServerList);
- return SQRESULT_NOTNULL;
-}
-
-// bool function NSMasterServerConnectionSuccessful()
-SQRESULT SQ_MasterServerConnectionSuccessful(void* sqvm)
-{
- ClientSq_pushbool(sqvm, g_MasterServerManager->m_successfullyConnected);
- return SQRESULT_NOTNULL;
-}
-
-// int function NSGetServerCount()
-SQRESULT SQ_GetServerCount(void* sqvm)
-{
- ClientSq_pushinteger(sqvm, g_MasterServerManager->m_remoteServers.size());
- return SQRESULT_NOTNULL;
-}
-
-// string function NSGetServerName( int serverIndex )
-SQRESULT SQ_GetServerName(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get name of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].name, -1);
- return SQRESULT_NOTNULL;
-}
-
-// string function NSGetServerDescription( int serverIndex )
-SQRESULT SQ_GetServerDescription(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get description of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].description.c_str(), -1);
- return SQRESULT_NOTNULL;
-}
-
-// string function NSGetServerMap( int serverIndex )
-SQInteger SQ_GetServerMap(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get map of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].map, -1);
- return SQRESULT_NOTNULL;
-}
-
-// string function NSGetServerPlaylist( int serverIndex )
-SQRESULT SQ_GetServerPlaylist(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get playlist of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].playlist, -1);
- return SQRESULT_NOTNULL;
-}
-
-// int function NSGetServerPlayerCount( int serverIndex )
-SQRESULT SQ_GetServerPlayerCount(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get playercount of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushinteger(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].playerCount);
- return SQRESULT_NOTNULL;
-}
-
-// int function NSGetServerMaxPlayerCount( int serverIndex )
-SQRESULT SQ_GetServerMaxPlayerCount(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get max playercount of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushinteger(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].maxPlayers);
- return SQRESULT_NOTNULL;
-}
-
-// string function NSGetServerID( int serverIndex )
-SQRESULT SQ_GetServerID(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get id of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].id, -1);
- return SQRESULT_NOTNULL;
-}
-
-// bool function NSServerRequiresPassword( int serverIndex )
-SQRESULT SQ_ServerRequiresPassword(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get hasPassword of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushbool(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].requiresPassword);
- return SQRESULT_NOTNULL;
-}
-
-// int function NSGetServerRequiredModsCount( int serverIndex )
-SQRESULT SQ_GetServerRequiredModsCount(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get required mods count of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushinteger(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].requiredMods.size());
- return SQRESULT_NOTNULL;
-}
-
-// string function NSGetServerRequiredModName( int serverIndex, int modIndex )
-SQRESULT SQ_GetServerRequiredModName(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
- SQInteger modIndex = ClientSq_getinteger(sqvm, 2);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get hasPassword of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- if (modIndex >= g_MasterServerManager->m_remoteServers[serverIndex].requiredMods.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get required mod name of mod index {} when only {} mod are available",
- modIndex,
- g_MasterServerManager->m_remoteServers[serverIndex].requiredMods.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].requiredMods[modIndex].Name.c_str(), -1);
- return SQRESULT_NOTNULL;
-}
-
-// string function NSGetServerRequiredModVersion( int serverIndex, int modIndex )
-SQRESULT SQ_GetServerRequiredModVersion(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
- SQInteger modIndex = ClientSq_getinteger(sqvm, 2);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get required mod version of server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- if (modIndex >= g_MasterServerManager->m_remoteServers[serverIndex].requiredMods.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to get required mod version of mod index {} when only {} mod are available",
- modIndex,
- g_MasterServerManager->m_remoteServers[serverIndex].requiredMods.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- ClientSq_pushstring(sqvm, g_MasterServerManager->m_remoteServers[serverIndex].requiredMods[modIndex].Version.c_str(), -1);
- return SQRESULT_NOTNULL;
-}
-
-// void function NSClearRecievedServerList()
-SQRESULT SQ_ClearRecievedServerList(void* sqvm)
-{
- g_MasterServerManager->ClearServerList();
- return SQRESULT_NULL;
-}
-
-// functions for authenticating with servers
-
-// void function NSTryAuthWithServer( int serverIndex, string password = "" )
-SQRESULT SQ_TryAuthWithServer(void* sqvm)
-{
- SQInteger serverIndex = ClientSq_getinteger(sqvm, 1);
- const SQChar* password = ClientSq_getstring(sqvm, 2);
-
- if (serverIndex >= g_MasterServerManager->m_remoteServers.size())
- {
- ClientSq_pusherror(
- sqvm,
- fmt::format(
- "Tried to auth with server index {} when only {} servers are available",
- serverIndex,
- g_MasterServerManager->m_remoteServers.size())
- .c_str());
- return SQRESULT_ERROR;
- }
-
- // send off persistent data first, don't worry about server/client stuff, since m_additionalPlayerData should only have entries when
- // we're a local server note: this seems like it could create a race condition, test later
- for (auto& pair : g_ServerAuthenticationManager->m_additionalPlayerData)
- g_ServerAuthenticationManager->WritePersistentData(pair.first);
-
- // do auth
- g_MasterServerManager->AuthenticateWithServer(
- g_LocalPlayerUserID,
- g_MasterServerManager->m_ownClientAuthToken,
- g_MasterServerManager->m_remoteServers[serverIndex].id,
- (char*)password);
-
- return SQRESULT_NULL;
-}
-
-// bool function NSIsAuthenticatingWithServer()
-SQRESULT SQ_IsAuthComplete(void* sqvm)
-{
- ClientSq_pushbool(sqvm, g_MasterServerManager->m_scriptAuthenticatingWithGameServer);
- return SQRESULT_NOTNULL;
-}
-
-// bool function NSWasAuthSuccessful()
-SQRESULT SQ_WasAuthSuccessful(void* sqvm)
-{
- ClientSq_pushbool(sqvm, g_MasterServerManager->m_successfullyAuthenticatedWithGameServer);
- return SQRESULT_NOTNULL;
-}
-
-// void function NSConnectToAuthedServer()
-SQRESULT SQ_ConnectToAuthedServer(void* sqvm)
-{
- if (!g_MasterServerManager->m_hasPendingConnectionInfo)
- {
- ClientSq_pusherror(sqvm, fmt::format("Tried to connect to authed server before any pending connection info was available").c_str());
- return SQRESULT_ERROR;
- }
-
- RemoteServerConnectionInfo info = g_MasterServerManager->m_pendingConnectionInfo;
-
- // set auth token, then try to connect
- // i'm honestly not entirely sure how silentconnect works regarding ports and encryption so using connect for now
- Cbuf_AddText(Cbuf_GetCurrentPlayer(), fmt::format("serverfilter {}", info.authToken).c_str(), cmd_source_t::kCommandSrcCode);
- Cbuf_AddText(
- Cbuf_GetCurrentPlayer(),
- fmt::format(
- "connect {}.{}.{}.{}:{}",
- info.ip.S_un.S_un_b.s_b1,
- info.ip.S_un.S_un_b.s_b2,
- info.ip.S_un.S_un_b.s_b3,
- info.ip.S_un.S_un_b.s_b4,
- info.port)
- .c_str(),
- cmd_source_t::kCommandSrcCode);
-
- g_MasterServerManager->m_hasPendingConnectionInfo = false;
- return SQRESULT_NULL;
-}
-
-// void function NSTryAuthWithLocalServer()
-SQRESULT SQ_TryAuthWithLocalServer(void* sqvm)
-{
- // do auth request
- g_MasterServerManager->AuthenticateWithOwnServer(g_LocalPlayerUserID, g_MasterServerManager->m_ownClientAuthToken);
-
- return SQRESULT_NULL;
-}
-
-// void function NSCompleteAuthWithLocalServer()
-SQRESULT SQ_CompleteAuthWithLocalServer(void* sqvm)
-{
- // literally just set serverfilter
- // note: this assumes we have no authdata other than our own
- Cbuf_AddText(
- Cbuf_GetCurrentPlayer(),
- fmt::format("serverfilter {}", g_ServerAuthenticationManager->m_authData.begin()->first).c_str(),
- cmd_source_t::kCommandSrcCode);
-
- return SQRESULT_NULL;
-}
-
-void InitialiseScriptServerBrowser(HMODULE baseAddress)
-{
- g_UISquirrelManager->AddFuncRegistration("bool", "NSIsMasterServerAuthenticated", "", "", SQ_IsMasterServerAuthenticated);
- g_UISquirrelManager->AddFuncRegistration("void", "NSRequestServerList", "", "", SQ_RequestServerList);
- g_UISquirrelManager->AddFuncRegistration("bool", "NSIsRequestingServerList", "", "", SQ_IsRequestingServerList);
- g_UISquirrelManager->AddFuncRegistration("bool", "NSMasterServerConnectionSuccessful", "", "", SQ_MasterServerConnectionSuccessful);
- g_UISquirrelManager->AddFuncRegistration("int", "NSGetServerCount", "", "", SQ_GetServerCount);
- g_UISquirrelManager->AddFuncRegistration("void", "NSClearRecievedServerList", "", "", SQ_ClearRecievedServerList);
-
- g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerName", "int serverIndex", "", SQ_GetServerName);
- g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerDescription", "int serverIndex", "", SQ_GetServerDescription);
- g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerMap", "int serverIndex", "", SQ_GetServerMap);
- g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerPlaylist", "int serverIndex", "", SQ_GetServerPlaylist);
- g_UISquirrelManager->AddFuncRegistration("int", "NSGetServerPlayerCount", "int serverIndex", "", SQ_GetServerPlayerCount);
- g_UISquirrelManager->AddFuncRegistration("int", "NSGetServerMaxPlayerCount", "int serverIndex", "", SQ_GetServerMaxPlayerCount);
- g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerID", "int serverIndex", "", SQ_GetServerID);
- g_UISquirrelManager->AddFuncRegistration("bool", "NSServerRequiresPassword", "int serverIndex", "", SQ_ServerRequiresPassword);
- g_UISquirrelManager->AddFuncRegistration("int", "NSGetServerRequiredModsCount", "int serverIndex", "", SQ_GetServerRequiredModsCount);
- g_UISquirrelManager->AddFuncRegistration(
- "string", "NSGetServerRequiredModName", "int serverIndex, int modIndex", "", SQ_GetServerRequiredModName);
- g_UISquirrelManager->AddFuncRegistration(
- "string", "NSGetServerRequiredModVersion", "int serverIndex, int modIndex", "", SQ_GetServerRequiredModVersion);
-
- g_UISquirrelManager->AddFuncRegistration(
- "void", "NSTryAuthWithServer", "int serverIndex, string password = \"\"", "", SQ_TryAuthWithServer);
- g_UISquirrelManager->AddFuncRegistration("bool", "NSIsAuthenticatingWithServer", "", "", SQ_IsAuthComplete);
- g_UISquirrelManager->AddFuncRegistration("bool", "NSWasAuthSuccessful", "", "", SQ_WasAuthSuccessful);
- g_UISquirrelManager->AddFuncRegistration("void", "NSConnectToAuthedServer", "", "", SQ_ConnectToAuthedServer);
-
- g_UISquirrelManager->AddFuncRegistration("void", "NSTryAuthWithLocalServer", "", "", SQ_TryAuthWithLocalServer);
- g_UISquirrelManager->AddFuncRegistration("void", "NSCompleteAuthWithLocalServer", "", "", SQ_CompleteAuthWithLocalServer);
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptserverbrowser.h b/NorthstarDedicatedTest/scriptserverbrowser.h
deleted file mode 100644
index 55776de0..00000000
--- a/NorthstarDedicatedTest/scriptserverbrowser.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-#include <minwindef.h>
-
-void InitialiseScriptServerBrowser(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/scriptservertoclientstringcommand.cpp b/NorthstarDedicatedTest/scriptservertoclientstringcommand.cpp
deleted file mode 100644
index 084db1e4..00000000
--- a/NorthstarDedicatedTest/scriptservertoclientstringcommand.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "pch.h"
-#include "scriptservertoclientstringcommand.h"
-#include "squirrel.h"
-#include "convar.h"
-#include "concommand.h"
-
-void ConCommand_ns_script_servertoclientstringcommand(const CCommand& arg)
-{
- if (g_ClientSquirrelManager->sqvm &&
- g_ClientSquirrelManager->setupfunc("NSClientCodeCallback_RecievedServerToClientStringCommand") != SQRESULT_ERROR)
- {
- g_ClientSquirrelManager->pusharg(arg.ArgS());
- g_ClientSquirrelManager->call(1); // todo: doesn't throw or log errors from within this, probably not great behaviour
- }
-}
-
-void InitialiseScriptServerToClientStringCommands(HMODULE baseAddress)
-{
- RegisterConCommand(
- "ns_script_servertoclientstringcommand",
- ConCommand_ns_script_servertoclientstringcommand,
- "",
- FCVAR_CLIENTDLL | FCVAR_SERVER_CAN_EXECUTE);
-}
diff --git a/NorthstarDedicatedTest/scriptservertoclientstringcommand.h b/NorthstarDedicatedTest/scriptservertoclientstringcommand.h
deleted file mode 100644
index 609c6105..00000000
--- a/NorthstarDedicatedTest/scriptservertoclientstringcommand.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void InitialiseScriptServerToClientStringCommands(HMODULE baseAddress); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp
deleted file mode 100644
index 09ed41d3..00000000
--- a/NorthstarDedicatedTest/serverauthentication.cpp
+++ /dev/null
@@ -1,743 +0,0 @@
-#include "pch.h"
-#include "serverauthentication.h"
-#include "cvar.h"
-#include "convar.h"
-#include "hookutils.h"
-#include "masterserver.h"
-#include "httplib.h"
-#include "gameutils.h"
-#include "bansystem.h"
-#include "miscserverscript.h"
-#include "concommand.h"
-#include "dedicated.h"
-#include <fstream>
-#include <filesystem>
-#include <thread>
-#include "configurables.h"
-#include "NSMem.h"
-
-const char* AUTHSERVER_VERIFY_STRING = "I am a northstar server!";
-
-// hook types
-
-typedef void* (*CBaseServer__ConnectClientType)(
- void* server,
- void* a2,
- void* a3,
- uint32_t a4,
- uint32_t a5,
- int32_t a6,
- void* a7,
- void* a8,
- char* serverFilter,
- void* a10,
- char a11,
- void* a12,
- char a13,
- char a14,
- int64_t uid,
- uint32_t a16,
- uint32_t a17);
-CBaseServer__ConnectClientType CBaseServer__ConnectClient;
-
-typedef bool (*CBaseClient__ConnectType)(
- void* self, char* name, __int64 netchan_ptr_arg, char b_fake_player_arg, __int64 a5, char* Buffer, void* a7);
-CBaseClient__ConnectType CBaseClient__Connect;
-
-typedef void (*CBaseClient__ActivatePlayerType)(void* self);
-CBaseClient__ActivatePlayerType CBaseClient__ActivatePlayer;
-
-CBaseClient__DisconnectType CBaseClient__Disconnect;
-
-typedef char (*CGameClient__ExecuteStringCommandType)(void* self, uint32_t unknown, const char* pCommandString);
-CGameClient__ExecuteStringCommandType CGameClient__ExecuteStringCommand;
-
-typedef char (*__fastcall CNetChan___ProcessMessagesType)(void* self, void* buf);
-CNetChan___ProcessMessagesType CNetChan___ProcessMessages;
-
-typedef char (*CBaseClient__SendServerInfoType)(void* self);
-CBaseClient__SendServerInfoType CBaseClient__SendServerInfo;
-
-typedef bool (*ProcessConnectionlessPacketType)(void* a1, netpacket_t* packet);
-ProcessConnectionlessPacketType ProcessConnectionlessPacket;
-
-typedef void (*CServerGameDLL__OnReceivedSayTextMessageType)(void* self, unsigned int senderClientIndex, const char* message, char unknown);
-CServerGameDLL__OnReceivedSayTextMessageType CServerGameDLL__OnReceivedSayTextMessage;
-
-typedef void (*ConCommand__DispatchType)(ConCommand* command, const CCommand& args, void* a3);
-ConCommand__DispatchType ConCommand__Dispatch;
-
-// global vars
-ServerAuthenticationManager* g_ServerAuthenticationManager;
-
-ConVar* Cvar_ns_player_auth_port;
-ConVar* Cvar_ns_erase_auth_info;
-ConVar* CVar_ns_auth_allow_insecure;
-ConVar* CVar_ns_auth_allow_insecure_write;
-ConVar* CVar_sv_quota_stringcmdspersecond;
-ConVar* Cvar_net_chan_limit_mode;
-ConVar* Cvar_net_chan_limit_msec_per_sec;
-ConVar* Cvar_sv_querylimit_per_sec;
-ConVar* Cvar_sv_max_chat_messages_per_sec;
-
-ConVar* Cvar_net_datablock_enabled;
-
-void ServerAuthenticationManager::StartPlayerAuthServer()
-{
- if (m_runningPlayerAuthThread)
- {
- spdlog::warn("ServerAuthenticationManager::StartPlayerAuthServer was called while m_runningPlayerAuthThread is true");
- return;
- }
-
- m_runningPlayerAuthThread = true;
-
- // listen is a blocking call so thread this
- std::thread serverThread(
- [this]
- {
- // this is just a super basic way to verify that servers have ports open, masterserver will try to read this before ensuring
- // server is legit
- m_playerAuthServer.Get(
- "/verify",
- [](const httplib::Request& request, httplib::Response& response)
- { response.set_content(AUTHSERVER_VERIFY_STRING, "text/plain"); });
-
- m_playerAuthServer.Post(
- "/authenticate_incoming_player",
- [this](const httplib::Request& request, httplib::Response& response)
- {
- // can't just do request.remote_addr == Cvar_ns_masterserver_hostname->GetString() because the cvar can be a url, gotta
- // resolve an ip from it for comparisons
- // unsigned long remoteAddr = inet_addr(request.remote_addr.c_str());
- //
- // char* addrPtr = Cvar_ns_masterserver_hostname->GetString();
- // char* typeStart = strstr(addrPtr, "://");
- // if (typeStart)
- // addrPtr = typeStart + 3;
- // hostent* resolvedRemoteAddr = gethostbyname((const char*)addrPtr);
-
- if (!request.has_param("id") || !request.has_param("authToken") || request.body.size() >= 65335 ||
- !request.has_param("serverAuthToken") ||
- strcmp(
- g_MasterServerManager->m_ownServerAuthToken,
- request.get_param_value("serverAuthToken")
- .c_str())) // || !resolvedRemoteAddr || ((in_addr**)resolvedRemoteAddr->h_addr_list)[0]->S_un.S_addr !=
- // remoteAddr)
- {
- response.set_content("{\"success\":false}", "application/json");
- return;
- }
-
- // Log playername and UID from request
- spdlog::info(
- "Player \"{}\" with UID \"{}\" requested to join",
- request.get_param_value("username").c_str(),
- request.get_param_value("id").c_str());
-
- AuthData newAuthData {};
- strncpy(newAuthData.uid, request.get_param_value("id").c_str(), sizeof(newAuthData.uid));
- newAuthData.uid[sizeof(newAuthData.uid) - 1] = 0;
-
- strncpy(newAuthData.username, request.get_param_value("username").c_str(), sizeof(newAuthData.username));
- newAuthData.username[sizeof(newAuthData.username) - 1] = 0;
-
- newAuthData.pdataSize = request.body.size();
- newAuthData.pdata = new char[newAuthData.pdataSize];
- memcpy(newAuthData.pdata, request.body.c_str(), newAuthData.pdataSize);
-
- std::lock_guard<std::mutex> guard(m_authDataMutex);
- m_authData.insert(std::make_pair(request.get_param_value("authToken"), newAuthData));
-
- response.set_content("{\"success\":true}", "application/json");
- });
-
- m_playerAuthServer.listen("0.0.0.0", Cvar_ns_player_auth_port->GetInt());
- });
-
- serverThread.detach();
-}
-
-void ServerAuthenticationManager::StopPlayerAuthServer()
-{
- if (!m_runningPlayerAuthThread)
- {
- spdlog::warn("ServerAuthenticationManager::StopPlayerAuthServer was called while m_runningPlayerAuthThread is false");
- return;
- }
-
- m_runningPlayerAuthThread = false;
- m_playerAuthServer.stop();
-}
-
-char* ServerAuthenticationManager::VerifyPlayerName(void* player, char* authToken, char* name)
-{
- std::lock_guard<std::mutex> guard(m_authDataMutex);
-
- if (!m_authData.empty() && m_authData.count(std::string(authToken)))
- {
- AuthData authData = m_authData[authToken];
-
- bool nameAccepted = (!*authData.username || !strcmp(name, authData.username));
-
- if (!nameAccepted && g_MasterServerManager->m_bRequireClientAuth && !CVar_ns_auth_allow_insecure->GetInt())
- {
- // limit name length to 64 characters just in case something changes, this technically shouldn't be needed given the master
- // server gets usernames from origin but we have it just in case
- strncpy(name, authData.username, 64);
- name[63] = 0;
- }
- }
- return name;
-}
-
-bool ServerAuthenticationManager::AuthenticatePlayer(void* player, int64_t uid, char* authToken)
-{
- std::string strUid = std::to_string(uid);
- std::lock_guard<std::mutex> guard(m_authDataMutex);
-
- bool authFail = true;
- if (!m_authData.empty() && m_authData.count(std::string(authToken)))
- {
- // use stored auth data
- AuthData authData = m_authData[authToken];
-
- // Log playnername and UID from request
- spdlog::info("Comparing connecting UID \"{}\" against stored UID from ms auth request \"{}\"", strUid.c_str(), authData.uid);
-
- if (!strcmp(strUid.c_str(), authData.uid)) // connecting client's uid is the same as auth's uid
- {
- authFail = false;
- // uuid
- strcpy((char*)player + 0xF500, strUid.c_str());
-
- // reset from disk if we're doing that
- if (m_bForceReadLocalPlayerPersistenceFromDisk && !strcmp(authData.uid, g_LocalPlayerUserID))
- {
- std::fstream pdataStream(GetNorthstarPrefix() + "/placeholder_playerdata.pdata", std::ios_base::in);
-
- if (!pdataStream.fail())
- {
- // get file length
- pdataStream.seekg(0, pdataStream.end);
- auto length = pdataStream.tellg();
- pdataStream.seekg(0, pdataStream.beg);
-
- // copy pdata into buffer
- pdataStream.read((char*)player + 0x4FA, length);
- }
- else // fallback to remote pdata if no local default
- memcpy((char*)player + 0x4FA, authData.pdata, authData.pdataSize);
- }
- else
- {
- // copy pdata into buffer
- memcpy((char*)player + 0x4FA, authData.pdata, authData.pdataSize);
- }
-
- // set persistent data as ready, we use 0x4 internally to mark the client as using remote persistence
- *((char*)player + 0x4a0) = (char)0x4;
- }
- }
-
- if (authFail)
- {
- // set persistent data as ready, we use 0x3 internally to mark the client as using local persistence
- *((char*)player + 0x4a0) = (char)0x3;
-
- if (!CVar_ns_auth_allow_insecure->GetBool()) // no auth data and insecure connections aren't allowed, so dc the client
- return false;
-
- // insecure connections are allowed, try reading from disk
- // uuid
- strcpy((char*)player + 0xF500, strUid.c_str());
-
- // try reading pdata file for player
- std::string pdataPath = GetNorthstarPrefix() + "/playerdata_";
- pdataPath += strUid;
- pdataPath += ".pdata";
-
- std::fstream pdataStream(pdataPath, std::ios_base::in);
- if (pdataStream.fail()) // file doesn't exist, use placeholder
- pdataStream = std::fstream(GetNorthstarPrefix() + "/placeholder_playerdata.pdata");
-
- // get file length
- pdataStream.seekg(0, pdataStream.end);
- auto length = pdataStream.tellg();
- pdataStream.seekg(0, pdataStream.beg);
-
- // copy pdata into buffer
- pdataStream.read((char*)player + 0x4FA, length);
-
- pdataStream.close();
- }
-
- return true; // auth successful, client stays on
-}
-
-bool ServerAuthenticationManager::RemovePlayerAuthData(void* player)
-{
- if (!Cvar_ns_erase_auth_info->GetBool())
- return false;
-
- // hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect
- if (m_bNeedLocalAuthForNewgame && !strcmp((char*)player + 0xF500, g_LocalPlayerUserID))
- return false;
-
- // we don't have our auth token at this point, so lookup authdata by uid
- for (auto& auth : m_authData)
- {
- if (!strcmp((char*)player + 0xF500, auth.second.uid))
- {
- // Log UID
- spdlog::info("Erasing auth data from UID \"{}\"", auth.second.uid);
- // pretty sure this is fine, since we don't iterate after the erase
- // i think if we iterated after it'd be undefined behaviour tho
- std::lock_guard<std::mutex> guard(m_authDataMutex);
-
- delete[] auth.second.pdata;
- m_authData.erase(auth.first);
- return true;
- }
- }
-
- return false;
-}
-
-void ServerAuthenticationManager::WritePersistentData(void* player)
-{
- // we use 0x4 internally to mark clients as using remote persistence
- if (*((char*)player + 0x4A0) == (char)0x4)
- {
- g_MasterServerManager->WritePlayerPersistentData(
- (char*)player + 0xF500, (char*)player + 0x4FA, m_additionalPlayerData[player].pdataSize);
- }
- else if (CVar_ns_auth_allow_insecure_write->GetBool())
- {
- // todo: write pdata to disk here
- }
-}
-
-bool ServerAuthenticationManager::CheckPlayerChatRatelimit(void* player)
-{
- if (Plat_FloatTime() - m_additionalPlayerData[player].lastSayTextLimitStart >= 1.0)
- {
- m_additionalPlayerData[player].lastSayTextLimitStart = Plat_FloatTime();
- m_additionalPlayerData[player].sayTextLimitCount = 0;
- }
-
- if (m_additionalPlayerData[player].sayTextLimitCount >= Cvar_sv_max_chat_messages_per_sec->GetInt())
- return false;
-
- m_additionalPlayerData[player].sayTextLimitCount++;
- return true;
-}
-
-// auth hooks
-
-// store these in vars so we can use them in CBaseClient::Connect
-// this is fine because ptrs won't decay by the time we use this, just don't use it outside of cbaseclient::connect
-char* nextPlayerToken;
-uint64_t nextPlayerUid;
-
-void* CBaseServer__ConnectClientHook(
- void* server,
- void* a2,
- void* a3,
- uint32_t a4,
- uint32_t a5,
- int32_t a6,
- void* a7,
- void* a8,
- char* serverFilter,
- void* a10,
- char a11,
- void* a12,
- char a13,
- char a14,
- int64_t uid,
- uint32_t a16,
- uint32_t a17)
-{
- // auth tokens are sent with serverfilter, can't be accessed from player struct to my knowledge, so have to do this here
- nextPlayerToken = serverFilter;
- nextPlayerUid = uid;
-
- // Random UID log
- spdlog::info("CBaseServer__ConnectClientHook says UID \"{}\"", uid);
-
- return CBaseServer__ConnectClient(server, a2, a3, a4, a5, a6, a7, a8, serverFilter, a10, a11, a12, a13, a14, uid, a16, a17);
-}
-
-bool CBaseClient__ConnectHook(void* self, char* name, __int64 netchan_ptr_arg, char b_fake_player_arg, __int64 a5, char* Buffer, void* a7)
-{
- // try changing name before all else
- name = g_ServerAuthenticationManager->VerifyPlayerName(self, nextPlayerToken, name);
-
- // try to auth player, dc if it fails
- // we connect irregardless of auth, because returning bad from this function can fuck client state p bad
- bool ret = CBaseClient__Connect(self, name, netchan_ptr_arg, b_fake_player_arg, a5, Buffer, a7);
-
- // Another UID log
- spdlog::info("CBaseClient__ConnectHook says UID \"{}\"", nextPlayerUid);
-
- if (!ret)
- return ret;
-
- if (!g_ServerBanSystem->IsUIDAllowed(nextPlayerUid))
- {
- CBaseClient__Disconnect(self, 1, "Banned from server");
- return ret;
- }
-
- if (strlen(name) >= 64) // fix for name overflow bug
- CBaseClient__Disconnect(self, 1, "Invalid name");
- else if (
- !g_ServerAuthenticationManager->AuthenticatePlayer(self, nextPlayerUid, nextPlayerToken) &&
- g_MasterServerManager->m_bRequireClientAuth)
- CBaseClient__Disconnect(self, 1, "Authentication Failed");
-
- if (!g_ServerAuthenticationManager->m_additionalPlayerData.count(self))
- {
- AdditionalPlayerData additionalData;
- additionalData.pdataSize = g_ServerAuthenticationManager->m_authData[nextPlayerToken].pdataSize;
- additionalData.usingLocalPdata = *((char*)self + 0x4a0) == (char)0x3;
-
- g_ServerAuthenticationManager->m_additionalPlayerData.insert(std::make_pair(self, additionalData));
-
- g_ServerAuthenticationManager->m_additionalPlayerData[self].uid = nextPlayerUid;
- }
-
- return ret;
-}
-
-void CBaseClient__ActivatePlayerHook(void* self)
-{
- bool uidMatches = false;
- if (g_ServerAuthenticationManager->m_additionalPlayerData.count(self))
- {
- std::string strUid = std::to_string(g_ServerAuthenticationManager->m_additionalPlayerData[self].uid);
- if (!strcmp(strUid.c_str(), (char*)self + 0xF500)) // connecting client's uid is the same as auth's uid
- {
- uidMatches = true;
- }
- }
- if (!uidMatches)
- {
- CBaseClient__Disconnect(self, 1, "Authentication Failed");
- return;
- }
-
- // if we're authed, write our persistent data
- // RemovePlayerAuthData returns true if it removed successfully, i.e. on first call only, and we only want to write on >= second call
- // (since this func is called on map loads)
- if (*((char*)self + 0x4A0) >= (char)0x3 && !g_ServerAuthenticationManager->RemovePlayerAuthData(self))
- {
- g_ServerAuthenticationManager->m_bForceReadLocalPlayerPersistenceFromDisk = false;
- g_ServerAuthenticationManager->WritePersistentData(self);
- g_MasterServerManager->UpdateServerPlayerCount(g_ServerAuthenticationManager->m_additionalPlayerData.size());
- }
- // Log UID
- spdlog::info("In CBaseClient__ActivatePlayerHook, activating UID \"{}\"", (char*)self + 0xF500);
-
- CBaseClient__ActivatePlayer(self);
-}
-
-void CBaseClient__DisconnectHook(void* self, uint32_t unknownButAlways1, const char* reason, ...)
-{
- // have to manually format message because can't pass varargs to original func
- char buf[1024];
-
- va_list va;
- va_start(va, reason);
- vsprintf(buf, reason, va);
- va_end(va);
-
- // this reason is used while connecting to a local server, hacky, but just ignore it
- if (strcmp(reason, "Connection closing"))
- {
- spdlog::info("Player {} disconnected: \"{}\"", (char*)self + 0x16, buf);
-
- // dcing, write persistent data
- if (g_ServerAuthenticationManager->m_additionalPlayerData[self].needPersistenceWriteOnLeave)
- g_ServerAuthenticationManager->WritePersistentData(self);
- g_ServerAuthenticationManager->RemovePlayerAuthData(self); // won't do anything 99% of the time, but just in case
- }
-
- if (g_ServerAuthenticationManager->m_additionalPlayerData.count(self))
- {
- g_ServerAuthenticationManager->m_additionalPlayerData.erase(self);
- g_MasterServerManager->UpdateServerPlayerCount(g_ServerAuthenticationManager->m_additionalPlayerData.size());
- }
-
- CBaseClient__Disconnect(self, unknownButAlways1, buf);
-}
-
-// maybe this should be done outside of auth code, but effort to refactor rn and it sorta fits
-typedef bool (*CCommand__TokenizeType)(CCommand& self, const char* pCommandString, cmd_source_t commandSource);
-CCommand__TokenizeType CCommand__Tokenize;
-
-char CGameClient__ExecuteStringCommandHook(void* self, uint32_t unknown, const char* pCommandString)
-{
- if (CVar_sv_quota_stringcmdspersecond->GetInt() != -1)
- {
- // note: this isn't super perfect, legit clients can trigger it in lobby, mostly good enough tho imo
- // https://github.com/perilouswithadollarsign/cstrike15_src/blob/f82112a2388b841d72cb62ca48ab1846dfcc11c8/engine/sv_client.cpp#L1513
- if (Plat_FloatTime() - g_ServerAuthenticationManager->m_additionalPlayerData[self].lastClientCommandQuotaStart >= 1.0)
- {
- // reset quota
- g_ServerAuthenticationManager->m_additionalPlayerData[self].lastClientCommandQuotaStart = Plat_FloatTime();
- g_ServerAuthenticationManager->m_additionalPlayerData[self].numClientCommandsInQuota = 0;
- }
-
- g_ServerAuthenticationManager->m_additionalPlayerData[self].numClientCommandsInQuota++;
- if (g_ServerAuthenticationManager->m_additionalPlayerData[self].numClientCommandsInQuota >
- CVar_sv_quota_stringcmdspersecond->GetInt())
- {
- // too many stringcmds, dc player
- CBaseClient__Disconnect(self, 1, "Sent too many stringcmd commands");
- return false;
- }
- }
-
- // verify the command we're trying to execute is FCVAR_CLIENTCMD_CAN_EXECUTE, if it's a concommand
- char* commandBuf[1040]; // assumedly this is the size of CCommand since we don't have an actual constructor
- memset(commandBuf, 0, sizeof(commandBuf));
- CCommand tempCommand = *(CCommand*)&commandBuf;
-
- if (!CCommand__Tokenize(tempCommand, pCommandString, cmd_source_t::kCommandSrcCode) || !tempCommand.ArgC())
- return false;
-
- ConCommand* command = g_pCVar->FindCommand(tempCommand.Arg(0));
-
- // if the command doesn't exist pass it on to ExecuteStringCommand for script clientcommands and stuff
- if (command && !command->IsFlagSet(FCVAR_CLIENTCMD_CAN_EXECUTE))
- {
- // ensure FCVAR_GAMEDLL concommands without FCVAR_CLIENTCMD_CAN_EXECUTE can't be executed by remote clients
- if (IsDedicated())
- return false;
-
- if (strcmp((char*)self + 0xF500, g_LocalPlayerUserID))
- return false;
- }
-
- // todo later, basically just limit to CVar_sv_quota_stringcmdspersecond->GetInt() stringcmds per client per second
- return CGameClient__ExecuteStringCommand(self, unknown, pCommandString);
-}
-
-char __fastcall CNetChan___ProcessMessagesHook(void* self, void* buf)
-{
- double startTime = Plat_FloatTime();
- char ret = CNetChan___ProcessMessages(self, buf);
-
- // check processing limits, unless we're in a level transition
- if (g_pHostState->m_iCurrentState == HostState_t::HS_RUN && ThreadInServerFrameThread())
- {
- // player that sent the message
- void* sender = *(void**)((char*)self + 368);
-
- // if no sender, return
- // relatively certain this is fine?
- if (!sender || !g_ServerAuthenticationManager->m_additionalPlayerData.count(sender))
- return ret;
-
- // reset every second
- if (startTime - g_ServerAuthenticationManager->m_additionalPlayerData[sender].lastNetChanProcessingLimitStart >= 1.0 ||
- g_ServerAuthenticationManager->m_additionalPlayerData[sender].lastNetChanProcessingLimitStart == -1.0)
- {
- g_ServerAuthenticationManager->m_additionalPlayerData[sender].lastNetChanProcessingLimitStart = startTime;
- g_ServerAuthenticationManager->m_additionalPlayerData[sender].netChanProcessingLimitTime = 0.0;
- }
- g_ServerAuthenticationManager->m_additionalPlayerData[sender].netChanProcessingLimitTime +=
- (Plat_FloatTime() * 1000) - (startTime * 1000);
-
- if (g_ServerAuthenticationManager->m_additionalPlayerData[sender].netChanProcessingLimitTime >=
- Cvar_net_chan_limit_msec_per_sec->GetInt())
- {
- spdlog::warn(
- "Client {} hit netchan processing limit with {}ms of processing time this second (max is {})",
- (char*)sender + 0x16,
- g_ServerAuthenticationManager->m_additionalPlayerData[sender].netChanProcessingLimitTime,
- Cvar_net_chan_limit_msec_per_sec->GetInt());
-
- // nonzero = kick, 0 = warn, but never kick local player
- if (Cvar_net_chan_limit_mode->GetInt() && strcmp(g_LocalPlayerUserID, (char*)sender + 0xF500))
- {
- CBaseClient__Disconnect(sender, 1, "Exceeded net channel processing limit");
- return false;
- }
- }
- }
-
- return ret;
-}
-
-bool bWasWritingStringTableSuccessful;
-
-void CBaseClient__SendServerInfoHook(void* self)
-{
- bWasWritingStringTableSuccessful = true;
- CBaseClient__SendServerInfo(self);
- if (!bWasWritingStringTableSuccessful)
- CBaseClient__Disconnect(
- self, 1, "Overflowed CNetworkStringTableContainer::WriteBaselines, try restarting your client and reconnecting");
-}
-
-bool ProcessConnectionlessPacketHook(void* a1, netpacket_t* packet)
-{
- if (packet->adr.type == NA_IP &&
- (!(packet->data[4] == 'N' && Cvar_net_datablock_enabled->GetBool()) || !Cvar_net_datablock_enabled->GetBool()))
- {
- // bad lookup: optimise later tm
- UnconnectedPlayerSendData* sendData = nullptr;
- for (UnconnectedPlayerSendData& foundSendData : g_ServerAuthenticationManager->m_unconnectedPlayerSendData)
- {
- if (!memcmp(packet->adr.ip, foundSendData.ip, 16))
- {
- sendData = &foundSendData;
- break;
- }
- }
-
- if (!sendData)
- {
- sendData = &g_ServerAuthenticationManager->m_unconnectedPlayerSendData.emplace_back();
- memcpy(sendData->ip, packet->adr.ip, 16);
- }
-
- if (Plat_FloatTime() < sendData->timeoutEnd)
- return false;
-
- if (Plat_FloatTime() - sendData->lastQuotaStart >= 1.0)
- {
- sendData->lastQuotaStart = Plat_FloatTime();
- sendData->packetCount = 0;
- }
-
- sendData->packetCount++;
-
- if (sendData->packetCount >= Cvar_sv_querylimit_per_sec->GetInt())
- {
- spdlog::warn(
- "Client went over connectionless ratelimit of {} per sec with packet of type {}",
- Cvar_sv_querylimit_per_sec->GetInt(),
- packet->data[4]);
-
- // timeout for a minute
- sendData->timeoutEnd = Plat_FloatTime() + 60.0;
- return false;
- }
- }
-
- return ProcessConnectionlessPacket(a1, packet);
-}
-
-void ResetPdataCommand(const CCommand& args)
-{
- if (*sv_m_State == server_state_t::ss_active)
- {
- spdlog::error("ns_resetpersistence must be entered from the main menu");
- return;
- }
-
- spdlog::info("resetting persistence on next lobby load...");
- g_ServerAuthenticationManager->m_bForceReadLocalPlayerPersistenceFromDisk = true;
-}
-
-void InitialiseServerAuthentication(HMODULE baseAddress)
-{
- g_ServerAuthenticationManager = new ServerAuthenticationManager;
-
- Cvar_ns_erase_auth_info =
- new ConVar("ns_erase_auth_info", "1", FCVAR_GAMEDLL, "Whether auth info should be erased from this server on disconnect or crash");
- CVar_ns_auth_allow_insecure =
- new ConVar("ns_auth_allow_insecure", "0", FCVAR_GAMEDLL, "Whether this server will allow unauthenicated players to connect");
- CVar_ns_auth_allow_insecure_write = new ConVar(
- "ns_auth_allow_insecure_write",
- "0",
- FCVAR_GAMEDLL,
- "Whether the pdata of unauthenticated clients will be written to disk when changed");
- // literally just stolen from a fix valve used in csgo
- CVar_sv_quota_stringcmdspersecond = new ConVar(
- "sv_quota_stringcmdspersecond",
- "60",
- FCVAR_GAMEDLL,
- "How many string commands per second clients are allowed to submit, 0 to disallow all string commands");
- // https://blog.counter-strike.net/index.php/2019/07/24922/ but different because idk how to check what current tick number is
- Cvar_net_chan_limit_mode =
- new ConVar("net_chan_limit_mode", "0", FCVAR_GAMEDLL, "The mode for netchan processing limits: 0 = log, 1 = kick");
- Cvar_net_chan_limit_msec_per_sec = new ConVar(
- "net_chan_limit_msec_per_sec",
- "0",
- FCVAR_GAMEDLL,
- "Netchannel processing is limited to so many milliseconds, abort connection if exceeding budget");
- Cvar_ns_player_auth_port = new ConVar("ns_player_auth_port", "8081", FCVAR_GAMEDLL, "");
- Cvar_sv_querylimit_per_sec = new ConVar("sv_querylimit_per_sec", "15", FCVAR_GAMEDLL, "");
- Cvar_sv_max_chat_messages_per_sec = new ConVar("sv_max_chat_messages_per_sec", "5", FCVAR_GAMEDLL, "");
-
- Cvar_net_datablock_enabled = g_pCVar->FindVar("net_datablock_enabled");
-
- RegisterConCommand("ns_resetpersistence", ResetPdataCommand, "resets your pdata when you next enter the lobby", FCVAR_NONE);
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x114430, &CBaseServer__ConnectClientHook, reinterpret_cast<LPVOID*>(&CBaseServer__ConnectClient));
- ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x101740, &CBaseClient__ConnectHook, reinterpret_cast<LPVOID*>(&CBaseClient__Connect));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x100F80, &CBaseClient__ActivatePlayerHook, reinterpret_cast<LPVOID*>(&CBaseClient__ActivatePlayer));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x1012C0, &CBaseClient__DisconnectHook, reinterpret_cast<LPVOID*>(&CBaseClient__Disconnect));
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x1022E0,
- &CGameClient__ExecuteStringCommandHook,
- reinterpret_cast<LPVOID*>(&CGameClient__ExecuteStringCommand));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x2140A0, &CNetChan___ProcessMessagesHook, reinterpret_cast<LPVOID*>(&CNetChan___ProcessMessages));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x104FB0, &CBaseClient__SendServerInfoHook, reinterpret_cast<LPVOID*>(&CBaseClient__SendServerInfo));
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x117800, &ProcessConnectionlessPacketHook, reinterpret_cast<LPVOID*>(&ProcessConnectionlessPacket));
-
- CCommand__Tokenize = (CCommand__TokenizeType)((char*)baseAddress + 0x418380);
-
- uintptr_t ba = (uintptr_t)baseAddress;
-
- // patch to disable kicking based on incorrect serverfilter in connectclient, since we repurpose it for use as an auth token
- {
- NSMem::BytePatch(
- ba + 0x114655,
- "EB" // jz => jmp
- );
- }
-
- // patch to disable fairfight marking players as cheaters and kicking them
- {
- NSMem::BytePatch(
- ba + 0x101012,
- "E9 90 00" // jz => jmp
- );
- }
-
- // patch to allow same of multiple account
- if (CommandLine()->CheckParm("-allowdupeaccounts"))
- {
- NSMem::BytePatch(
- ba + 0x114510,
- "EB" // jz => jmp
- );
- }
-
- // patch to set bWasWritingStringTableSuccessful in CNetworkStringTableContainer::WriteBaselines if it fails
- {
- uintptr_t writeAddress = (uintptr_t)(&bWasWritingStringTableSuccessful - (ba + 0x234EDC));
-
- auto addr = ba + 0x234ED2;
- NSMem::BytePatch(addr, "C7 05");
- NSMem::BytePatch(addr + 2, (BYTE*)&writeAddress, sizeof(writeAddress));
-
- NSMem::BytePatch(addr + 6, "00 00 00 00");
-
- NSMem::NOP(addr + 10, 5);
- }
-}
diff --git a/NorthstarDedicatedTest/serverauthentication.h b/NorthstarDedicatedTest/serverauthentication.h
deleted file mode 100644
index e79577e6..00000000
--- a/NorthstarDedicatedTest/serverauthentication.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#pragma once
-#include "convar.h"
-#include "httplib.h"
-#include <unordered_map>
-#include <string>
-
-struct AuthData
-{
- char uid[33];
- char username[64];
-
- // pdata
- char* pdata;
- size_t pdataSize;
-};
-
-struct AdditionalPlayerData
-{
- bool usingLocalPdata;
- size_t pdataSize;
- bool needPersistenceWriteOnLeave = true;
-
- double lastClientCommandQuotaStart = -1.0;
- int numClientCommandsInQuota = 0;
-
- double lastNetChanProcessingLimitStart = -1.0;
- double netChanProcessingLimitTime = 0.0;
-
- double lastSayTextLimitStart = -1.0;
- int sayTextLimitCount = 0;
-
- uint64_t uid;
-};
-
-#pragma once
-typedef enum
-{
- NA_NULL = 0,
- NA_LOOPBACK,
- NA_IP,
-} netadrtype_t;
-
-#pragma pack(push, 1)
-typedef struct netadr_s
-{
- netadrtype_t type;
- unsigned char ip[16]; // IPv6
- // IPv4's 127.0.0.1 is [::ffff:127.0.0.1], that is:
- // 00 00 00 00 00 00 00 00 00 00 FF FF 7F 00 00 01
- unsigned short port;
-} netadr_t;
-#pragma pack(pop)
-
-#pragma pack(push, 1)
-typedef struct netpacket_s
-{
- netadr_t adr; // sender address
- // int source; // received source
- char unk[10];
- double received_time;
- unsigned char* data; // pointer to raw packet data
- void* message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
- char unk2[16];
- int size;
-
- // bf_read message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
- // int size; // size in bytes
- // int wiresize; // size in bytes before decompression
- // bool stream; // was send as stream
- // struct netpacket_s* pNext; // for internal use, should be NULL in public
-} netpacket_t;
-#pragma pack(pop)
-
-struct UnconnectedPlayerSendData
-{
- char ip[16];
- double lastQuotaStart = 0.0;
- int packetCount = 0;
- double timeoutEnd = -1.0;
-};
-
-class ServerAuthenticationManager
-{
- private:
- httplib::Server m_playerAuthServer;
-
- public:
- std::mutex m_authDataMutex;
- std::unordered_map<std::string, AuthData> m_authData;
- std::unordered_map<void*, AdditionalPlayerData> m_additionalPlayerData;
- std::vector<UnconnectedPlayerSendData> m_unconnectedPlayerSendData;
- bool m_runningPlayerAuthThread = false;
- bool m_bNeedLocalAuthForNewgame = false;
- bool m_bForceReadLocalPlayerPersistenceFromDisk = false;
-
- public:
- void StartPlayerAuthServer();
- void StopPlayerAuthServer();
- bool AuthenticatePlayer(void* player, int64_t uid, char* authToken);
- char* VerifyPlayerName(void* player, char* authToken, char* name);
- bool RemovePlayerAuthData(void* player);
- void WritePersistentData(void* player);
- bool CheckPlayerChatRatelimit(void* player);
-};
-
-typedef void (*CBaseClient__DisconnectType)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
-extern CBaseClient__DisconnectType CBaseClient__Disconnect;
-
-void InitialiseServerAuthentication(HMODULE baseAddress);
-
-extern ServerAuthenticationManager* g_ServerAuthenticationManager;
-extern ConVar* Cvar_ns_player_auth_port;
diff --git a/NorthstarDedicatedTest/serverchathooks.cpp b/NorthstarDedicatedTest/serverchathooks.cpp
deleted file mode 100644
index 985d3d1b..00000000
--- a/NorthstarDedicatedTest/serverchathooks.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-#include "pch.h"
-#include "serverchathooks.h"
-#include <rapidjson/document.h>
-#include <rapidjson/stringbuffer.h>
-#include <rapidjson/writer.h>
-#include "serverauthentication.h"
-#include "squirrel.h"
-#include "miscserverscript.h"
-
-class CServerGameDLL;
-class CBasePlayer;
-
-class CRecipientFilter
-{
- char unknown[58];
-};
-
-CServerGameDLL* g_pServerGameDLL;
-
-typedef void(__fastcall* CServerGameDLL__OnReceivedSayTextMessageType)(
- CServerGameDLL* self, unsigned int senderPlayerId, const char* text, int channelId);
-CServerGameDLL__OnReceivedSayTextMessageType CServerGameDLL__OnReceivedSayTextMessage;
-CServerGameDLL__OnReceivedSayTextMessageType CServerGameDLL__OnReceivedSayTextMessageHookBase;
-
-typedef CBasePlayer*(__fastcall* UTIL_PlayerByIndexType)(int playerIndex);
-UTIL_PlayerByIndexType UTIL_PlayerByIndex;
-
-typedef void(__fastcall* CRecipientFilter__ConstructType)(CRecipientFilter* self);
-CRecipientFilter__ConstructType CRecipientFilter__Construct;
-
-typedef void(__fastcall* CRecipientFilter__DestructType)(CRecipientFilter* self);
-CRecipientFilter__DestructType CRecipientFilter__Destruct;
-
-typedef void(__fastcall* CRecipientFilter__AddAllPlayersType)(CRecipientFilter* self);
-CRecipientFilter__AddAllPlayersType CRecipientFilter__AddAllPlayers;
-
-typedef void(__fastcall* CRecipientFilter__AddRecipientType)(CRecipientFilter* self, const CBasePlayer* player);
-CRecipientFilter__AddRecipientType CRecipientFilter__AddRecipient;
-
-typedef void(__fastcall* CRecipientFilter__MakeReliableType)(CRecipientFilter* self);
-CRecipientFilter__MakeReliableType CRecipientFilter__MakeReliable;
-
-typedef void(__fastcall* UserMessageBeginType)(CRecipientFilter* filter, const char* messagename);
-UserMessageBeginType UserMessageBegin;
-
-typedef void(__fastcall* MessageEndType)();
-MessageEndType MessageEnd;
-
-typedef void(__fastcall* MessageWriteByteType)(int iValue);
-MessageWriteByteType MessageWriteByte;
-
-typedef void(__fastcall* MessageWriteStringType)(const char* sz);
-MessageWriteStringType MessageWriteString;
-
-typedef void(__fastcall* MessageWriteBoolType)(bool bValue);
-MessageWriteBoolType MessageWriteBool;
-
-bool isSkippingHook = false;
-
-static void CServerGameDLL__OnReceivedSayTextMessageHook(CServerGameDLL* self, unsigned int senderPlayerId, const char* text, bool isTeam)
-{
- // MiniHook doesn't allow calling the base function outside of anywhere but the hook function.
- // To allow bypassing the hook, isSkippingHook can be set.
- if (isSkippingHook)
- {
- isSkippingHook = false;
- CServerGameDLL__OnReceivedSayTextMessageHookBase(self, senderPlayerId, text, isTeam);
- return;
- }
-
- void* sender = GetPlayerByIndex(senderPlayerId - 1);
-
- // check chat ratelimits
- if (!g_ServerAuthenticationManager->CheckPlayerChatRatelimit(sender))
- {
- return;
- }
-
- if (g_ServerSquirrelManager->setupfunc("CServerGameDLL_ProcessMessageStartThread") != SQRESULT_ERROR)
- {
- g_ServerSquirrelManager->pusharg((int)senderPlayerId - 1);
- g_ServerSquirrelManager->pusharg(text);
- g_ServerSquirrelManager->pusharg(isTeam);
- g_ServerSquirrelManager->call(3);
- }
- else
- CServerGameDLL__OnReceivedSayTextMessageHookBase(self, senderPlayerId, text, isTeam);
-}
-
-void ChatSendMessage(unsigned int playerIndex, const char* text, bool isteam)
-{
- isSkippingHook = true;
- CServerGameDLL__OnReceivedSayTextMessage(
- g_pServerGameDLL,
- // Ensure the first bit isn't set, since this indicates a custom message
- (playerIndex + 1) & CUSTOM_MESSAGE_INDEX_MASK,
- text,
- isteam);
-}
-
-void ChatBroadcastMessage(int fromPlayerIndex, int toPlayerIndex, const char* text, bool isTeam, bool isDead, CustomMessageType messageType)
-{
- CBasePlayer* toPlayer = NULL;
- if (toPlayerIndex >= 0)
- {
- toPlayer = UTIL_PlayerByIndex(toPlayerIndex + 1);
- if (toPlayer == NULL)
- return;
- }
-
- // Build a new string where the first byte is the message type
- char sendText[256];
- sendText[0] = (char)messageType;
- strncpy(sendText + 1, text, 255);
- sendText[255] = 0;
-
- // Anonymous custom messages use playerId=0, non-anonymous ones use a player ID with the first bit set
- unsigned int fromPlayerId = fromPlayerIndex < 0 ? 0 : ((fromPlayerIndex + 1) | CUSTOM_MESSAGE_INDEX_BIT);
-
- CRecipientFilter filter;
- CRecipientFilter__Construct(&filter);
- if (toPlayer == NULL)
- {
- CRecipientFilter__AddAllPlayers(&filter);
- }
- else
- {
- CRecipientFilter__AddRecipient(&filter, toPlayer);
- }
- CRecipientFilter__MakeReliable(&filter);
-
- UserMessageBegin(&filter, "SayText");
- MessageWriteByte(fromPlayerId);
- MessageWriteString(sendText);
- MessageWriteBool(isTeam);
- MessageWriteBool(isDead);
- MessageEnd();
-
- CRecipientFilter__Destruct(&filter);
-}
-
-SQRESULT SQ_SendMessage(void* sqvm)
-{
- int playerIndex = ServerSq_getinteger(sqvm, 1);
- const char* text = ServerSq_getstring(sqvm, 2);
- bool isTeam = ServerSq_getbool(sqvm, 3);
-
- ChatSendMessage(playerIndex, text, isTeam);
-
- return SQRESULT_NULL;
-}
-
-SQRESULT SQ_BroadcastMessage(void* sqvm)
-{
- int fromPlayerIndex = ServerSq_getinteger(sqvm, 1);
- int toPlayerIndex = ServerSq_getinteger(sqvm, 2);
- const char* text = ServerSq_getstring(sqvm, 3);
- bool isTeam = ServerSq_getbool(sqvm, 4);
- bool isDead = ServerSq_getbool(sqvm, 5);
- int messageType = ServerSq_getinteger(sqvm, 6);
-
- if (messageType < 1)
- {
- ServerSq_pusherror(sqvm, fmt::format("Invalid message type {}", messageType).c_str());
- return SQRESULT_ERROR;
- }
-
- ChatBroadcastMessage(fromPlayerIndex, toPlayerIndex, text, isTeam, isDead, (CustomMessageType)messageType);
-
- return SQRESULT_NULL;
-}
-
-void InitialiseServerChatHooks_Engine(HMODULE baseAddress)
-{
- g_pServerGameDLL = (CServerGameDLL*)((char*)baseAddress + 0x13F0AA98);
-}
-
-void InitialiseServerChatHooks_Server(HMODULE baseAddress)
-{
- CServerGameDLL__OnReceivedSayTextMessage = (CServerGameDLL__OnReceivedSayTextMessageType)((char*)baseAddress + 0x1595C0);
- UTIL_PlayerByIndex = (UTIL_PlayerByIndexType)((char*)baseAddress + 0x26AA10);
- CRecipientFilter__Construct = (CRecipientFilter__ConstructType)((char*)baseAddress + 0x1E9440);
- CRecipientFilter__Destruct = (CRecipientFilter__DestructType)((char*)baseAddress + 0x1E9700);
- CRecipientFilter__AddAllPlayers = (CRecipientFilter__AddAllPlayersType)((char*)baseAddress + 0x1E9940);
- CRecipientFilter__AddRecipient = (CRecipientFilter__AddRecipientType)((char*)baseAddress + 0x1E9b30);
- CRecipientFilter__MakeReliable = (CRecipientFilter__MakeReliableType)((char*)baseAddress + 0x1EA4E0);
-
- UserMessageBegin = (UserMessageBeginType)((char*)baseAddress + 0x15C520);
- MessageEnd = (MessageEndType)((char*)baseAddress + 0x158880);
- MessageWriteByte = (MessageWriteByteType)((char*)baseAddress + 0x158A90);
- MessageWriteString = (MessageWriteStringType)((char*)baseAddress + 0x158D00);
- MessageWriteBool = (MessageWriteBoolType)((char*)baseAddress + 0x158A00);
-
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook,
- CServerGameDLL__OnReceivedSayTextMessage,
- &CServerGameDLL__OnReceivedSayTextMessageHook,
- reinterpret_cast<LPVOID*>(&CServerGameDLL__OnReceivedSayTextMessageHookBase));
-
- // Chat sending functions
- g_ServerSquirrelManager->AddFuncRegistration("void", "NSSendMessage", "int playerIndex, string text, bool isTeam", "", SQ_SendMessage);
- g_ServerSquirrelManager->AddFuncRegistration(
- "void",
- "NSBroadcastMessage",
- "int fromPlayerIndex, int toPlayerIndex, string text, bool isTeam, bool isDead, int messageType",
- "",
- SQ_BroadcastMessage);
-}
diff --git a/NorthstarDedicatedTest/sigscanning.cpp b/NorthstarDedicatedTest/sigscanning.cpp
deleted file mode 100644
index 761f9f08..00000000
--- a/NorthstarDedicatedTest/sigscanning.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include "pch.h"
-#include "sigscanning.h"
-#include <map>
-
-// note: sigscanning is only really intended to be used for resolving stuff like shared function definitions
-// we mostly use raw function addresses for stuff
-
-size_t GetModuleLength(HMODULE moduleHandle)
-{
- // based on sigscn code from ttf2sdk, which is in turn based on CSigScan from https://wiki.alliedmods.net/Signature_Scanning
- MEMORY_BASIC_INFORMATION mem;
- VirtualQuery(moduleHandle, &mem, sizeof(mem));
-
- IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)mem.AllocationBase;
- IMAGE_NT_HEADERS* pe = (IMAGE_NT_HEADERS*)((unsigned char*)dos + dos->e_lfanew);
-
- return pe->OptionalHeader.SizeOfImage;
-}
-
-void* FindSignature(std::string dllName, const char* sig, const char* mask)
-{
- HMODULE module = GetModuleHandleA(dllName.c_str());
-
- unsigned char* dllAddress = (unsigned char*)module;
- unsigned char* dllEnd = dllAddress + GetModuleLength(module);
-
- size_t sigLength = strlen(mask);
-
- for (auto i = dllAddress; i < dllEnd - sigLength + 1; i++)
- {
- int j = 0;
- for (; j < sigLength; j++)
- if (mask[j] != '?' && sig[j] != i[j])
- break;
-
- if (j == sigLength) // loop finished of its own accord
- return i;
- }
-
- return nullptr;
-}
diff --git a/NorthstarDedicatedTest/sigscanning.h b/NorthstarDedicatedTest/sigscanning.h
deleted file mode 100644
index 56979fbc..00000000
--- a/NorthstarDedicatedTest/sigscanning.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#pragma once
-#include <string>
-
-// note: sigscanning is only really intended to be used for resolving stuff like shared function definitions
-// we mostly use raw function addresses for stuff
-
-void* FindSignature(std::string dllName, const char* sig, const char* mask); \ No newline at end of file
diff --git a/NorthstarDedicatedTest/sourceconsole.cpp b/NorthstarDedicatedTest/sourceconsole.cpp
deleted file mode 100644
index a6d54989..00000000
--- a/NorthstarDedicatedTest/sourceconsole.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "pch.h"
-#include "convar.h"
-#include "sourceconsole.h"
-#include "sourceinterface.h"
-#include "concommand.h"
-#include "hookutils.h"
-
-SourceInterface<CGameConsole>* g_SourceGameConsole;
-
-void ConCommand_toggleconsole(const CCommand& arg)
-{
- if ((*g_SourceGameConsole)->IsConsoleVisible())
- (*g_SourceGameConsole)->Hide();
- else
- (*g_SourceGameConsole)->Activate();
-}
-
-typedef void (*OnCommandSubmittedType)(CConsoleDialog* consoleDialog, const char* pCommand);
-OnCommandSubmittedType onCommandSubmittedOriginal;
-void OnCommandSubmittedHook(CConsoleDialog* consoleDialog, const char* pCommand)
-{
- consoleDialog->m_pConsolePanel->Print("] ");
- consoleDialog->m_pConsolePanel->Print(pCommand);
- consoleDialog->m_pConsolePanel->Print("\n");
-
- // todo: call the help command in the future
-
- onCommandSubmittedOriginal(consoleDialog, pCommand);
-}
-
-// called from sourceinterface.cpp in client createinterface hooks, on GameClientExports001
-void InitialiseConsoleOnInterfaceCreation()
-{
- (*g_SourceGameConsole)->Initialize();
-
- auto consoleLogger = std::make_shared<SourceConsoleSink>();
- consoleLogger->set_pattern("[%l] %v");
-
- spdlog::default_logger()->sinks().push_back(consoleLogger);
-
- // hook OnCommandSubmitted so we print inputted commands
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook,
- (void*)((*g_SourceGameConsole)->m_pConsole->m_vtable->OnCommandSubmitted),
- &OnCommandSubmittedHook,
- reinterpret_cast<LPVOID*>(&onCommandSubmittedOriginal));
-}
-
-void InitialiseSourceConsole(HMODULE baseAddress)
-{
- g_SourceGameConsole = new SourceInterface<CGameConsole>("client.dll", "GameConsole004");
- RegisterConCommand("toggleconsole", ConCommand_toggleconsole, "toggles the console", FCVAR_DONTRECORD);
-}
-
-// logging stuff
-
-SourceConsoleSink::SourceConsoleSink()
-{
- logColours.emplace(spdlog::level::trace, SourceColor(0, 255, 255, 255));
- logColours.emplace(spdlog::level::debug, SourceColor(0, 255, 255, 255));
- logColours.emplace(spdlog::level::info, SourceColor(255, 255, 255, 255));
- logColours.emplace(spdlog::level::warn, SourceColor(255, 255, 0, 255));
- logColours.emplace(spdlog::level::err, SourceColor(255, 0, 0, 255));
- logColours.emplace(spdlog::level::critical, SourceColor(255, 0, 0, 255));
- logColours.emplace(spdlog::level::off, SourceColor(0, 0, 0, 0));
-}
-
-void SourceConsoleSink::sink_it_(const spdlog::details::log_msg& msg)
-{
- if (!(*g_SourceGameConsole)->m_bInitialized)
- return;
-
- spdlog::memory_buf_t formatted;
- spdlog::sinks::base_sink<std::mutex>::formatter_->format(msg, formatted);
- (*g_SourceGameConsole)
- ->m_pConsole->m_pConsolePanel->ColorPrint(logColours[msg.level], fmt::to_string(formatted).c_str()); // todo needs colour support
-}
-
-void SourceConsoleSink::flush_() {} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/sourceinterface.cpp b/NorthstarDedicatedTest/sourceinterface.cpp
deleted file mode 100644
index 2cc4733d..00000000
--- a/NorthstarDedicatedTest/sourceinterface.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "pch.h"
-#include "sourceinterface.h"
-#include "hooks.h"
-#include "hookutils.h"
-
-#include "sourceconsole.h"
-#include "context.h"
-#include "convar.h"
-#include <iostream>
-
-// really wanted to do a modular callback system here but honestly couldn't be bothered so hardcoding stuff for now: todo later
-
-CreateInterfaceFn clientCreateInterfaceOriginal;
-void* ClientCreateInterfaceHook(const char* pName, int* pReturnCode)
-{
- void* ret = clientCreateInterfaceOriginal(pName, pReturnCode);
-
- spdlog::info("CreateInterface CLIENT {}", pName);
- if (!strcmp(pName, "GameClientExports001"))
- InitialiseConsoleOnInterfaceCreation();
-
- return ret;
-}
-
-CreateInterfaceFn serverCreateInterfaceOriginal;
-void* ServerCreateInterfaceHook(const char* pName, int* pReturnCode)
-{
- void* ret = serverCreateInterfaceOriginal(pName, pReturnCode);
-
- std::cout << "CreateInterface SERVER " << pName << std::endl;
-
- return ret;
-}
-
-CreateInterfaceFn engineCreateInterfaceOriginal;
-void* EngineCreateInterfaceHook(const char* pName, int* pReturnCode)
-{
- void* ret = engineCreateInterfaceOriginal(pName, pReturnCode);
-
- std::cout << "CreateInterface ENGINE " << pName << std::endl;
-
- return ret;
-}
-
-void HookClientCreateInterface(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook,
- GetProcAddress(baseAddress, "CreateInterface"),
- &ClientCreateInterfaceHook,
- reinterpret_cast<LPVOID*>(&clientCreateInterfaceOriginal));
-}
-
-void HookServerCreateInterface(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook,
- GetProcAddress(baseAddress, "CreateInterface"),
- &ServerCreateInterfaceHook,
- reinterpret_cast<LPVOID*>(&serverCreateInterfaceOriginal));
-}
-
-void HookEngineCreateInterface(HMODULE baseAddress)
-{
- HookEnabler hook;
- ENABLER_CREATEHOOK(
- hook,
- GetProcAddress(baseAddress, "CreateInterface"),
- &EngineCreateInterfaceHook,
- reinterpret_cast<LPVOID*>(&engineCreateInterfaceOriginal));
-}
-
-void InitialiseInterfaceCreationHooks()
-{
- AddDllLoadCallback("client.dll", HookClientCreateInterface);
-
- // not used atm
- // AddDllLoadCallback("server.dll", HookServerCreateInterface);
- // AddDllLoadCallback("engine.dll", HookEngineCreateInterface);
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp
deleted file mode 100644
index 84caa389..00000000
--- a/NorthstarDedicatedTest/squirrel.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-#include "pch.h"
-#include "squirrel.h"
-#include "hooks.h"
-#include "hookutils.h"
-#include "sigscanning.h"
-#include "concommand.h"
-#include "modmanager.h"
-#include <iostream>
-
-// hook forward declarations
-typedef SQInteger (*SQPrintType)(void* sqvm, char* fmt, ...);
-SQPrintType ClientSQPrint;
-SQPrintType UISQPrint;
-SQPrintType ServerSQPrint;
-template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...);
-
-typedef void* (*CreateNewVMType)(void* a1, ScriptContext contextArg);
-CreateNewVMType ClientCreateNewVM; // only need a client one since ui doesn't have its own func for this
-CreateNewVMType ServerCreateNewVM;
-template <ScriptContext context> void* CreateNewVMHook(void* a1, ScriptContext contextArg);
-
-typedef void (*DestroyVMType)(void* a1, void* sqvm);
-DestroyVMType ClientDestroyVM; // only need a client one since ui doesn't have its own func for this
-DestroyVMType ServerDestroyVM;
-template <ScriptContext context> void DestroyVMHook(void* a1, void* sqvm);
-
-typedef void (*ScriptCompileError)(void* sqvm, const char* error, const char* file, int line, int column);
-ScriptCompileError ClientSQCompileError; // only need a client one since ui doesn't have its own func for this
-ScriptCompileError ServerSQCompileError;
-template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const char* error, const char* file, int line, int column);
-
-typedef char (*CallScriptInitCallbackType)(void* sqvm, const char* callback);
-CallScriptInitCallbackType ClientCallScriptInitCallback;
-CallScriptInitCallbackType ServerCallScriptInitCallback;
-template <ScriptContext context> char CallScriptInitCallbackHook(void* sqvm, const char* callback);
-
-// core sqvm funcs
-sq_compilebufferType ClientSq_compilebuffer;
-sq_compilebufferType ServerSq_compilebuffer;
-
-sq_pushroottableType ClientSq_pushroottable;
-sq_pushroottableType ServerSq_pushroottable;
-
-sq_callType ClientSq_call;
-sq_callType ServerSq_call;
-
-RegisterSquirrelFuncType ClientRegisterSquirrelFunc;
-RegisterSquirrelFuncType ServerRegisterSquirrelFunc;
-
-// sq stack array funcs
-sq_newarrayType ClientSq_newarray;
-sq_newarrayType ServerSq_newarray;
-
-sq_arrayappendType ClientSq_arrayappend;
-sq_arrayappendType ServerSq_arrayappend;
-
-// sq stack push funcs
-sq_pushstringType ClientSq_pushstring;
-sq_pushstringType ServerSq_pushstring;
-
-sq_pushintegerType ClientSq_pushinteger;
-sq_pushintegerType ServerSq_pushinteger;
-
-sq_pushfloatType ClientSq_pushfloat;
-sq_pushfloatType ServerSq_pushfloat;
-
-sq_pushboolType ClientSq_pushbool;
-sq_pushboolType ServerSq_pushbool;
-
-sq_pusherrorType ClientSq_pusherror;
-sq_pusherrorType ServerSq_pusherror;
-
-// sq stack get funcs
-sq_getstringType ClientSq_getstring;
-sq_getstringType ServerSq_getstring;
-
-sq_getintegerType ClientSq_getinteger;
-sq_getintegerType ServerSq_getinteger;
-
-sq_getfloatType ClientSq_getfloat;
-sq_getfloatType ServerSq_getfloat;
-
-sq_getboolType ClientSq_getbool;
-sq_getboolType ServerSq_getbool;
-
-sq_getType ClientSq_sq_get;
-sq_getType ServerSq_sq_get;
-
-template <ScriptContext context> void ExecuteCodeCommand(const CCommand& args);
-
-// inits
-SquirrelManager<ScriptContext::CLIENT>* g_ClientSquirrelManager;
-SquirrelManager<ScriptContext::SERVER>* g_ServerSquirrelManager;
-SquirrelManager<ScriptContext::UI>* g_UISquirrelManager;
-
-SQInteger NSTestFunc(void* sqvm)
-{
- return 1;
-}
-
-void InitialiseClientSquirrel(HMODULE baseAddress)
-{
- HookEnabler hook;
-
- // client inits
- g_ClientSquirrelManager = new SquirrelManager<ScriptContext::CLIENT>();
-
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x12B00,
- &SQPrintHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientSQPrint)); // client print function
- RegisterConCommand(
- "script_client", ExecuteCodeCommand<ScriptContext::CLIENT>, "Executes script code on the client vm", FCVAR_CLIENTDLL);
-
- // ui inits
- g_UISquirrelManager = new SquirrelManager<ScriptContext::UI>();
-
- ENABLER_CREATEHOOK(
- hook, (char*)baseAddress + 0x12BA0, &SQPrintHook<ScriptContext::UI>, reinterpret_cast<LPVOID*>(&UISQPrint)); // ui print function
- RegisterConCommand("script_ui", ExecuteCodeCommand<ScriptContext::UI>, "Executes script code on the ui vm", FCVAR_CLIENTDLL);
-
- // inits for both client and ui, since they share some functions
- ClientSq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
- ClientSq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5860);
- ClientSq_call = (sq_callType)((char*)baseAddress + 0x8650);
- ClientRegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x108E0);
-
- ClientSq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
- ClientSq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
-
- ClientSq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
- ClientSq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
- ClientSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
- ClientSq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
- ClientSq_pusherror = (sq_pusherrorType)((char*)baseAddress + 0x8470);
-
- ClientSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0);
- ClientSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0);
- ClientSq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x6100);
- ClientSq_getbool = (sq_getboolType)((char*)baseAddress + 0x6130);
-
- ClientSq_sq_get = (sq_getType)((char*)baseAddress + 0x7C30);
-
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x26130,
- &CreateNewVMHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientCreateNewVM)); // client createnewvm function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x26E70,
- &DestroyVMHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientDestroyVM)); // client destroyvm function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x79A50,
- &ScriptCompileErrorHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientSQCompileError)); // client compileerror function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x10190,
- &CallScriptInitCallbackHook<ScriptContext::CLIENT>,
- reinterpret_cast<LPVOID*>(&ClientCallScriptInitCallback)); // client callscriptinitcallback function
-}
-
-void InitialiseServerSquirrel(HMODULE baseAddress)
-{
- g_ServerSquirrelManager = new SquirrelManager<ScriptContext::SERVER>();
-
- HookEnabler hook;
-
- ServerSq_compilebuffer = (sq_compilebufferType)((char*)baseAddress + 0x3110);
- ServerSq_pushroottable = (sq_pushroottableType)((char*)baseAddress + 0x5840);
- ServerSq_call = (sq_callType)((char*)baseAddress + 0x8620);
- ServerRegisterSquirrelFunc = (RegisterSquirrelFuncType)((char*)baseAddress + 0x1DD10);
-
- ServerSq_newarray = (sq_newarrayType)((char*)baseAddress + 0x39F0);
- ServerSq_arrayappend = (sq_arrayappendType)((char*)baseAddress + 0x3C70);
-
- ServerSq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440);
- ServerSq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0);
- ServerSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800);
- ServerSq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710);
- ServerSq_pusherror = (sq_pusherrorType)((char*)baseAddress + 0x8440);
-
- ServerSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60A0);
- ServerSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60C0);
- ServerSq_getfloat = (sq_getfloatType)((char*)baseAddress + 0x60E0);
- ServerSq_getbool = (sq_getboolType)((char*)baseAddress + 0x6110);
-
- ServerSq_sq_get = (sq_getType)((char*)baseAddress + 0x7C00);
-
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x1FE90,
- &SQPrintHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerSQPrint)); // server print function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x260E0,
- &CreateNewVMHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerCreateNewVM)); // server createnewvm function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x26E20,
- &DestroyVMHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerDestroyVM)); // server destroyvm function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x799E0,
- &ScriptCompileErrorHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerSQCompileError)); // server compileerror function
- ENABLER_CREATEHOOK(
- hook,
- (char*)baseAddress + 0x1D5C0,
- &CallScriptInitCallbackHook<ScriptContext::SERVER>,
- reinterpret_cast<LPVOID*>(&ServerCallScriptInitCallback)); // server callscriptinitcallback function
-
- // cheat and clientcmd_can_execute allows clients to execute this, but since it's unsafe we only allow it when cheats are enabled
- // for script_client and script_ui, we don't use cheats, so clients can execute them on themselves all they want
- RegisterConCommand(
- "script",
- ExecuteCodeCommand<ScriptContext::SERVER>,
- "Executes script code on the server vm",
- FCVAR_GAMEDLL | FCVAR_CLIENTCMD_CAN_EXECUTE | FCVAR_CHEAT);
-}
-
-// hooks
-template <ScriptContext context> SQInteger SQPrintHook(void* sqvm, char* fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
-
- SQChar buf[1024];
- int charsWritten = vsnprintf_s(buf, _TRUNCATE, fmt, va);
-
- if (charsWritten > 0)
- {
- if (buf[charsWritten - 1] == '\n')
- buf[charsWritten - 1] = '\0';
-
- spdlog::info("[{} SCRIPT] {}", GetContextName(context), buf);
- }
-
- va_end(va);
- return 0;
-}
-
-template <ScriptContext context> void* CreateNewVMHook(void* a1, ScriptContext realContext)
-{
- void* sqvm;
-
- if (context == ScriptContext::CLIENT)
- {
- sqvm = ClientCreateNewVM(a1, realContext);
-
- if (realContext == ScriptContext::UI)
- g_UISquirrelManager->VMCreated(sqvm);
- else
- g_ClientSquirrelManager->VMCreated(sqvm);
- }
- else if (context == ScriptContext::SERVER)
- {
- sqvm = ServerCreateNewVM(a1, context);
- g_ServerSquirrelManager->VMCreated(sqvm);
- }
-
- spdlog::info("CreateNewVM {} {}", GetContextName(realContext), sqvm);
- return sqvm;
-}
-
-template <ScriptContext context> void DestroyVMHook(void* a1, void* sqvm)
-{
- ScriptContext realContext = context; // ui and client use the same function so we use this for prints
-
- if (context == ScriptContext::CLIENT)
- {
- if (g_ClientSquirrelManager->sqvm == sqvm)
- g_ClientSquirrelManager->VMDestroyed();
- else if (g_UISquirrelManager->sqvm == sqvm)
- {
- g_UISquirrelManager->VMDestroyed();
- realContext = ScriptContext::UI;
- }
-
- ClientDestroyVM(a1, sqvm);
- }
- else if (context == ScriptContext::SERVER)
- {
- g_ServerSquirrelManager->VMDestroyed();
- ServerDestroyVM(a1, sqvm);
- }
-
- spdlog::info("DestroyVM {} {}", GetContextName(realContext), sqvm);
-}
-
-template <ScriptContext context> void ScriptCompileErrorHook(void* sqvm, const char* error, const char* file, int line, int column)
-{
- ScriptContext realContext = context; // ui and client use the same function so we use this for prints
- if (context == ScriptContext::CLIENT && sqvm == g_UISquirrelManager->sqvm)
- realContext = ScriptContext::UI;
-
- spdlog::error("{} SCRIPT COMPILE ERROR {}", GetContextName(realContext), error);
- spdlog::error("{} line [{}] column [{}]", file, line, column);
-
- // dont call the original since it kills game
- // in the future it'd be nice to do an actual error with UICodeCallback_ErrorDialog here, but only if we're compiling level scripts
- // compilestring and stuff shouldn't tho
- // though, that also has potential to be REALLY bad if we're compiling ui scripts lol
-}
-
-template <ScriptContext context> char CallScriptInitCallbackHook(void* sqvm, const char* callback)
-{
- char ret;
-
- if (context == ScriptContext::CLIENT)
- {
- ScriptContext realContext = context; // ui and client use the same function so we use this for prints
- bool shouldCallCustomCallbacks = false;
-
- // since we don't hook arbitrary callbacks yet, make sure we're only doing callbacks on inits
- if (!strcmp(callback, "UICodeCallback_UIInit"))
- {
- realContext = ScriptContext::UI;
- shouldCallCustomCallbacks = true;
- }
- else if (!strcmp(callback, "ClientCodeCallback_MapSpawn"))
- shouldCallCustomCallbacks = true;
-
- // run before callbacks
- // todo: we need to verify if RunOn is valid for current state before calling callbacks
- if (shouldCallCustomCallbacks)
- {
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- for (ModScript script : mod.Scripts)
- {
- for (ModScriptCallback modCallback : script.Callbacks)
- {
- if (modCallback.Context == realContext && modCallback.BeforeCallback.length())
- {
- spdlog::info(
- "Running custom {} script callback \"{}\"", GetContextName(realContext), modCallback.BeforeCallback);
- ClientCallScriptInitCallback(sqvm, modCallback.BeforeCallback.c_str());
- }
- }
- }
- }
- }
-
- spdlog::info("{} CodeCallback {} called", GetContextName(realContext), callback);
- if (!shouldCallCustomCallbacks)
- spdlog::info("Not executing custom callbacks for CodeCallback {}", callback);
- ret = ClientCallScriptInitCallback(sqvm, callback);
-
- // run after callbacks
- if (shouldCallCustomCallbacks)
- {
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- for (ModScript script : mod.Scripts)
- {
- for (ModScriptCallback modCallback : script.Callbacks)
- {
- if (modCallback.Context == realContext && modCallback.AfterCallback.length())
- {
- spdlog::info(
- "Running custom {} script callback \"{}\"", GetContextName(realContext), modCallback.AfterCallback);
- ClientCallScriptInitCallback(sqvm, modCallback.AfterCallback.c_str());
- }
- }
- }
- }
- }
- }
- else if (context == ScriptContext::SERVER)
- {
- // since we don't hook arbitrary callbacks yet, make sure we're only doing callbacks on inits
- bool shouldCallCustomCallbacks = !strcmp(callback, "CodeCallback_MapSpawn");
-
- // run before callbacks
- // todo: we need to verify if RunOn is valid for current state before calling callbacks
- if (shouldCallCustomCallbacks)
- {
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- for (ModScript script : mod.Scripts)
- {
- for (ModScriptCallback modCallback : script.Callbacks)
- {
- if (modCallback.Context == ScriptContext::SERVER && modCallback.BeforeCallback.length())
- {
- spdlog::info("Running custom {} script callback \"{}\"", GetContextName(context), modCallback.BeforeCallback);
- ServerCallScriptInitCallback(sqvm, modCallback.BeforeCallback.c_str());
- }
- }
- }
- }
- }
-
- spdlog::info("{} CodeCallback {} called", GetContextName(context), callback);
- if (!shouldCallCustomCallbacks)
- spdlog::info("Not executing custom callbacks for CodeCallback {}", callback);
- ret = ServerCallScriptInitCallback(sqvm, callback);
-
- // run after callbacks
- if (shouldCallCustomCallbacks)
- {
- for (Mod mod : g_ModManager->m_loadedMods)
- {
- if (!mod.Enabled)
- continue;
-
- for (ModScript script : mod.Scripts)
- {
- for (ModScriptCallback modCallback : script.Callbacks)
- {
- if (modCallback.Context == ScriptContext::SERVER && modCallback.AfterCallback.length())
- {
- spdlog::info("Running custom {} script callback \"{}\"", GetContextName(context), modCallback.AfterCallback);
- ServerCallScriptInitCallback(sqvm, modCallback.AfterCallback.c_str());
- }
- }
- }
- }
- }
- }
-
- return ret;
-}
-
-template <ScriptContext context> void ExecuteCodeCommand(const CCommand& args)
-{
- if (context == ScriptContext::CLIENT)
- g_ClientSquirrelManager->ExecuteCode(args.ArgS());
- else if (context == ScriptContext::UI)
- g_UISquirrelManager->ExecuteCode(args.ArgS());
- else if (context == ScriptContext::SERVER)
- g_ServerSquirrelManager->ExecuteCode(args.ArgS());
-} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/squirrel.h b/NorthstarDedicatedTest/squirrel.h
deleted file mode 100644
index cc39cc2a..00000000
--- a/NorthstarDedicatedTest/squirrel.h
+++ /dev/null
@@ -1,294 +0,0 @@
-#pragma once
-
-void InitialiseClientSquirrel(HMODULE baseAddress);
-void InitialiseServerSquirrel(HMODULE baseAddress);
-
-// stolen from ttf2sdk: sqvm types
-typedef float SQFloat;
-typedef long SQInteger;
-typedef unsigned long SQUnsignedInteger;
-typedef char SQChar;
-
-typedef SQUnsignedInteger SQBool;
-typedef SQInteger SQRESULT;
-
-const SQRESULT SQRESULT_ERROR = -1;
-const SQRESULT SQRESULT_NULL = 0;
-const SQRESULT SQRESULT_NOTNULL = 1;
-
-typedef SQInteger (*SQFunction)(void* sqvm);
-
-struct CompileBufferState
-{
- const SQChar* buffer;
- const SQChar* bufferPlusLength;
- const SQChar* bufferAgain;
-
- CompileBufferState(const std::string& code)
- {
- buffer = code.c_str();
- bufferPlusLength = code.c_str() + code.size();
- bufferAgain = code.c_str();
- }
-};
-
-struct SQFuncRegistration
-{
- const char* squirrelFuncName;
- const char* cppFuncName;
- const char* helpText;
- const char* returnValueType;
- const char* argTypes;
- int16_t somethingThatsZero;
- int16_t padding1;
- int32_t unknown1;
- int64_t unknown2;
- int32_t unknown3;
- int32_t padding2;
- int64_t unknown4;
- int64_t unknown5;
- int64_t unknown6;
- int32_t unknown7;
- int32_t padding3;
- void* funcPtr;
-
- SQFuncRegistration()
- {
- memset(this, 0, sizeof(SQFuncRegistration));
- this->padding2 = 32;
- }
-};
-
-// core sqvm funcs
-typedef SQRESULT (*sq_compilebufferType)(void* sqvm, CompileBufferState* compileBuffer, const char* file, int a1, ScriptContext a2);
-extern sq_compilebufferType ClientSq_compilebuffer;
-extern sq_compilebufferType ServerSq_compilebuffer;
-
-typedef void (*sq_pushroottableType)(void* sqvm);
-extern sq_pushroottableType ClientSq_pushroottable;
-extern sq_pushroottableType ServerSq_pushroottable;
-
-typedef SQRESULT (*sq_callType)(void* sqvm, SQInteger s1, SQBool a2, SQBool a3);
-extern sq_callType ClientSq_call;
-extern sq_callType ServerSq_call;
-
-typedef int64_t (*RegisterSquirrelFuncType)(void* sqvm, SQFuncRegistration* funcReg, char unknown);
-extern RegisterSquirrelFuncType ClientRegisterSquirrelFunc;
-extern RegisterSquirrelFuncType ServerRegisterSquirrelFunc;
-
-// sq stack array funcs
-typedef void (*sq_newarrayType)(void* sqvm, SQInteger stackpos);
-extern sq_newarrayType ClientSq_newarray;
-extern sq_newarrayType ServerSq_newarray;
-
-typedef SQRESULT (*sq_arrayappendType)(void* sqvm, SQInteger stackpos);
-extern sq_arrayappendType ClientSq_arrayappend;
-extern sq_arrayappendType ServerSq_arrayappend;
-
-// sq stack push funcs
-typedef void (*sq_pushstringType)(void* sqvm, const SQChar* str, SQInteger stackpos);
-extern sq_pushstringType ClientSq_pushstring;
-extern sq_pushstringType ServerSq_pushstring;
-
-// weird how these don't take a stackpos arg?
-typedef void (*sq_pushintegerType)(void* sqvm, SQInteger i);
-extern sq_pushintegerType ClientSq_pushinteger;
-extern sq_pushintegerType ServerSq_pushinteger;
-
-typedef void (*sq_pushfloatType)(void* sqvm, SQFloat f);
-extern sq_pushfloatType ClientSq_pushfloat;
-extern sq_pushfloatType ServerSq_pushfloat;
-
-typedef void (*sq_pushboolType)(void* sqvm, SQBool b);
-extern sq_pushboolType ClientSq_pushbool;
-extern sq_pushboolType ServerSq_pushbool;
-
-typedef SQInteger (*sq_pusherrorType)(void* sqvm, const SQChar* error);
-extern sq_pusherrorType ClientSq_pusherror;
-extern sq_pusherrorType ServerSq_pusherror;
-
-// sq stack get funcs
-typedef const SQChar* (*sq_getstringType)(void* sqvm, SQInteger stackpos);
-extern sq_getstringType ClientSq_getstring;
-extern sq_getstringType ServerSq_getstring;
-
-typedef SQInteger (*sq_getintegerType)(void* sqvm, SQInteger stackpos);
-extern sq_getintegerType ClientSq_getinteger;
-extern sq_getintegerType ServerSq_getinteger;
-
-typedef SQFloat (*sq_getfloatType)(void*, SQInteger stackpos);
-extern sq_getfloatType ClientSq_getfloat;
-extern sq_getfloatType ServerSq_getfloat;
-
-typedef SQBool (*sq_getboolType)(void*, SQInteger stackpos);
-extern sq_getboolType ClientSq_getbool;
-extern sq_getboolType ServerSq_getbool;
-
-typedef SQRESULT (*sq_getType)(void* sqvm, SQInteger idx);
-extern sq_getType ServerSq_sq_get;
-extern sq_getType ClientSq_sq_get;
-
-template <ScriptContext context> class SquirrelManager
-{
- private:
- std::vector<SQFuncRegistration*> m_funcRegistrations;
-
- public:
- void* sqvm;
- void* sqvm2;
-
- public:
- SquirrelManager() : sqvm(nullptr) {}
-
- void VMCreated(void* newSqvm)
- {
- sqvm = newSqvm;
- sqvm2 = *((void**)((char*)sqvm + 8)); // honestly not 100% sure on what this is, but alot of functions take it
-
- for (SQFuncRegistration* funcReg : m_funcRegistrations)
- {
- spdlog::info("Registering {} function {}", GetContextName(context), funcReg->squirrelFuncName);
-
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- ClientRegisterSquirrelFunc(sqvm, funcReg, 1);
- else
- ServerRegisterSquirrelFunc(sqvm, funcReg, 1);
- }
- }
-
- void VMDestroyed()
- {
- sqvm = nullptr;
- }
-
- void ExecuteCode(const char* code)
- {
- // ttf2sdk checks ThreadIsInMainThread here, might be good to do that? doesn't seem like an issue rn tho
-
- if (!sqvm)
- {
- spdlog::error("Cannot execute code, {} squirrel vm is not initialised", GetContextName(context));
- return;
- }
-
- spdlog::info("Executing {} script code {} ", GetContextName(context), code);
-
- std::string strCode(code);
- CompileBufferState bufferState = CompileBufferState(strCode);
-
- SQRESULT compileResult;
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- compileResult = ClientSq_compilebuffer(sqvm2, &bufferState, "console", -1, context);
- else if (context == ScriptContext::SERVER)
- compileResult = ServerSq_compilebuffer(sqvm2, &bufferState, "console", -1, context);
-
- spdlog::info("sq_compilebuffer returned {}", compileResult);
- if (compileResult >= 0)
- {
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- {
- ClientSq_pushroottable(sqvm2);
- SQRESULT callResult = ClientSq_call(sqvm2, 1, false, false);
- spdlog::info("sq_call returned {}", callResult);
- }
- else if (context == ScriptContext::SERVER)
- {
- ServerSq_pushroottable(sqvm2);
- SQRESULT callResult = ServerSq_call(sqvm2, 1, false, false);
- spdlog::info("sq_call returned {}", callResult);
- }
- }
- }
-
- int setupfunc(const char* funcname)
- {
- int result = -2;
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- {
- ClientSq_pushroottable(sqvm2);
- ClientSq_pushstring(sqvm2, funcname, -1);
- result = ClientSq_sq_get(sqvm2, -2);
- if (result != SQRESULT_ERROR)
- {
- ClientSq_pushroottable(sqvm2);
- }
- }
- else if (context == ScriptContext::SERVER)
- {
- ServerSq_pushroottable(sqvm2);
- ServerSq_pushstring(sqvm2, funcname, -1);
- result = ServerSq_sq_get(sqvm2, -2);
- if (result != SQRESULT_ERROR)
- {
- ServerSq_pushroottable(sqvm2);
- }
- }
- return result;
- }
-
- void pusharg(int arg)
- {
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- ClientSq_pushinteger(sqvm2, arg);
- else if (context == ScriptContext::SERVER)
- ServerSq_pushinteger(sqvm2, arg);
- }
- void pusharg(const char* arg)
- {
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- ClientSq_pushstring(sqvm2, arg, -1);
- else if (context == ScriptContext::SERVER)
- ServerSq_pushstring(sqvm2, arg, -1);
- }
- void pusharg(float arg)
- {
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- ClientSq_pushfloat(sqvm2, arg);
- else if (context == ScriptContext::SERVER)
- ServerSq_pushfloat(sqvm2, arg);
- }
- void pusharg(bool arg)
- {
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- ClientSq_pushbool(sqvm2, arg);
- else if (context == ScriptContext::SERVER)
- ServerSq_pushbool(sqvm2, arg);
- }
-
- int call(int args)
- {
- int result = -2;
- if (context == ScriptContext::CLIENT || context == ScriptContext::UI)
- result = ClientSq_call(sqvm2, args + 1, false, false);
- else if (context == ScriptContext::SERVER)
- result = ServerSq_call(sqvm2, args + 1, false, false);
-
- return result;
- }
-
- void AddFuncRegistration(std::string returnType, std::string name, std::string argTypes, std::string helpText, SQFunction func)
- {
- SQFuncRegistration* reg = new SQFuncRegistration;
-
- reg->squirrelFuncName = new char[name.size() + 1];
- strcpy((char*)reg->squirrelFuncName, name.c_str());
- reg->cppFuncName = reg->squirrelFuncName;
-
- reg->helpText = new char[helpText.size() + 1];
- strcpy((char*)reg->helpText, helpText.c_str());
-
- reg->returnValueType = new char[returnType.size() + 1];
- strcpy((char*)reg->returnValueType, returnType.c_str());
-
- reg->argTypes = new char[argTypes.size() + 1];
- strcpy((char*)reg->argTypes, argTypes.c_str());
-
- reg->funcPtr = func;
-
- m_funcRegistrations.push_back(reg);
- }
-};
-
-extern SquirrelManager<ScriptContext::CLIENT>* g_ClientSquirrelManager;
-extern SquirrelManager<ScriptContext::SERVER>* g_ServerSquirrelManager;
-extern SquirrelManager<ScriptContext::UI>* g_UISquirrelManager;
diff --git a/LauncherInjector/LauncherInjector.vcxproj b/NorthstarLauncher/NorthstarLauncher.vcxproj
index 8870c732..1c3ebe37 100644
--- a/LauncherInjector/LauncherInjector.vcxproj
+++ b/NorthstarLauncher/NorthstarLauncher.vcxproj
@@ -56,7 +56,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
- <LanguageStandard>stdcpp17</LanguageStandard>
+ <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/F8000000 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
@@ -65,6 +65,9 @@
<AdditionalDependencies>shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<StackReserveSize>8000000</StackReserveSize>
</Link>
+ <PostBuildEvent>
+ <Command>copy /Y "$(TargetPath)" "$(SolutionDir)..\..\"</Command>
+ </PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -74,7 +77,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
- <LanguageStandard>stdcpp17</LanguageStandard>
+ <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/F8000000 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
@@ -85,6 +88,9 @@
<AdditionalDependencies>shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<StackReserveSize>8000000</StackReserveSize>
</Link>
+ <PostBuildEvent>
+ <Command>copy /Y "$(TargetPath)" "$(SolutionDir)..\..\"</Command>
+ </PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
diff --git a/LauncherInjector/LauncherInjector.vcxproj.filters b/NorthstarLauncher/NorthstarLauncher.vcxproj.filters
index 87e25fa8..76b907bf 100644
--- a/LauncherInjector/LauncherInjector.vcxproj.filters
+++ b/NorthstarLauncher/NorthstarLauncher.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
@@ -34,4 +34,4 @@
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/LauncherInjector/main.cpp b/NorthstarLauncher/main.cpp
index 04aadf03..078cbc4a 100644
--- a/LauncherInjector/main.cpp
+++ b/NorthstarLauncher/main.cpp
@@ -1,12 +1,17 @@
#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#include <TlHelp32.h>
+#include <windows.h>
+#include <tlhelp32.h>
#include <filesystem>
#include <sstream>
#include <fstream>
-#include <Shlwapi.h>
+#include <shlwapi.h>
#include <iostream>
+#pragma comment(lib, "Ws2_32.lib")
+
+#include <winsock2.h>
+#include <WS2tcpip.h>
+
namespace fs = std::filesystem;
extern "C"
@@ -125,6 +130,41 @@ void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t*
MessageBoxA(GetForegroundWindow(), text, "Northstar Launcher Error", 0);
}
+void AwaitOriginStartup()
+{
+ WSADATA wsaData;
+ WSAStartup(MAKEWORD(2, 2), &wsaData);
+ SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if (sock != INVALID_SOCKET)
+ {
+ const int LSX_PORT = 3216;
+
+ sockaddr_in lsxAddr;
+ lsxAddr.sin_family = AF_INET;
+ inet_pton(AF_INET, "127.0.0.1", &(lsxAddr.sin_addr));
+ lsxAddr.sin_port = htons(LSX_PORT);
+
+ std::cout << "LSX: connect()" << std::endl;
+ connect(sock, (struct sockaddr*)&lsxAddr, sizeof(lsxAddr));
+
+ char buf[4096];
+ memset(buf, 0, sizeof(buf));
+
+ do
+ {
+ recv(sock, buf, 4096, 0);
+ std::cout << buf << std::endl;
+
+ // honestly really shit, this isn't needed for origin due to being able to check OriginClientService
+ // but for ea desktop we don't have anything like this, so atm we just have to wait to ensure that we start after logging in
+ Sleep(8000);
+ } while (!strstr(buf, "<LSX>")); // ensure we're actually getting data from lsx
+ }
+
+ WSACleanup(); // cleanup sockets and such so game can contact lsx itself
+}
+
void EnsureOriginStarted()
{
if (GetProcessByName(L"Origin.exe") || GetProcessByName(L"EADesktop.exe"))
@@ -147,7 +187,7 @@ void EnsureOriginStarted()
return;
}
- printf("[*] Starting Origin...\n");
+ std::cout << "[*] Starting Origin..." << std::endl;
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
@@ -168,11 +208,16 @@ void EnsureOriginStarted()
(LPSTARTUPINFOA)&si,
&pi);
- printf("[*] Waiting for Origin...\n");
+ std::cout << "[*] Waiting for Origin..." << std::endl;
+
+ // wait for origin process to boot
+ do
+ {
+ Sleep(500);
+ } while (!GetProcessByName(L"OriginClientService.exe") && !GetProcessByName(L"EADesktop.exe"));
- // wait for origin to be ready, this process is created when origin is ready enough to launch game without any errors
- while (!GetProcessByName(L"OriginClientService.exe") && !GetProcessByName(L"EADesktop.exe"))
- Sleep(200);
+ // wait for origin to be ready to start
+ AwaitOriginStartup();
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
@@ -225,7 +270,7 @@ bool ShouldLoadNorthstar(int argc, char* argv[])
std::stringstream runNorthstarFileBuffer;
runNorthstarFileBuffer << runNorthstarFile.rdbuf();
runNorthstarFile.close();
- if (runNorthstarFileBuffer.str()._Starts_with("0"))
+ if (runNorthstarFileBuffer.str().starts_with("0"))
loadNorthstar = false;
}
return loadNorthstar;
@@ -236,7 +281,7 @@ bool LoadNorthstar()
FARPROC Hook_Init = nullptr;
{
swprintf_s(buffer, L"%s\\Northstar.dll", exePath);
- hHookModule = LoadLibraryExW(buffer, 0i64, 8u);
+ hHookModule = LoadLibraryExW(buffer, 0, 8u);
if (hHookModule)
Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar");
if (!hHookModule || Hook_Init == nullptr)
@@ -253,7 +298,7 @@ bool LoadNorthstar()
LoadPlugins = GetProcAddress(hHookModule, "LoadPlugins");
if (!hHookModule || LoadPlugins == nullptr)
{
- printf("Failed to get function pointer to LoadPlugins of Northstar.dll\n");
+ std::cout << "Failed to get function pointer to LoadPlugins of Northstar.dll" << std::endl;
LibraryLoadError(GetLastError(), L"Northstar.dll", buffer);
return false;
}
@@ -266,7 +311,7 @@ bool LoadNorthstar()
HMODULE LoadDediStub(const char* name)
{
// this works because materialsystem_dx11.dll uses relative imports, and even a DLL loaded with an absolute path will take precedence
- printf("[*] Loading %s\n", name);
+ std::cout << "[*] Loading " << name << std::endl;
swprintf_s(buffer, L"%s\\bin\\x64_dedi\\%hs", exePath, name);
HMODULE h = LoadLibraryExW(buffer, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!h)
@@ -310,7 +355,7 @@ int main(int argc, char* argv[])
if (dedicated && !nostubs)
{
- printf("[*] Loading stubs\n");
+ std::cout << "[*] Loading stubs" << std::endl;
HMODULE gssao, gtxaa, d3d11;
if (!(gssao = GetModuleHandleA("GFSDK_SSAO.win64.dll")) && !(gtxaa = GetModuleHandleA("GFSDK_TXAA.win64.dll")) &&
!(d3d11 = GetModuleHandleA("d3d11.dll")))
@@ -320,8 +365,9 @@ int main(int argc, char* argv[])
{
if ((!gssao || FreeLibrary(gssao)) && (!gtxaa || FreeLibrary(gtxaa)) && (!d3d11 || FreeLibrary(d3d11)))
{
- printf("[*] WARNING: Failed to load d3d11/gfsdk stubs from bin/x64_dedi. "
- "The stubs have been unloaded and the original libraries will be used instead.\n");
+ std::cout << "[*] WARNING: Failed to load d3d11/gfsdk stubs from bin/x64_dedi. "
+ "The stubs have been unloaded and the original libraries will be used instead"
+ << std::endl;
}
else
{
@@ -339,8 +385,9 @@ int main(int argc, char* argv[])
else
{
// this should never happen
- printf("[*] WARNING: Failed to load stubs because conflicting modules are already loaded, so those will be used instead "
- "(did Northstar initialize too late?).\n");
+ std::cout << "[*] WARNING: Failed to load stubs because conflicting modules are already loaded, so those will be used instead "
+ "(did Northstar initialize too late?)."
+ << std::endl;
}
}
@@ -362,7 +409,7 @@ int main(int argc, char* argv[])
file.close();
}
- printf("[*] Loading tier0.dll\n");
+ std::cout << "[*] Loading tier0.dll" << std::endl;
swprintf_s(buffer, L"%s\\bin\\x64_retail\\tier0.dll", exePath);
hTier0Module = LoadLibraryExW(buffer, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!hTier0Module)
@@ -374,14 +421,14 @@ int main(int argc, char* argv[])
bool loadNorthstar = ShouldLoadNorthstar(argc, argv);
if (loadNorthstar)
{
- printf("[*] Loading Northstar\n");
+ std::cout << "[*] Loading Northstar" << std::endl;
if (!LoadNorthstar())
return 1;
}
else
- printf("[*] Going to load the vanilla game\n");
+ std::cout << "[*] Going to load the vanilla game" << std::endl;
- printf("[*] Loading launcher.dll\n");
+ std::cout << "[*] Loading launcher.dll" << std::endl;
swprintf_s(buffer, L"%s\\bin\\x64_retail\\launcher.dll", exePath);
hLauncherModule = LoadLibraryExW(buffer, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!hLauncherModule)
@@ -391,7 +438,7 @@ int main(int argc, char* argv[])
}
}
- printf("[*] Launching the game...\n");
+ std::cout << "[*] Launching the game..." << std::endl;
auto LauncherMain = GetLauncherMain();
if (!LauncherMain)
MessageBoxA(
@@ -399,9 +446,8 @@ int main(int argc, char* argv[])
"Failed loading launcher.dll.\nThe game cannot continue and has to exit.",
"Northstar Launcher Error",
0);
- // auto result = ((__int64(__fastcall*)())LauncherMain)();
- // auto result = ((signed __int64(__fastcall*)(__int64))LauncherMain)(0i64);
+ std::cout.flush();
return ((int(/*__fastcall*/*)(HINSTANCE, HINSTANCE, LPSTR, int))LauncherMain)(
NULL, NULL, NULL, 0); // the parameters aren't really used anyways
}
diff --git a/LauncherInjector/ns_icon.ico b/NorthstarLauncher/ns_icon.ico
index fc9ad166..fc9ad166 100644
--- a/LauncherInjector/ns_icon.ico
+++ b/NorthstarLauncher/ns_icon.ico
Binary files differ
diff --git a/LauncherInjector/resource1.h b/NorthstarLauncher/resource1.h
index bb584502..bb584502 100644
--- a/LauncherInjector/resource1.h
+++ b/NorthstarLauncher/resource1.h
diff --git a/LauncherInjector/resources.rc b/NorthstarLauncher/resources.rc
index de16250b..32038499 100644
--- a/LauncherInjector/resources.rc
+++ b/NorthstarLauncher/resources.rc
@@ -1,7 +1,7 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource1.h"
-#include "../NorthstarDedicatedTest/ns_version.h"
+#include "../NorthstarDLL/ns_version.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
diff --git a/R2Northstar.sln b/R2Northstar.sln
index 3dfdb218..b66b0dcd 100644
--- a/R2Northstar.sln
+++ b/R2Northstar.sln
@@ -1,11 +1,11 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Northstar", "NorthstarDedicatedTest\NorthstarDedicatedTest.vcxproj", "{CFAD2623-064F-453C-8196-79EE10292E32}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Northstar", "NorthstarDLL\NorthstarDLL.vcxproj", "{CFAD2623-064F-453C-8196-79EE10292E32}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NorthstarLauncher", "LauncherInjector\LauncherInjector.vcxproj", "{0EA82CB0-53FE-4D4C-96DF-47FA970513D0}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NorthstarLauncher", "NorthstarLauncher\NorthstarLauncher.vcxproj", "{0EA82CB0-53FE-4D4C-96DF-47FA970513D0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_launcher_proxy", "loader_launcher_proxy\loader_launcher_proxy.vcxproj", "{F65C322D-66DF-4AF1-B650-70221DE334C0}"
EndProject
diff --git a/README.md b/README.md
index 793dca8e..434231e6 100644
--- a/README.md
+++ b/README.md
@@ -9,4 +9,4 @@ Check [BUILD.md](https://github.com/R2Northstar/NorthstarLauncher/blob/main/BUIL
## Format
-This project uses [clang-format](https://clang.llvm.org/docs/ClangFormat.html), make sure you run `clang-format -i --style=file LauncherInjector/*.cpp LauncherInjector/*.h NorthstarDedicatedTest/*.cpp NorthstarDedicatedTest/*.h` when opening a Pull Request. Check the tool's website for instructions on how to integrate it with your IDE. \ No newline at end of file
+This project uses [clang-format](https://clang.llvm.org/docs/ClangFormat.html), make sure you run `clang-format -i --style=file NorthstarLauncher/*.cpp NorthstarLauncher/*.h NorthstarDLL/*.cpp NorthstarDLL/*.h` when opening a Pull Request. Check the tool's website for instructions on how to integrate it with your IDE.
diff --git a/loader_launcher_proxy/Memory.cpp b/loader_launcher_proxy/Memory.cpp
deleted file mode 100644
index 200246eb..00000000
--- a/loader_launcher_proxy/Memory.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "pch.h"
-
-extern HMODULE hTier0Module;
-IMemAlloc** g_ppMemAllocSingleton;
-
-void LoadTier0Handle()
-{
- if (!hTier0Module)
- hTier0Module = GetModuleHandleA("tier0.dll");
- if (!hTier0Module)
- return;
-
- g_ppMemAllocSingleton = (IMemAlloc**)GetProcAddress(hTier0Module, "g_pMemAllocSingleton");
-}
-
-const int STATIC_ALLOC_SIZE = 4096;
-
-size_t g_iStaticAllocated = 0;
-void* g_pLastAllocated = nullptr;
-char pStaticAllocBuf[STATIC_ALLOC_SIZE];
-
-// they should never be used here, except in LibraryLoadError?
-
-void* malloc(size_t n)
-{
- // allocate into static buffer
- if (g_iStaticAllocated + n <= STATIC_ALLOC_SIZE)
- {
- void* ret = pStaticAllocBuf + g_iStaticAllocated;
- g_iStaticAllocated += n;
- return ret;
- }
- else
- {
- // try to fallback to g_pMemAllocSingleton
- if (!hTier0Module || !g_ppMemAllocSingleton)
- LoadTier0Handle();
- if (g_ppMemAllocSingleton && *g_ppMemAllocSingleton)
- return (*g_ppMemAllocSingleton)->m_vtable->Alloc(*g_ppMemAllocSingleton, n);
- else
- throw "Cannot allocate";
- }
-}
-
-void free(void* p)
-{
- // if it was allocated into the static buffer, just do nothing, safest way to deal with it
- if (p >= pStaticAllocBuf && p <= pStaticAllocBuf + STATIC_ALLOC_SIZE)
- return;
-
- if (g_ppMemAllocSingleton && *g_ppMemAllocSingleton)
- (*g_ppMemAllocSingleton)->m_vtable->Free(*g_ppMemAllocSingleton, p);
-}
-
-void* realloc(void* old_ptr, size_t size)
-{
- // it was allocated into the static buffer
- if (old_ptr >= pStaticAllocBuf && old_ptr <= pStaticAllocBuf + STATIC_ALLOC_SIZE)
- {
- if (g_pLastAllocated == old_ptr)
- {
- // nothing was allocated after this
- size_t old_size = g_iStaticAllocated - ((size_t)g_pLastAllocated - (size_t)pStaticAllocBuf);
- size_t diff = size - old_size;
- if (diff > 0)
- g_iStaticAllocated += diff;
- return old_ptr;
- }
- else
- {
- return malloc(size);
- }
- }
-
- if (g_ppMemAllocSingleton && *g_ppMemAllocSingleton)
- return (*g_ppMemAllocSingleton)->m_vtable->Realloc(*g_ppMemAllocSingleton, old_ptr, size);
- return nullptr;
-}
-
-void* operator new(size_t n) { return malloc(n); }
-
-void operator delete(void* p) { return free(p); }
diff --git a/loader_launcher_proxy/Memory.h b/loader_launcher_proxy/Memory.h
deleted file mode 100644
index c983966c..00000000
--- a/loader_launcher_proxy/Memory.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-class IMemAlloc
-{
-public:
- struct VTable
- {
- void* unknown[1]; // alloc debug
- void* (*Alloc) (IMemAlloc* memAlloc, size_t nSize);
- void* unknown2[1]; // realloc debug
- void* (*Realloc)(IMemAlloc* memAlloc, void* pMem, size_t nSize);
- void* unknown3[1]; // free #1
- void (*Free) (IMemAlloc* memAlloc, void* pMem);
- void* unknown4[2]; // nullsubs, maybe CrtSetDbgFlag
- size_t(*GetSize) (IMemAlloc* memAlloc, void* pMem);
- void* unknown5[9]; // they all do literally nothing
- void (*DumpStats) (IMemAlloc* memAlloc);
- void (*DumpStatsFileBase) (IMemAlloc* memAlloc, const char* pchFileBase);
- void* unknown6[4];
- int (*heapchk) (IMemAlloc* memAlloc);
- };
-
- VTable* m_vtable;
-};
diff --git a/loader_launcher_proxy/dllmain.cpp b/loader_launcher_proxy/dllmain.cpp
index 1215ca1f..a382bc97 100644
--- a/loader_launcher_proxy/dllmain.cpp
+++ b/loader_launcher_proxy/dllmain.cpp
@@ -2,7 +2,7 @@
#include <stdio.h>
#include <string>
#include <system_error>
-#include <Shlwapi.h>
+#include <shlwapi.h>
#include <sstream>
#include <fstream>
#include <filesystem>
@@ -14,61 +14,64 @@ HMODULE hTier0Module;
using CreateInterfaceFn = void* (*)(const char* pName, int* pReturnCode);
// does not seem to ever be used
-extern "C" _declspec(dllexport) void* __fastcall CreateInterface(const char* pName, int* pReturnCode)
+extern "C" __declspec(dllexport) void* __fastcall CreateInterface(const char* pName, int* pReturnCode)
{
- //AppSystemCreateInterfaceFn(pName, pReturnCode);
- printf("external CreateInterface: name: %s\n", pName);
+ // AppSystemCreateInterfaceFn(pName, pReturnCode);
+ printf("external CreateInterface: name: %s\n", pName);
- static CreateInterfaceFn launcher_CreateInterface = (CreateInterfaceFn)GetProcAddress(hLauncherModule, "CreateInterface");
- auto res = launcher_CreateInterface(pName, pReturnCode);
+ static CreateInterfaceFn launcher_CreateInterface = (CreateInterfaceFn)GetProcAddress(hLauncherModule, "CreateInterface");
+ auto res = launcher_CreateInterface(pName, pReturnCode);
- printf("external CreateInterface: return code: %p\n", res);
- return res;
+ printf("external CreateInterface: return code: %p\n", res);
+ return res;
}
bool GetExePathWide(wchar_t* dest, DWORD destSize)
{
- if (!dest) return NULL;
- if (destSize < MAX_PATH) return NULL;
+ if (!dest)
+ return NULL;
+ if (destSize < MAX_PATH)
+ return NULL;
- DWORD length = GetModuleFileNameW(NULL, dest, destSize);
- return length && PathRemoveFileSpecW(dest);
+ DWORD length = GetModuleFileNameW(NULL, dest, destSize);
+ return length && PathRemoveFileSpecW(dest);
}
FARPROC GetLauncherMain()
{
- static FARPROC Launcher_LauncherMain;
- if (!Launcher_LauncherMain)
- Launcher_LauncherMain = GetProcAddress(hLauncherModule, "LauncherMain");
- return Launcher_LauncherMain;
+ static FARPROC Launcher_LauncherMain;
+ if (!Launcher_LauncherMain)
+ Launcher_LauncherMain = GetProcAddress(hLauncherModule, "LauncherMain");
+ return Launcher_LauncherMain;
}
void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t* location)
{
- char text[4096];
- std::string message = std::system_category().message(dwMessageId);
- sprintf_s(text, "Failed to load the %ls at \"%ls\" (%lu):\n\n%hs", libName, location, dwMessageId, message.c_str());
- if (dwMessageId == 126 && std::filesystem::exists(location))
- {
- sprintf_s(text, "%s\n\nThe file at the specified location DOES exist, so this error indicates that one of its *dependencies* failed to be found.", text);
- }
- MessageBoxA(GetForegroundWindow(), text, "Northstar Launcher Proxy Error", 0);
+ char text[4096];
+ std::string message = std::system_category().message(dwMessageId);
+ sprintf_s(text, "Failed to load the %ls at \"%ls\" (%lu):\n\n%hs", libName, location, dwMessageId, message.c_str());
+ if (dwMessageId == 126 && std::filesystem::exists(location))
+ {
+ sprintf_s(
+ text,
+ "%s\n\nThe file at the specified location DOES exist, so this error indicates that one of its *dependencies* failed to be "
+ "found.",
+ text);
+ }
+ MessageBoxA(GetForegroundWindow(), text, "Northstar Launcher Proxy Error", 0);
}
-BOOL APIENTRY DllMain( HMODULE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved
- )
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
}
wchar_t exePath[4096];
@@ -76,86 +79,96 @@ wchar_t dllPath[4096];
bool ShouldLoadNorthstar()
{
- bool loadNorthstar = !strstr(GetCommandLineA(), "-vanilla");
-
- if (!loadNorthstar)
- return loadNorthstar;
-
- auto runNorthstarFile = std::ifstream("run_northstar.txt");
- if (runNorthstarFile)
- {
- std::stringstream runNorthstarFileBuffer;
- runNorthstarFileBuffer << runNorthstarFile.rdbuf();
- runNorthstarFile.close();
- if (runNorthstarFileBuffer.str()._Starts_with("0"))
- loadNorthstar = false;
- }
- return loadNorthstar;
+ bool loadNorthstar = !strstr(GetCommandLineA(), "-vanilla");
+
+ if (!loadNorthstar)
+ return loadNorthstar;
+
+ auto runNorthstarFile = std::ifstream("run_northstar.txt");
+ if (runNorthstarFile)
+ {
+ std::stringstream runNorthstarFileBuffer;
+ runNorthstarFileBuffer << runNorthstarFile.rdbuf();
+ runNorthstarFile.close();
+ if (runNorthstarFileBuffer.str().starts_with("0"))
+ loadNorthstar = false;
+ }
+ return loadNorthstar;
}
bool LoadNorthstar()
{
- FARPROC Hook_Init = nullptr;
- {
- swprintf_s(dllPath, L"%s\\Northstar.dll", exePath);
- hHookModule = LoadLibraryExW(dllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (hHookModule) Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar");
- if (!hHookModule || Hook_Init == nullptr)
- {
- LibraryLoadError(GetLastError(), L"Northstar.dll", dllPath);
- return false;
- }
- }
-
- ((bool (*)()) Hook_Init)();
- return true;
+ FARPROC Hook_Init = nullptr;
+ {
+ swprintf_s(dllPath, L"%s\\Northstar.dll", exePath);
+ hHookModule = LoadLibraryExW(dllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (hHookModule)
+ Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar");
+ if (!hHookModule || Hook_Init == nullptr)
+ {
+ LibraryLoadError(GetLastError(), L"Northstar.dll", dllPath);
+ return false;
+ }
+ }
+
+ ((bool (*)())Hook_Init)();
+ return true;
}
extern "C" __declspec(dllexport) int LauncherMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
- {
- if (!GetExePathWide(exePath, 4096))
- {
- MessageBoxA(GetForegroundWindow(), "Failed getting game directory.\nThe game cannot continue and has to exit.", "Northstar Launcher Proxy Error", 0);
- return 1;
- }
-
- bool loadNorthstar = ShouldLoadNorthstar();
-
- if (loadNorthstar)
- {
- swprintf_s(dllPath, L"%s\\bin\\x64_retail\\tier0.dll", exePath);
- hTier0Module = LoadLibraryExW(dllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (!hTier0Module)
- {
- LibraryLoadError(GetLastError(), L"tier0.dll", dllPath);
- return 1;
- }
-
- if (!LoadNorthstar())
- return 1;
- }
- //else printf("\n\n WILL !!!NOT!!! LOAD NORTHSTAR\n\n");
-
- swprintf_s(dllPath, L"%s\\bin\\x64_retail\\launcher.org.dll", exePath);
- hLauncherModule = LoadLibraryExW(dllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (!hLauncherModule)
- {
- LibraryLoadError(GetLastError(), L"launcher.org.dll", dllPath);
- return 1;
- }
- }
-
- auto LauncherMain = GetLauncherMain();
- if (!LauncherMain)
- MessageBoxA(GetForegroundWindow(), "Failed loading launcher.org.dll.\nThe game cannot continue and has to exit.", "Northstar Launcher Proxy Error", 0);
- //auto result = ((__int64(__fastcall*)())LauncherMain)();
- //auto result = ((signed __int64(__fastcall*)(__int64))LauncherMain)(0i64);
- return ((int(__fastcall*)(HINSTANCE, HINSTANCE, LPSTR, int))LauncherMain)(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
+ {
+ if (!GetExePathWide(exePath, 4096))
+ {
+ MessageBoxA(
+ GetForegroundWindow(),
+ "Failed getting game directory.\nThe game cannot continue and has to exit.",
+ "Northstar Launcher Proxy Error",
+ 0);
+ return 1;
+ }
+
+ bool loadNorthstar = ShouldLoadNorthstar();
+
+ if (loadNorthstar)
+ {
+ swprintf_s(dllPath, L"%s\\bin\\x64_retail\\tier0.dll", exePath);
+ hTier0Module = LoadLibraryExW(dllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (!hTier0Module)
+ {
+ LibraryLoadError(GetLastError(), L"tier0.dll", dllPath);
+ return 1;
+ }
+
+ if (!LoadNorthstar())
+ return 1;
+ }
+ // else printf("\n\n WILL !!!NOT!!! LOAD NORTHSTAR\n\n");
+
+ swprintf_s(dllPath, L"%s\\bin\\x64_retail\\launcher.org.dll", exePath);
+ hLauncherModule = LoadLibraryExW(dllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (!hLauncherModule)
+ {
+ LibraryLoadError(GetLastError(), L"launcher.org.dll", dllPath);
+ return 1;
+ }
+ }
+
+ auto LauncherMain = GetLauncherMain();
+ if (!LauncherMain)
+ MessageBoxA(
+ GetForegroundWindow(),
+ "Failed loading launcher.org.dll.\nThe game cannot continue and has to exit.",
+ "Northstar Launcher Proxy Error",
+ 0);
+ // auto result = ((__int64(__fastcall*)())LauncherMain)();
+ // auto result = ((signed __int64(__fastcall*)(__int64))LauncherMain)(0i64);
+ return ((int(__fastcall*)(HINSTANCE, HINSTANCE, LPSTR, int))LauncherMain)(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
// doubt that will help us here (in launcher.dll) though
-extern "C" {
- __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
- __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
+extern "C"
+{
+ __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
+ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}
diff --git a/loader_launcher_proxy/framework.h b/loader_launcher_proxy/framework.h
index d1b49600..1800e436 100644
--- a/loader_launcher_proxy/framework.h
+++ b/loader_launcher_proxy/framework.h
@@ -1,7 +1,7 @@
#pragma once
-#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define WIN32_EXTRA_LEAN
#define VC_EXTRALEAN
// Windows Header Files
-#include <Windows.h>
+#include <windows.h>
diff --git a/loader_launcher_proxy/loader_launcher_proxy.vcxproj b/loader_launcher_proxy/loader_launcher_proxy.vcxproj
index 24cdabc0..b62ac63f 100644
--- a/loader_launcher_proxy/loader_launcher_proxy.vcxproj
+++ b/loader_launcher_proxy/loader_launcher_proxy.vcxproj
@@ -59,7 +59,7 @@
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <LanguageStandard>stdcpp17</LanguageStandard>
+ <LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -78,7 +78,7 @@
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <LanguageStandard>stdcpp17</LanguageStandard>
+ <LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
diff --git a/loader_launcher_proxy/loader_launcher_proxy.vcxproj.filters b/loader_launcher_proxy/loader_launcher_proxy.vcxproj.filters
index 1e57c7b1..4bf52578 100644
--- a/loader_launcher_proxy/loader_launcher_proxy.vcxproj.filters
+++ b/loader_launcher_proxy/loader_launcher_proxy.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
@@ -30,4 +30,4 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/loader_launcher_proxy/pch.h b/loader_launcher_proxy/pch.h
index 885d5d62..cc757129 100644
--- a/loader_launcher_proxy/pch.h
+++ b/loader_launcher_proxy/pch.h
@@ -10,4 +10,4 @@
// add headers that you want to pre-compile here
#include "framework.h"
-#endif //PCH_H
+#endif // PCH_H
diff --git a/loader_wsock32_proxy/dllmain.cpp b/loader_wsock32_proxy/dllmain.cpp
index f4c0d604..7feb278d 100644
--- a/loader_wsock32_proxy/dllmain.cpp
+++ b/loader_wsock32_proxy/dllmain.cpp
@@ -1,7 +1,7 @@
#include "pch.h"
#include "loader.h"
-#include <Shlwapi.h>
+#include <shlwapi.h>
#include <filesystem>
HINSTANCE hLThis = 0;
@@ -10,8 +10,10 @@ HINSTANCE hL = 0;
bool GetExePathWide(wchar_t* dest, DWORD destSize)
{
- if (!dest) return NULL;
- if (destSize < MAX_PATH) return NULL;
+ if (!dest)
+ return NULL;
+ if (destSize < MAX_PATH)
+ return NULL;
DWORD length = GetModuleFileNameW(NULL, dest, destSize);
return length && PathRemoveFileSpecW(dest);
@@ -29,7 +31,11 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID)
if (!GetExePathWide(exePath, 4096))
{
- MessageBoxA(GetForegroundWindow(), "Failed getting game directory.\nThe game cannot continue and has to exit.", "Northstar Wsock32 Proxy Error", 0);
+ MessageBoxA(
+ GetForegroundWindow(),
+ "Failed getting game directory.\nThe game cannot continue and has to exit.",
+ "Northstar Wsock32 Proxy Error",
+ 0);
return true;
}
@@ -59,7 +65,14 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID)
{
if (!std::filesystem::exists(temp_dir))
{
- swprintf_s(buffer2, L"Failed copying wsock32.dll from system32 to \"%s\"\n\n%S\n\nFurthermore, we failed copying wsock32.dll into temporary directory at \"%s\"\n\n%S", buffer1, e1.what(), temp_dir.c_str(), e2.what());
+ swprintf_s(
+ buffer2,
+ L"Failed copying wsock32.dll from system32 to \"%s\"\n\n%S\n\nFurthermore, we failed copying wsock32.dll into "
+ L"temporary directory at \"%s\"\n\n%S",
+ buffer1,
+ e1.what(),
+ temp_dir.c_str(),
+ e2.what());
MessageBoxW(GetForegroundWindow(), buffer2, L"Northstar Wsock32 Proxy Error", 0);
return false;
}
@@ -68,7 +81,8 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID)
}
}
hL = LoadLibraryExW(buffer1, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (!hL) {
+ if (!hL)
+ {
LibraryLoadError(GetLastError(), L"wsock32.org.dll", buffer1);
return false;
}
@@ -104,52 +118,64 @@ extern "C"
FARPROC PA = NULL;
int RunASM();
- void PROXY_EnumProtocolsA() {
+ void PROXY_EnumProtocolsA()
+ {
PA = p[1];
RunASM();
}
- void PROXY_EnumProtocolsW() {
+ void PROXY_EnumProtocolsW()
+ {
PA = p[2];
RunASM();
}
- void PROXY_GetAddressByNameA() {
+ void PROXY_GetAddressByNameA()
+ {
PA = p[4];
RunASM();
}
- void PROXY_GetAddressByNameW() {
+ void PROXY_GetAddressByNameW()
+ {
PA = p[5];
RunASM();
}
- void PROXY_WEP() {
+ void PROXY_WEP()
+ {
PA = p[17];
RunASM();
}
- void PROXY_WSARecvEx() {
+ void PROXY_WSARecvEx()
+ {
PA = p[30];
RunASM();
}
- void PROXY___WSAFDIsSet() {
+ void PROXY___WSAFDIsSet()
+ {
PA = p[36];
RunASM();
}
- void PROXY_getnetbyname() {
+ void PROXY_getnetbyname()
+ {
PA = p[45];
RunASM();
}
- void PROXY_getsockopt() {
+ void PROXY_getsockopt()
+ {
PA = p[52];
RunASM();
}
- void PROXY_inet_network() {
+ void PROXY_inet_network()
+ {
PA = p[56];
RunASM();
}
- void PROXY_s_perror() {
+ void PROXY_s_perror()
+ {
PA = p[67];
RunASM();
}
- void PROXY_setsockopt() {
+ void PROXY_setsockopt()
+ {
PA = p[72];
RunASM();
}
-} \ No newline at end of file
+}
diff --git a/loader_wsock32_proxy/hookutils.cpp b/loader_wsock32_proxy/hookutils.cpp
deleted file mode 100644
index f933f993..00000000
--- a/loader_wsock32_proxy/hookutils.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "pch.h"
-#include "../NorthstarDedicatedTest/hookutils.h"
-
-#define ERROR(...) { char err[2048]; sprintf_s(err, __VA_ARGS__); MessageBoxA(GetForegroundWindow(), err, "Northstar Wsock32 Proxy Error", 0); }
-
-void HookEnabler::CreateHook(LPVOID ppTarget, LPVOID ppDetour, LPVOID* ppOriginal, const char* targetName)
-{
- // the macro for this uses ppTarget's name as targetName, and this typically starts with &
- // targetname is used for debug stuff and debug output is nicer if we don't have this
- if (*targetName == '&')
- targetName++;
-
- if (MH_CreateHook(ppTarget, ppDetour, ppOriginal) == MH_OK)
- {
- HookTarget* target = new HookTarget;
- target->targetAddress = ppTarget;
- target->targetName = (char*)targetName;
-
- m_hookTargets.push_back(target);
- }
- else
- {
- if (targetName != nullptr)
- {
- ERROR("MH_CreateHook failed for function %s", targetName);
- }
- else
- {
- ERROR("MH_CreateHook failed for unknown function");
- }
- }
-}
-
-HookEnabler::~HookEnabler()
-{
- for (auto& hook : m_hookTargets)
- {
- if (MH_EnableHook(hook->targetAddress) != MH_OK)
- {
- if (hook->targetName != nullptr)
- {
- ERROR("MH_EnableHook failed for function %s", hook->targetName);
- }
- else
- {
- ERROR("MH_EnableHook failed for unknown function");
- }
- }
- else
- {
- //ERROR("Enabling hook %s", hook->targetName);
- }
- }
-} \ No newline at end of file
diff --git a/loader_wsock32_proxy/include/MinHook.h b/loader_wsock32_proxy/include/MinHook.h
new file mode 100644
index 00000000..15c0a875
--- /dev/null
+++ b/loader_wsock32_proxy/include/MinHook.h
@@ -0,0 +1,186 @@
+/*
+ * MinHook - The Minimalistic API Hooking Library for x64/x86
+ * Copyright (C) 2009-2017 Tsuda Kageyu.
+ * 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.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
+ #error MinHook supports only x86 and x64 systems.
+#endif
+
+#include <windows.h>
+
+// MinHook Error Codes.
+typedef enum MH_STATUS
+{
+ // Unknown error. Should not be returned.
+ MH_UNKNOWN = -1,
+
+ // Successful.
+ MH_OK = 0,
+
+ // MinHook is already initialized.
+ MH_ERROR_ALREADY_INITIALIZED,
+
+ // MinHook is not initialized yet, or already uninitialized.
+ MH_ERROR_NOT_INITIALIZED,
+
+ // The hook for the specified target function is already created.
+ MH_ERROR_ALREADY_CREATED,
+
+ // The hook for the specified target function is not created yet.
+ MH_ERROR_NOT_CREATED,
+
+ // The hook for the specified target function is already enabled.
+ MH_ERROR_ENABLED,
+
+ // The hook for the specified target function is not enabled yet, or already
+ // disabled.
+ MH_ERROR_DISABLED,
+
+ // The specified pointer is invalid. It points the address of non-allocated
+ // and/or non-executable region.
+ MH_ERROR_NOT_EXECUTABLE,
+
+ // The specified target function cannot be hooked.
+ MH_ERROR_UNSUPPORTED_FUNCTION,
+
+ // Failed to allocate memory.
+ MH_ERROR_MEMORY_ALLOC,
+
+ // Failed to change the memory protection.
+ MH_ERROR_MEMORY_PROTECT,
+
+ // The specified module is not loaded.
+ MH_ERROR_MODULE_NOT_FOUND,
+
+ // The specified function is not found.
+ MH_ERROR_FUNCTION_NOT_FOUND
+}
+MH_STATUS;
+
+// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
+// MH_QueueEnableHook or MH_QueueDisableHook.
+#define MH_ALL_HOOKS NULL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // Initialize the MinHook library. You must call this function EXACTLY ONCE
+ // at the beginning of your program.
+ MH_STATUS WINAPI MH_Initialize(VOID);
+
+ // Uninitialize the MinHook library. You must call this function EXACTLY
+ // ONCE at the end of your program.
+ MH_STATUS WINAPI MH_Uninitialize(VOID);
+
+ // Creates a Hook for the specified target function, in disabled state.
+ // Parameters:
+ // pTarget [in] A pointer to the target function, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
+
+ // Creates a Hook for the specified API function, in disabled state.
+ // Parameters:
+ // pszModule [in] A pointer to the loaded module name which contains the
+ // target function.
+ // pszTarget [in] A pointer to the target function name, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHookApi(
+ LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
+
+ // Creates a Hook for the specified API function, in disabled state.
+ // Parameters:
+ // pszModule [in] A pointer to the loaded module name which contains the
+ // target function.
+ // pszTarget [in] A pointer to the target function name, which will be
+ // overridden by the detour function.
+ // pDetour [in] A pointer to the detour function, which will override
+ // the target function.
+ // ppOriginal [out] A pointer to the trampoline function, which will be
+ // used to call the original target function.
+ // This parameter can be NULL.
+ // ppTarget [out] A pointer to the target function, which will be used
+ // with other functions.
+ // This parameter can be NULL.
+ MH_STATUS WINAPI MH_CreateHookApiEx(
+ LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
+
+ // Removes an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
+
+ // Enables an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // enabled in one go.
+ MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
+
+ // Disables an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // disabled in one go.
+ MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
+
+ // Queues to enable an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // queued to be enabled.
+ MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
+
+ // Queues to disable an already created hook.
+ // Parameters:
+ // pTarget [in] A pointer to the target function.
+ // If this parameter is MH_ALL_HOOKS, all created hooks are
+ // queued to be disabled.
+ MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
+
+ // Applies all queued changes in one go.
+ MH_STATUS WINAPI MH_ApplyQueued(VOID);
+
+ // Translates the MH_STATUS to its name as a string.
+ const char * WINAPI MH_StatusToString(MH_STATUS status);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/loader_wsock32_proxy/include/MinHook.x64.lib b/loader_wsock32_proxy/include/MinHook.x64.lib
new file mode 100644
index 00000000..a346f386
--- /dev/null
+++ b/loader_wsock32_proxy/include/MinHook.x64.lib
Binary files differ
diff --git a/loader_wsock32_proxy/loader.cpp b/loader_wsock32_proxy/loader.cpp
index 61b4daf3..4af4daa1 100644
--- a/loader_wsock32_proxy/loader.cpp
+++ b/loader_wsock32_proxy/loader.cpp
@@ -1,6 +1,6 @@
#include "pch.h"
#include "loader.h"
-#include "../NorthstarDedicatedTest/hookutils.h"
+#include "include/MinHook.h"
#include <string>
#include <system_error>
#include <sstream>
@@ -14,7 +14,11 @@ void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t*
sprintf_s(text, "Failed to load the %ls at \"%ls\" (%lu):\n\n%hs", libName, location, dwMessageId, message.c_str());
if (dwMessageId == 126 && std::filesystem::exists(location))
{
- sprintf_s(text, "%s\n\nThe file at the specified location DOES exist, so this error indicates that one of its *dependencies* failed to be found.", text);
+ sprintf_s(
+ text,
+ "%s\n\nThe file at the specified location DOES exist, so this error indicates that one of its *dependencies* failed to be "
+ "found.",
+ text);
}
MessageBoxA(GetForegroundWindow(), text, "Northstar Wsock32 Proxy Error", 0);
}
@@ -44,7 +48,8 @@ bool LoadNorthstar()
{
swprintf_s(buffer1, L"%s\\Northstar.dll", exePath);
auto hHookModule = LoadLibraryExW(buffer1, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (hHookModule) Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar");
+ if (hHookModule)
+ Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar");
if (!hHookModule || Hook_Init == nullptr)
{
LibraryLoadError(GetLastError(), L"Northstar.dll", buffer1);
@@ -52,11 +57,11 @@ bool LoadNorthstar()
}
}
- ((bool (*)()) Hook_Init)();
+ ((bool (*)())Hook_Init)();
return true;
}
-typedef int(*LauncherMainType)(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
+typedef int (*LauncherMainType)(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
LauncherMainType LauncherMainOriginal;
int LauncherMainHook(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
@@ -73,19 +78,26 @@ bool ProvisionNorthstar()
if (MH_Initialize() != MH_OK)
{
- MessageBoxA(GetForegroundWindow(), "MH_Initialize failed\nThe game cannot continue and has to exit.", "Northstar Wsock32 Proxy Error", 0);
+ MessageBoxA(
+ GetForegroundWindow(), "MH_Initialize failed\nThe game cannot continue and has to exit.", "Northstar Wsock32 Proxy Error", 0);
return false;
}
auto launcherHandle = GetModuleHandleA("launcher.dll");
if (!launcherHandle)
{
- MessageBoxA(GetForegroundWindow(), "Launcher isn't loaded yet.\nThe game cannot continue and has to exit.", "Northstar Wsock32 Proxy Error", 0);
+ MessageBoxA(
+ GetForegroundWindow(),
+ "Launcher isn't loaded yet.\nThe game cannot continue and has to exit.",
+ "Northstar Wsock32 Proxy Error",
+ 0);
return false;
}
- HookEnabler hook;
- ENABLER_CREATEHOOK(hook, GetProcAddress(launcherHandle, "LauncherMain"), &LauncherMainHook, reinterpret_cast<LPVOID*>(&LauncherMainOriginal));
+ LPVOID pTarget = GetProcAddress(launcherHandle, "LauncherMain");
+ if (MH_CreateHook(pTarget, &LauncherMainHook, reinterpret_cast<LPVOID*>(&LauncherMainOriginal)) != MH_OK ||
+ MH_EnableHook(pTarget) != MH_OK)
+ MessageBoxA(GetForegroundWindow(), "Hook creation failed for function LauncherMain.", "Northstar Wsock32 Proxy Error", 0);
return true;
-} \ No newline at end of file
+}
diff --git a/loader_wsock32_proxy/loader_wsock32_proxy.vcxproj b/loader_wsock32_proxy/loader_wsock32_proxy.vcxproj
index 9866d368..d65a8f12 100644
--- a/loader_wsock32_proxy/loader_wsock32_proxy.vcxproj
+++ b/loader_wsock32_proxy/loader_wsock32_proxy.vcxproj
@@ -60,7 +60,7 @@
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <LanguageStandard>stdcpp17</LanguageStandard>
+ <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>..\NorthstarDedicatedTest\</AdditionalIncludeDirectories>
</ClCompile>
<Link>
@@ -68,7 +68,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<ModuleDefinitionFile>wsock32.def</ModuleDefinitionFile>
- <AdditionalDependencies>..\NorthstarDedicatedTest\include\MinHook.x64.lib;mswsock.lib;ws2_32.lib;Shlwapi.lib;imagehlp.lib;dbghelp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>.\include\MinHook.x64.lib;mswsock.lib;ws2_32.lib;Shlwapi.lib;imagehlp.lib;dbghelp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -82,7 +82,7 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\NorthstarDedicatedTest\</AdditionalIncludeDirectories>
- <LanguageStandard>stdcpp17</LanguageStandard>
+ <LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -91,16 +91,16 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<ModuleDefinitionFile>wsock32.def</ModuleDefinitionFile>
- <AdditionalDependencies>..\NorthstarDedicatedTest\include\MinHook.x64.lib;mswsock.lib;ws2_32.lib;Shlwapi.lib;imagehlp.lib;dbghelp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;wsock32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>.\include\MinHook.x64.lib;mswsock.lib;ws2_32.lib;Shlwapi.lib;imagehlp.lib;dbghelp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;wsock32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClInclude Include="include\MinHook.h" />
<ClInclude Include="loader.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
- <ClCompile Include="hookutils.cpp" />
<ClCompile Include="loader.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
diff --git a/loader_wsock32_proxy/loader_wsock32_proxy.vcxproj.filters b/loader_wsock32_proxy/loader_wsock32_proxy.vcxproj.filters
index 6d131e5b..d3c022de 100644
--- a/loader_wsock32_proxy/loader_wsock32_proxy.vcxproj.filters
+++ b/loader_wsock32_proxy/loader_wsock32_proxy.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
@@ -13,6 +13,9 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
+ <Filter Include="Header Files\include">
+ <UniqueIdentifier>{1b1575f7-3332-478b-9e85-9c0978249a70}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
@@ -21,6 +24,9 @@
<ClInclude Include="loader.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="include\MinHook.h">
+ <Filter>Header Files\include</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
@@ -32,9 +38,6 @@
<ClCompile Include="loader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="hookutils.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
</ItemGroup>
<ItemGroup>
<MASM Include="wsock32.asm">
@@ -46,4 +49,4 @@
<Filter>Source Files</Filter>
</None>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/loader_wsock32_proxy/pch.h b/loader_wsock32_proxy/pch.h
index 0103ff59..6e8873a1 100644
--- a/loader_wsock32_proxy/pch.h
+++ b/loader_wsock32_proxy/pch.h
@@ -7,10 +7,10 @@
#ifndef PCH_H
#define PCH_H
-#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
#include "include/MinHook.h"
-#endif //PCH_H
+#endif // PCH_H