init
11
.gitattributes
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# Line Endings
|
||||
*.cpp text eof=lf
|
||||
*.hpp text eof=lf
|
||||
*.php text eof=lf
|
||||
*.cs text eof=lf
|
||||
|
||||
# Exclude vendored code from language stats
|
||||
Stand/lib/** linguist-vendored
|
||||
|
||||
# Count .pluto files as Lua
|
||||
*.pluto linguist-language=Lua
|
39
.gitignore
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# Trash
|
||||
.vs/
|
||||
bin/
|
||||
_bin/
|
||||
int/
|
||||
Debug/
|
||||
obj/
|
||||
stand.gg/src/vendor/
|
||||
*.asi
|
||||
*.lib
|
||||
*.lnk
|
||||
*.log
|
||||
*.obj
|
||||
*.pch
|
||||
*.recipe
|
||||
*.tlog
|
||||
*.exe
|
||||
*.map
|
||||
composer.lock
|
||||
.apm_cache/
|
||||
|
||||
# Script-Generated Trash
|
||||
lang/flex/
|
||||
lang/translations.json
|
||||
Stand/bin.*pp
|
||||
Stand/font_*
|
||||
Stand/lang_*.cpp
|
||||
Stand/xormagics.hpp
|
||||
stand.gg/lang/
|
||||
vehicle_items generator/vehicles.json
|
||||
|
||||
# DLLs
|
||||
*.dll
|
||||
|
||||
# Tools
|
||||
Virtualizer/
|
||||
|
||||
# Misc
|
||||
Changelog.md
|
BIN
Default Custom Header.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
Default Theme/BeVietnamProLight.spritefont
Normal file
BIN
Default Theme/Disabled.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Default Theme/Edit.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
Default Theme/Enabled.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Default Theme/Friends.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Default Theme/Header Loading.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
Default Theme/Link.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
Default Theme/List.png
Normal file
After Width: | Height: | Size: 747 B |
BIN
Default Theme/NanumGothic.spritefont
Normal file
BIN
Default Theme/Search.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Default Theme/Tabs/Game.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
Default Theme/Tabs/Online.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
Default Theme/Tabs/Players.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
Default Theme/Tabs/Self.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
Default Theme/Tabs/Stand.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
Default Theme/Tabs/Vehicle.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
Default Theme/Tabs/World.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
Default Theme/Toggle Off Auto.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Default Theme/Toggle Off List.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Default Theme/Toggle Off.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Default Theme/Toggle On Auto.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
Default Theme/Toggle On List.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Default Theme/Toggle On.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Default Theme/User.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
Default Theme/Users.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
Default Theme/YaHei.spritefont
Normal file
1
Directory.Build.props
Normal file
@ -0,0 +1 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <EnableUnitySupport>true</EnableUnitySupport> </PropertyGroup> </Project>
|
71
ISaidNoRTTI/ISaidNoRTTI.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
static void eraseRttiByPattern(std::string& str, const char* pattern)
|
||||
{
|
||||
size_t pattern_i = 0;
|
||||
size_t pattern_len = strlen(pattern);
|
||||
std::string::iterator rtti_start;
|
||||
std::string rttibuf{};
|
||||
for (auto i = str.begin(); i != str.end(); ++i)
|
||||
{
|
||||
const auto c = *i;
|
||||
if (pattern_i == pattern_len)
|
||||
{
|
||||
if (c != 0)
|
||||
{
|
||||
rttibuf.push_back(c);
|
||||
continue;
|
||||
}
|
||||
if (rttibuf.find("Stand") != std::string::npos
|
||||
|| rttibuf.find("soup") != std::string::npos
|
||||
)
|
||||
{
|
||||
for (auto j = rtti_start; j != i; ++j)
|
||||
{
|
||||
*j = 0;
|
||||
}
|
||||
//std::cout << "RTTI erased: " << std::move(rttibuf) << std::endl;
|
||||
}
|
||||
rttibuf.clear();
|
||||
}
|
||||
else if (pattern[pattern_i] == c)
|
||||
{
|
||||
if (pattern_i++ == 0)
|
||||
{
|
||||
rtti_start = i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
pattern_i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, const char** args)
|
||||
{
|
||||
const char* filename = args[1];
|
||||
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
file.unsetf(std::ios::skipws);
|
||||
|
||||
std::streampos file_size;
|
||||
file.seekg(0, std::ios::end);
|
||||
file_size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
std::string str;
|
||||
str.reserve(file_size);
|
||||
str.assign((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||
file.close();
|
||||
|
||||
eraseRttiByPattern(str, ".?AV");
|
||||
eraseRttiByPattern(str, ".?AU");
|
||||
eraseRttiByPattern(str, ".PEA");
|
||||
eraseRttiByPattern(str, ".P6AX");
|
||||
|
||||
std::ofstream ofile(filename, std::ios::binary);
|
||||
ofile.write(str.data(), str.size());
|
||||
|
||||
return 0;
|
||||
}
|
61
ISaidNoRTTI/ISaidNoRTTI.vcxproj
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{874eb20e-df0c-4496-9325-27476bf86e48}</ProjectGuid>
|
||||
<RootNamespace>ISaidNoRTTI</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</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)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>bin\</OutDir>
|
||||
<IntDir>bin\int\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<CallingConvention>FastCall</CallingConvention>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ISaidNoRTTI.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
6
ISaidNoRTTI/ISaidNoRTTI.vcxproj.filters
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ISaidNoRTTI.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
4
ISaidNoRTTI/ISaidNoRTTI.vcxproj.user
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
46
README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Stand
|
||||
|
||||
The ultimate trainer for Stealy V-eely Automobiley, allowing you to finally become a **[Stand User]**!
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Soup](https://github.com/calamity-inc/Soup)
|
||||
- [Soup-Lua-Bindings](https://github.com/calamity-inc/Soup-Lua-Bindings)
|
||||
|
||||
Make sure you have a flat folder structure, such that Stand and its dependencies have the same parent folder.
|
||||
|
||||
## Building
|
||||
|
||||
To make a Debug build of the Stand project, you need to perform the following steps:
|
||||
|
||||
1. Build the ScriptHookV project
|
||||
2. Build the Soup project in the ReleaseDLL configuration
|
||||
3. Ensure you have PHP installed and its php.ini has a memory_limit of at least 2G
|
||||
4. Double-click `lang/_update.bat`
|
||||
5. Open a console in the repository root and run `php generate_bin.php && php generate_font_bevietnamprolight.php && php generate_font_nanumgothic.php && php generate_font_yahei.php && php xormagics.php`
|
||||
|
||||
After that, you can compile the Stand project to your heart's content.
|
||||
|
||||
## Updating
|
||||
|
||||
Every once in a while, Rockstar will actually bother to change this game, which will make all mod menus unusable until they are updated. In order to update Stand to a new GTA version, the following changes must be made:
|
||||
|
||||
- [x] **Sigs.**
|
||||
- [x] **ASI Game Version.**
|
||||
|
||||
And for major updates:
|
||||
|
||||
- [x] **Crossmap.**
|
||||
- [x] **Peds.**
|
||||
- [x] **Vehicles.**
|
||||
- [x] **Weapons.**
|
||||
- [x] **Native Tables.** From decompiled scripts with up-to-date crossmap.
|
||||
- [x] **Script Funcs.**
|
||||
- [x] **Script Locals.**
|
||||
- [x] **Script Globals.**
|
||||
- [x] **Script Globals in MusinessBanager.**
|
||||
- [x] **Script Events.**
|
||||
- [x] **Session Scripts.**
|
||||
- [x] **Asset Hashes.**
|
||||
|
||||
Additionally, structs may be off; [ReClassEx64](https://github.com/ajkhoury/ReClassEx) and Cheat Engine will help update them.
|
80
ScriptHookV/ScriptHookV.vcxproj
Normal file
@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\scripthookv.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{01fe0637-6bcc-4ada-b0dd-7b7ff09541a2}</ProjectGuid>
|
||||
<RootNamespace>ScriptHookV</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>ClangCL</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</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)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<OutDir>bin\</OutDir>
|
||||
<IntDir>bin\int\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>
|
||||
</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>..\Stand\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<CallingConvention>FastCall</CallingConvention>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<NoEntryPoint>true</NoEntryPoint>
|
||||
<AdditionalOptions>"/pdbaltpath:made you look" %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
14
ScriptHookV/ScriptHookV.vcxproj.filters
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="src">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\scripthookv.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
4
ScriptHookV/ScriptHookV.vcxproj.user
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
199
ScriptHookV/src/scripthookv.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
#include <asi_decl.hpp>
|
||||
|
||||
using namespace Stand;
|
||||
|
||||
using createTexture_t = int(*)(const char*);
|
||||
using drawTexture_t = void(*)(int id, int index, int level, int time, float sizeX, float sizeY, float centerX, float centerY, float posX, float posY, float rotation, float screenHeightScaleFactor, float r, float g, float b, float a);
|
||||
using presentCallbackRegister_t = void(*)(AsiPresentCallback cb);
|
||||
using presentCallbackUnregister_t = void(*)(AsiPresentCallback cb);
|
||||
using keyboardHandlerRegister_t = void(*)(KeyboardHandler handler);
|
||||
using keyboardHandlerUnregister_t = void(*)(KeyboardHandler handler);
|
||||
using scriptWait_t = void(*)(DWORD time);
|
||||
using scriptRegister_t = void(*)(HMODULE module, void(*LP_SCRIPT_MAIN)());
|
||||
using scriptRegisterAdditionalThread_t = void(*)(HMODULE module, void(*LP_SCRIPT_MAIN)());
|
||||
using scriptUnregister_t = void(*)(HMODULE module);
|
||||
using scriptUnregister_old_t = void(*)(void(*LP_SCRIPT_MAIN)());
|
||||
using nativeInit_t = void(*)(UINT64 hash);
|
||||
using nativePush64_t = void(*)(UINT64 val);
|
||||
using nativeCall_t = PUINT64(*)();
|
||||
using getGlobalPtr_t = UINT64*(*)(int globalId);
|
||||
using worldGetAllVehicles_t = int(*)(int* arr, int arrSize);
|
||||
using worldGetAllPeds_t = int(*)(int* arr, int arrSize);
|
||||
using worldGetAllObjects_t = int(*)(int* arr, int arrSize);
|
||||
using worldGetAllPickups_t = int(*)(int* arr, int arrSize);
|
||||
using getScriptHandleBaseAddress_t = BYTE*(*)(int handle);
|
||||
using getGameVersion_t = eGameVersion(*)();
|
||||
|
||||
static createTexture_t Stand_createTexture;
|
||||
static drawTexture_t Stand_drawTexture;
|
||||
static presentCallbackRegister_t Stand_presentCallbackRegister;
|
||||
static presentCallbackUnregister_t Stand_presentCallbackUnregister;
|
||||
static keyboardHandlerRegister_t Stand_keyboardHandlerRegister;
|
||||
static keyboardHandlerUnregister_t Stand_keyboardHandlerUnregister;
|
||||
static scriptWait_t Stand_scriptWait;
|
||||
static scriptRegister_t Stand_scriptRegister;
|
||||
static scriptRegisterAdditionalThread_t Stand_scriptRegisterAdditionalThread;
|
||||
static scriptUnregister_t Stand_scriptUnregister;
|
||||
static scriptUnregister_old_t Stand_scriptUnregister_old;
|
||||
static nativeInit_t Stand_nativeInit;
|
||||
static nativePush64_t Stand_nativePush64;
|
||||
static nativeCall_t Stand_nativeCall;
|
||||
static getGlobalPtr_t Stand_getGlobalPtr;
|
||||
static worldGetAllVehicles_t Stand_worldGetAllVehicles;
|
||||
static worldGetAllPeds_t Stand_worldGetAllPeds;
|
||||
static worldGetAllObjects_t Stand_worldGetAllObjects;
|
||||
static worldGetAllPickups_t Stand_worldGetAllPickups;
|
||||
static getScriptHandleBaseAddress_t Stand_getScriptHandleBaseAddress;
|
||||
static getGameVersion_t Stand_getGameVersion;
|
||||
|
||||
extern "C" __declspec(dllexport) void SSHV_init(
|
||||
createTexture_t createTexture,
|
||||
drawTexture_t drawTexture,
|
||||
presentCallbackRegister_t presentCallbackRegister,
|
||||
presentCallbackUnregister_t presentCallbackUnregister,
|
||||
keyboardHandlerRegister_t keyboardHandlerRegister,
|
||||
keyboardHandlerUnregister_t keyboardHandlerUnregister,
|
||||
scriptWait_t scriptWait,
|
||||
scriptRegister_t scriptRegister,
|
||||
scriptRegisterAdditionalThread_t scriptRegisterAdditionalThread,
|
||||
scriptUnregister_t scriptUnregister,
|
||||
scriptUnregister_old_t scriptUnregister_old,
|
||||
nativeInit_t nativeInit,
|
||||
nativePush64_t nativePush64,
|
||||
nativeCall_t nativeCall,
|
||||
getGlobalPtr_t getGlobalPtr,
|
||||
worldGetAllVehicles_t worldGetAllVehicles,
|
||||
worldGetAllPeds_t worldGetAllPeds,
|
||||
worldGetAllObjects_t worldGetAllObjects,
|
||||
worldGetAllPickups_t worldGetAllPickups,
|
||||
getScriptHandleBaseAddress_t getScriptHandleBaseAddress,
|
||||
getGameVersion_t getGameVersion
|
||||
)
|
||||
{
|
||||
Stand_createTexture = createTexture;
|
||||
Stand_drawTexture = drawTexture;
|
||||
Stand_presentCallbackRegister = presentCallbackRegister;
|
||||
Stand_presentCallbackUnregister = presentCallbackUnregister;
|
||||
Stand_keyboardHandlerRegister = keyboardHandlerRegister;
|
||||
Stand_keyboardHandlerUnregister = keyboardHandlerUnregister;
|
||||
Stand_scriptWait = scriptWait;
|
||||
Stand_scriptRegister = scriptRegister;
|
||||
Stand_scriptRegisterAdditionalThread = scriptRegisterAdditionalThread;
|
||||
Stand_scriptUnregister = scriptUnregister;
|
||||
Stand_scriptUnregister_old = scriptUnregister_old;
|
||||
Stand_nativeInit = nativeInit;
|
||||
Stand_nativePush64 = nativePush64;
|
||||
Stand_nativeCall = nativeCall;
|
||||
Stand_getGlobalPtr = getGlobalPtr;
|
||||
Stand_worldGetAllVehicles = worldGetAllVehicles;
|
||||
Stand_worldGetAllPeds = worldGetAllPeds;
|
||||
Stand_worldGetAllObjects = worldGetAllObjects;
|
||||
Stand_worldGetAllPickups = worldGetAllPickups;
|
||||
Stand_getScriptHandleBaseAddress = getScriptHandleBaseAddress;
|
||||
Stand_getGameVersion = getGameVersion;
|
||||
}
|
||||
|
||||
__declspec(dllexport) int createTexture(const char* texFileName)
|
||||
{
|
||||
return Stand_createTexture(texFileName);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void drawTexture(int id, int index, int level, int time, float sizeX, float sizeY, float centerX, float centerY, float posX, float posY, float rotation, float screenHeightScaleFactor, float r, float g, float b, float a)
|
||||
{
|
||||
Stand_drawTexture(id, index, level, time, sizeX, sizeY, centerX, centerY, posX, posY, rotation, screenHeightScaleFactor, r, g, b, a);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void presentCallbackRegister(Stand::AsiPresentCallback cb)
|
||||
{
|
||||
Stand_presentCallbackRegister(cb);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void presentCallbackUnregister(Stand::AsiPresentCallback cb)
|
||||
{
|
||||
Stand_presentCallbackUnregister(cb);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void keyboardHandlerRegister(Stand::KeyboardHandler handler)
|
||||
{
|
||||
Stand_keyboardHandlerRegister(handler);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void keyboardHandlerUnregister(Stand::KeyboardHandler handler)
|
||||
{
|
||||
Stand_keyboardHandlerUnregister(handler);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void scriptWait(DWORD time)
|
||||
{
|
||||
Stand_scriptWait(time);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void scriptRegister(HMODULE module, void(*LP_SCRIPT_MAIN)())
|
||||
{
|
||||
Stand_scriptRegister(module, LP_SCRIPT_MAIN);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void scriptRegisterAdditionalThread(HMODULE module, void(*LP_SCRIPT_MAIN)())
|
||||
{
|
||||
Stand_scriptRegisterAdditionalThread(module, LP_SCRIPT_MAIN);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void scriptUnregister(HMODULE module)
|
||||
{
|
||||
Stand_scriptUnregister(module);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void scriptUnregister(void(*LP_SCRIPT_MAIN)())
|
||||
{
|
||||
Stand_scriptUnregister_old(LP_SCRIPT_MAIN);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void nativeInit(UINT64 hash)
|
||||
{
|
||||
Stand_nativeInit(hash);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void nativePush64(UINT64 val)
|
||||
{
|
||||
Stand_nativePush64(val);
|
||||
}
|
||||
|
||||
__declspec(dllexport) PUINT64 nativeCall()
|
||||
{
|
||||
return Stand_nativeCall();
|
||||
}
|
||||
|
||||
__declspec(dllexport) UINT64* getGlobalPtr(int globalId)
|
||||
{
|
||||
return Stand_getGlobalPtr(globalId);
|
||||
}
|
||||
|
||||
__declspec(dllexport) int worldGetAllVehicles(int* arr, int arrSize)
|
||||
{
|
||||
return Stand_worldGetAllVehicles(arr, arrSize);
|
||||
}
|
||||
|
||||
__declspec(dllexport) int worldGetAllPeds(int* arr, int arrSize)
|
||||
{
|
||||
return Stand_worldGetAllPeds(arr, arrSize);
|
||||
}
|
||||
|
||||
__declspec(dllexport) int worldGetAllObjects(int* arr, int arrSize)
|
||||
{
|
||||
return Stand_worldGetAllObjects(arr, arrSize);
|
||||
}
|
||||
|
||||
__declspec(dllexport) int worldGetAllPickups(int* arr, int arrSize)
|
||||
{
|
||||
return Stand_worldGetAllPickups(arr, arrSize);
|
||||
}
|
||||
|
||||
__declspec(dllexport) BYTE* getScriptHandleBaseAddress(int handle)
|
||||
{
|
||||
return Stand_getScriptHandleBaseAddress(handle);
|
||||
}
|
||||
|
||||
__declspec(dllexport) eGameVersion getGameVersion()
|
||||
{
|
||||
return Stand_getGameVersion();
|
||||
}
|
51
Server Software/guilded-bot/index.js
Normal file
@ -0,0 +1,51 @@
|
||||
const Guilded = require('guildscript');
|
||||
const client = new Guilded.Client();
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
client.on('ready', () => {
|
||||
console.log(`Logged in as ${client.user.name}.`);
|
||||
});
|
||||
|
||||
client.on('message', message => {
|
||||
let content = message.content.toString().trim();
|
||||
if(!message.channel.team && message.author != client.user && message.channel.constructor.name == "TextChannel")
|
||||
{
|
||||
if(content.substr(0, 15)=="Stand-Activate-"&&content.length==(15+31))
|
||||
{
|
||||
message.channel.send("Validating your activation key...");
|
||||
fetch("https://api.stand.one/internal_get_privilege/?0="+content.substr(15))
|
||||
.then(data=>data.text())
|
||||
.then(data=>
|
||||
{
|
||||
if(data=="0")
|
||||
{
|
||||
message.channel.send("Invalid activation key.");
|
||||
}
|
||||
else
|
||||
{
|
||||
let edition_names = {
|
||||
1: "Basic",
|
||||
2: "Regular",
|
||||
3: "Ultimate"
|
||||
};
|
||||
message.channel.send("Alright, that's a valid **"+edition_names[data]+" Edition** activation key, and you should have the role for that now. :)");
|
||||
let edition_role_ids = {
|
||||
1: "24499397",
|
||||
2: "24499396",
|
||||
3: "24499395",
|
||||
};
|
||||
client.request({
|
||||
method: "PUT",
|
||||
path: "teams/WlorOWQR/roles/"+edition_role_ids[data]+"/users/"+message.author.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
message.channel.send("Hi, I'm an automated service for getting the [Stand User] role in the Stand Community.\nTo do so, I simply require you to send me your activation key.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.login('guilded.bot@calamity.gg', 'ezyxjhc%!yHZAivCYhi7#4vc9ZGrme@odn3Ny!Tno6uLfKKGo&!$CaU3uyyc3U7&jXk5#tjc');
|
1
Server Software/guilded-bot/start.sh
Normal file
@ -0,0 +1 @@
|
||||
screen -dmS "guilded-bot" node index.js
|
24
Server Software/keygen/common.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
require "vendor/autoload.php";
|
||||
|
||||
$db = new hellsh\smw(
|
||||
"localhost",
|
||||
"web",
|
||||
"zP7gBygUPacLMnzN3yGmFhmMXazMgccZDn5eRFNfXPqXge4xPJHxAEN9QUzPnZkFNAnxk8fp7g8RfxE3SN66UJV3zm7f3eMPCXJgRaqkA5tVQErSi373WFBvEGUuweGN",
|
||||
"stand"
|
||||
);
|
||||
|
||||
function generateKey($len) : string
|
||||
{
|
||||
$str = "";
|
||||
for($i = 0; $i < $len; $i++)
|
||||
{
|
||||
$c = rand(0, 35);
|
||||
if($c > 9)
|
||||
{
|
||||
$c += 39;
|
||||
}
|
||||
$str .= chr(48 + $c);
|
||||
}
|
||||
return $str;
|
||||
}
|
5
Server Software/keygen/composer.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"require": {
|
||||
"hell-sh/smw": "^1.0"
|
||||
}
|
||||
}
|
13
Server Software/keygen/gen_basic.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require "common.php";
|
||||
|
||||
echo "--- Basic ---\n\n";
|
||||
|
||||
for($i = 0; $i < $argv[2]; $i++)
|
||||
{
|
||||
$key = generateKey(30);
|
||||
$db->query("INSERT INTO `license_keys` (`key`, `privilege`, `note`) VALUES (?, 1, ?)", "ss", $key, $argv[1]);
|
||||
echo "Stand-$key\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
13
Server Software/keygen/gen_regular.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require "common.php";
|
||||
|
||||
echo "--- Regular ---\n\n";
|
||||
|
||||
for($i = 0; $i < $argv[2]; $i++)
|
||||
{
|
||||
$key = generateKey(30);
|
||||
$db->query("INSERT INTO `license_keys` (`key`, `privilege`, `note`) VALUES (?, 2, ?)", "ss", $key, $argv[1]);
|
||||
echo "Stand-$key\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
13
Server Software/keygen/gen_ultimate.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require "common.php";
|
||||
|
||||
echo "--- Ultimate ---\n\n";
|
||||
|
||||
for($i = 0; $i < $argv[2]; $i++)
|
||||
{
|
||||
$key = generateKey(30);
|
||||
$db->query("INSERT INTO `license_keys` (`key`, `privilege`, `note`) VALUES (?, 3, ?)", "ss", $key, $argv[1]);
|
||||
echo "Stand-$key\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
13
Server Software/keygen/gen_upgrade_basic_to_regular.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require "common.php";
|
||||
|
||||
echo "--- Basic To Regular ---\n\n";
|
||||
|
||||
for($i = 0; $i < $argv[2]; $i++)
|
||||
{
|
||||
$key = generateKey(31);
|
||||
$db->query("INSERT INTO `upgrades` (`key`, `privilege_from`, `privilege_to`, `note`) VALUES (?, 1, 2, ?)", "ss", $key, $argv[1]);
|
||||
echo "Stand-Upgrade-$key\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
13
Server Software/keygen/gen_upgrade_basic_to_ultimate.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require "common.php";
|
||||
|
||||
echo "--- Basic To Ultimate ---\n\n";
|
||||
|
||||
for($i = 0; $i < $argv[2]; $i++)
|
||||
{
|
||||
$key = generateKey(31);
|
||||
$db->query("INSERT INTO `upgrades` (`key`, `privilege_from`, `privilege_to`, `note`) VALUES (?, 1, 3, ?)", "ss", $key, $argv[1]);
|
||||
echo "Stand-Upgrade-$key\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
13
Server Software/keygen/gen_upgrade_regular_to_ultimate.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require "common.php";
|
||||
|
||||
echo "--- Regular To Ultimate ---\n\n";
|
||||
|
||||
for($i = 0; $i < $argv[2]; $i++)
|
||||
{
|
||||
$key = generateKey(31);
|
||||
$db->query("INSERT INTO `upgrades` (`key`, `privilege_from`, `privilege_to`, `note`) VALUES (?, 2, 3, ?)", "ss", $key, $argv[1]);
|
||||
echo "Stand-Upgrade-$key\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
16
Server Software/keygen/omni.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
$note = $argv[1];
|
||||
|
||||
$basic = $argv[2] ?? 0;
|
||||
$regular = $argv[3] ?? 0;
|
||||
$ultimate = $argv[4] ?? 0;
|
||||
$basic_to_regular = $argv[5] ?? 0;
|
||||
$regular_to_ultimate = $argv[6] ?? 0;
|
||||
$basic_to_ultimate = $argv[7] ?? 0;
|
||||
|
||||
if($basic) passthru("php gen_basic.php \"$note\" $basic");
|
||||
if($regular) passthru("php gen_regular.php \"$note\" $regular");
|
||||
if($ultimate) passthru("php gen_ultimate.php \"$note\" $ultimate");
|
||||
if($basic_to_regular) passthru("php gen_upgrade_basic_to_regular.php \"$note\" $basic_to_regular");
|
||||
if($regular_to_ultimate) passthru("php gen_upgrade_regular_to_ultimate.php \"$note\" $regular_to_ultimate");
|
||||
if($basic_to_ultimate) passthru("php gen_upgrade_basic_to_ultimate.php \"$note\" $basic_to_ultimate");
|
159
Server Software/keygen/revoke.php
Normal file
@ -0,0 +1,159 @@
|
||||
<?php
|
||||
$keys = [
|
||||
];
|
||||
|
||||
require "common.php";
|
||||
|
||||
// Simplify keys
|
||||
foreach ($keys as $i => $key)
|
||||
{
|
||||
$keys[$i] = trim($key);
|
||||
}
|
||||
|
||||
// Initialise parameters for omni
|
||||
$note = NULL;
|
||||
$basic = 0;
|
||||
$regular = 0;
|
||||
$ultimate = 0;
|
||||
$basic_to_regular = 0;
|
||||
$regular_to_ultimate = 0;
|
||||
$basic_to_ultimate = 0;
|
||||
|
||||
// Utility functions
|
||||
function privilegeToString(int $priv): string
|
||||
{
|
||||
switch ($priv)
|
||||
{
|
||||
case 1: return "Basic";
|
||||
case 2: return "Regular";
|
||||
case 3: return "Ultimate";
|
||||
}
|
||||
return "Privilege $priv";
|
||||
}
|
||||
|
||||
function processNote($res)
|
||||
{
|
||||
global $note;
|
||||
if($note === NULL)
|
||||
{
|
||||
$note = $res[0]["note"];
|
||||
}
|
||||
else if ($note != $res[0]["note"])
|
||||
{
|
||||
echo "Unexpected note: ".$res[0]["note"].". Skipping.\n";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function collapseAccountId(string $acctid): string
|
||||
{
|
||||
return substr($acctid, 0, 6);
|
||||
}
|
||||
|
||||
// Iterate license keys
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (strlen($key) != 30)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
echo "Stand-".$key.": ";
|
||||
$res = $db->query("SELECT `privilege`,`note`,`used_by` FROM `license_keys` WHERE `key`=?", "s", $key);
|
||||
if(!$res)
|
||||
{
|
||||
echo "Not found.\n";
|
||||
continue;
|
||||
}
|
||||
echo privilegeToString($res[0]["privilege"]).". ";
|
||||
if (processNote($res))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if($account_id = $res[0]["used_by"])
|
||||
{
|
||||
echo "Used to create account ".collapseAccountId($account_id).". ";
|
||||
if ($suspended_for = $db->query("SELECT `suspended_for` FROM `accounts` WHERE `id`=?", "s", $account_id)[0]["suspended_for"])
|
||||
{
|
||||
echo "Suspended for $suspended_for. ";
|
||||
if ($suspended_for != "compromised account" && $suspended_for != "compromised account (T)")
|
||||
{
|
||||
echo "Skipping.\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$db->query("UPDATE `accounts` SET `suspended_for`='reseller revoke' WHERE `id`=?", "s", $account_id);
|
||||
echo "Revoked.\n";
|
||||
//$db->query("DELETE FROM `account_devices` WHERE `account_id`=?", "s", $account_id);
|
||||
//$db->query("DELETE FROM `account_discords` WHERE `account_id`=?", "s", $account_id);
|
||||
//$db->query("DELETE FROM `menus` WHERE `account_id`=?", "s", $account_id);
|
||||
//$db->query("DELETE FROM `accounts` WHERE `id`=?", "s", $account_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$db->query("DELETE FROM `license_keys` WHERE `key`=?", "s", $key);
|
||||
echo "Unused. Yeeted.\n";
|
||||
}
|
||||
|
||||
switch($res[0]["privilege"])
|
||||
{
|
||||
case 1: ++$basic; break;
|
||||
case 2: ++$regular; break;
|
||||
case 3: ++$ultimate; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate upgrade keys
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (strlen($key) != 31)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
echo "Stand-Upgrade-".$key.": ";
|
||||
$res = $db->query("SELECT `used_by`,`privilege_from`,`privilege_to`,`note` FROM `upgrades` WHERE `key`=?", "s", $key);
|
||||
if(!$res)
|
||||
{
|
||||
echo "Not found.\n";
|
||||
continue;
|
||||
}
|
||||
$typename = privilegeToString($res[0]["privilege_from"])." to ".privilegeToString($res[0]["privilege_to"]);
|
||||
echo $typename.". ";
|
||||
if (processNote($res))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if($account_id = $res[0]["used_by"])
|
||||
{
|
||||
echo "Used by account ".collapseAccountId($account_id).". ";
|
||||
if ($acct = $db->query("SELECT `privilege` FROM `accounts` WHERE `id`=?", "s", $account_id)[0])
|
||||
{
|
||||
$acctpriv = $acct["privilege"];
|
||||
if ($acctpriv != $res[0]["privilege_to"])
|
||||
{
|
||||
echo "Account is ".privilegeToString($acctpriv).". Skipping.\n";
|
||||
continue;
|
||||
}
|
||||
$db->query("UPDATE `accounts` SET `privilege`=? WHERE `id`=?", "is", $res[0]["privilege_from"], $account_id);
|
||||
echo "Downgraded.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Unused.\n";
|
||||
}
|
||||
$db->query("DELETE FROM `upgrades` WHERE `key`=?", "s", $key);
|
||||
|
||||
switch ($typename)
|
||||
{
|
||||
case "Basic to Regular": ++$basic_to_regular; break;
|
||||
case "Regular to Ultimate": ++$regular_to_ultimate; break;
|
||||
case "Basic to Ultimate": ++$basic_to_ultimate; break;
|
||||
}
|
||||
}
|
||||
|
||||
if($note !== NULL)
|
||||
{
|
||||
echo "Note: ".$note."\n";
|
||||
passthru("php omni.php \"$note\" $basic $regular $ultimate $basic_to_regular $regular_to_ultimate $basic_to_ultimate");
|
||||
}
|
27
Server Software/keygen/splitomni.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
$note = $argv[1];
|
||||
|
||||
$basic = $argv[2] ?? 0;
|
||||
$regular = $argv[3] ?? 0;
|
||||
$ultimate = $argv[4] ?? 0;
|
||||
$basic_to_regular = $argv[5] ?? 0;
|
||||
$regular_to_ultimate = $argv[6] ?? 0;
|
||||
$basic_to_ultimate = $argv[7] ?? 0;
|
||||
|
||||
if(!is_dir("out"))
|
||||
{
|
||||
mkdir("out");
|
||||
}
|
||||
|
||||
function generateToFile($what, $amount)
|
||||
{
|
||||
global $note;
|
||||
file_put_contents("out/".$what.".txt", shell_exec("php gen_$what.php \"$note\" $amount"));
|
||||
}
|
||||
|
||||
if($basic) generateToFile("basic", $basic);
|
||||
if($regular) generateToFile("regular", $regular);
|
||||
if($ultimate) generateToFile("ultimate", $ultimate);
|
||||
if($basic_to_regular) generateToFile("upgrade_basic_to_regular", $basic_to_regular);
|
||||
if($regular_to_ultimate) generateToFile("upgrade_regular_to_ultimate", $regular_to_ultimate);
|
||||
if($basic_to_ultimate) generateToFile("upgrade_basic_to_ultimate", $basic_to_ultimate);
|
1
Server Software/mailer/NOTE.md
Normal file
@ -0,0 +1 @@
|
||||
The hostname has been hardcoded in php-mail-transfer as it may randomly fail to resolve, and then trip shitty heuristics because of "bare IP HELO"
|
5
Server Software/mailer/composer.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"require": {
|
||||
"hell-sh/mail-transfer": "dev-senpai"
|
||||
}
|
||||
}
|
31
Server Software/mailer/send-mail.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
require "vendor/autoload.php";
|
||||
|
||||
$email = Email\Email::basic(
|
||||
new Email\Address("Your Brain Replacement <your-brain-replacement@stand.sh>"),
|
||||
new Email\Address($_POST["r"]),
|
||||
/* Subject: */ "Your Stand Account ID",
|
||||
new Email\ContentTextPlain("Your Stand Account ID: ".$_POST["i"]."\r\n\r\nDon't share this with anyone!\r\n\r\nLogin: https://stand.sh/account/login")
|
||||
)->sign(new Email\DkimKey("a", "file://".__DIR__."/dkim-private.pem"));
|
||||
|
||||
$con = $email->getRecipient()->createConnection(
|
||||
Email\Client::DEFAULT_CONNECT_TIMEOUT,
|
||||
Email\Client::DEFAULT_READ_TIMEOUT,
|
||||
Email\Connection::LOGFUNC_ECHO
|
||||
);
|
||||
|
||||
if($con instanceof Email\Connection)
|
||||
{
|
||||
$con->identify(function() use ($con, $email)
|
||||
{
|
||||
$con->sendEmail($email, function() use ($con)
|
||||
{
|
||||
$con->close();
|
||||
}, function(Email\Fail $fail) use ($con)
|
||||
{
|
||||
$con->close();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Asyncore\Asyncore::loop();
|
2
Server Software/relayserver/.sun
Normal file
@ -0,0 +1,2 @@
|
||||
+*.cpp
|
||||
require ../Soup/soup
|
1
Server Software/relayserver/cert.sh
Normal file
@ -0,0 +1 @@
|
||||
certbot certonly -m letsencrypt@sai.navy --agree-tos -d relay1.stand.gg --manual --preferred-challenges dns --force-interactive
|
71
Server Software/relayserver/cert/certplusissuer.pem
Normal file
@ -0,0 +1,71 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGLzCCBRegAwIBAgIRAILIyLcitteoEGcJt1QBXvcwDQYJKoZIhvcNAQELBQAw
|
||||
gY8xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
|
||||
BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UE
|
||||
AxMuU2VjdGlnbyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
|
||||
QTAeFw0yNDA4MDIwMDAwMDBaFw0yNTA4MDIyMzU5NTlaMBcxFTATBgNVBAMMDCou
|
||||
dmlhdGxzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTToSjY
|
||||
3aUIxjghIkikJfFExVwSEzIM2XaQNJE+SxQ6Cc+xUR5QJrMJnM/39sH5c5imMEUo
|
||||
2OnstCIaVMPx5ZPN+HXLsvmoVAe2/xYe7emnZ5ZFTUXPyqkzDRg0hkMJiWWo/Nmf
|
||||
ypZfUJoz6hVkXwsgNFPTVuo7aECQFlZslh2HQVDOfBaNBxQBaOJ5vf6nllf/aLyB
|
||||
tZ74nlLynVYV9kYzISP4dUcxQ+D4HZgIxyOQfcN3EHUS1ZVaIp8hupOygF8zGQyJ
|
||||
uzFozzg5I59U+hT1yQG3FlwTBnP+sA0+hW0LBTbWSISm0If1SgHlUEqxLlosjuTG
|
||||
BG45h9o2bAz9po0CAwEAAaOCAvswggL3MB8GA1UdIwQYMBaAFI2MXsRUrYrhd+mb
|
||||
+ZsF4bgBjWHhMB0GA1UdDgQWBBQ/OeA2gLbVIKIuIitYRqSRUWMP3TAOBgNVHQ8B
|
||||
Af8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
|
||||
BQUHAwIwSQYDVR0gBEIwQDA0BgsrBgEEAbIxAQICBzAlMCMGCCsGAQUFBwIBFhdo
|
||||
dHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZngQwBAgEwgYQGCCsGAQUFBwEBBHgw
|
||||
djBPBggrBgEFBQcwAoZDaHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNB
|
||||
RG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAjBggrBgEFBQcwAYYX
|
||||
aHR0cDovL29jc3Auc2VjdGlnby5jb20wIwYDVR0RBBwwGoIMKi52aWF0bHMuY29t
|
||||
ggp2aWF0bHMuY29tMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdQDd3Mo0ldfh
|
||||
FgXnlTL6x5/4PRxQ39sAOhQSdgosrLvIKgAAAZEVLi9VAAAEAwBGMEQCIGiZNOV7
|
||||
IvcHKU7nEaxFgWPpUu2CxyULg1ueJTYwTT12AiAJWQv3RrqCtOJC7JEdztILs3Bn
|
||||
an9s0Bf93uOE4C/LiAB3AA3h8jAr0w3BQGISCepVLvxHdHyx1+kw7w5CHrR+Tqo0
|
||||
AAABkRUuLxAAAAQDAEgwRgIhAOhlC+IpJV3uAaDCRXi6RZ+V8++QaLaTEtqFp2UP
|
||||
yWeSAiEA8qtGDk1RE1VGwQQcJCf3CBYU5YTlsZNi7F6hEONLuzMAdwAS8U40vVNy
|
||||
TIQGGcOPP3oT+Oe1YoeInG0wBYTr5YYmOgAAAZEVLi7kAAAEAwBIMEYCIQDWCnSm
|
||||
N+2/xxo8bl3pbpNBEBZZIwnYPQW0A+SJ0+dboQIhANjH2L0xV/+rPuPMzK40vk3J
|
||||
1fWHLocLjpgaxGhsBAOzMA0GCSqGSIb3DQEBCwUAA4IBAQBcObVjc1zFdOER50ZF
|
||||
mI+WyVF8t6nV6dm3zIDraLA4++zKUu9UKNJm9YPqLdPP7uTLHz6wuBNmyuWPdF0r
|
||||
qAf4vsK3tcAds7kjK8injewEUCPG20mtNMUHyhlNEOJR2ySPPQ6Q+t+TtGAnimKa
|
||||
Zr86quYgYaJYhoEEXcbB9fMoDQYlJDzgT2DXvfM4cyoden2tYZ3gQS6ftiXacBe0
|
||||
WzFWYZ8mIP2Kb+D9tCapB9MVUzu3XJVy3S2FLQEWcWIvjnpad73a0/35i/nro6/k
|
||||
TSK+MKBEBaNZuHJ8ubCToo1BftnsS8HuEPTNe8W1hyc2YmT9f5YQP6HWB2rxjH42
|
||||
OTXh
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
|
||||
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
|
||||
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
|
||||
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
|
||||
MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBjzELMAkGA1UEBhMCR0IxGzAZBgNV
|
||||
BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE
|
||||
ChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFJTQSBEb21haW4g
|
||||
VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEA1nMz1tc8INAA0hdFuNY+B6I/x0HuMjDJsGz99J/LEpgPLT+N
|
||||
TQEMgg8Xf2Iu6bhIefsWg06t1zIlk7cHv7lQP6lMw0Aq6Tn/2YHKHxYyQdqAJrkj
|
||||
eocgHuP/IJo8lURvh3UGkEC0MpMWCRAIIz7S3YcPb11RFGoKacVPAXJpz9OTTG0E
|
||||
oKMbgn6xmrntxZ7FN3ifmgg0+1YuWMQJDgZkW7w33PGfKGioVrCSo1yfu4iYCBsk
|
||||
Haswha6vsC6eep3BwEIc4gLw6uBK0u+QDrTBQBbwb4VCSmT3pDCg/r8uoydajotY
|
||||
uK3DGReEY+1vVv2Dy2A0xHS+5p3b4eTlygxfFQIDAQABo4IBbjCCAWowHwYDVR0j
|
||||
BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFI2MXsRUrYrhd+mb
|
||||
+ZsF4bgBjWHhMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
|
||||
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAbBgNVHSAEFDASMAYGBFUdIAAw
|
||||
CAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0
|
||||
LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2Bggr
|
||||
BgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNv
|
||||
bS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDov
|
||||
L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMr9hvQ5Iw0/H
|
||||
ukdN+Jx4GQHcEx2Ab/zDcLRSmjEzmldS+zGea6TvVKqJjUAXaPgREHzSyrHxVYbH
|
||||
7rM2kYb2OVG/Rr8PoLq0935JxCo2F57kaDl6r5ROVm+yezu/Coa9zcV3HAO4OLGi
|
||||
H19+24rcRki2aArPsrW04jTkZ6k4Zgle0rj8nSg6F0AnwnJOKf0hPHzPE/uWLMUx
|
||||
RP0T7dWbqWlod3zu4f+k+TY4CFM5ooQ0nBnzvg6s1SQ36yOoeNDT5++SR2RiOSLv
|
||||
xvcRviKFxmZEJCaOEDKNyJOuB56DPi/Z+fVGjmO+wea03KbNIaiGCpXZLoUmGv38
|
||||
sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
|
||||
l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
|
||||
6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
|
||||
LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
|
||||
yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
|
||||
00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
|
||||
-----END CERTIFICATE-----
|
28
Server Software/relayserver/cert/privkey.pem
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDE06Eo2N2lCMY4
|
||||
ISJIpCXxRMVcEhMyDNl2kDSRPksUOgnPsVEeUCazCZzP9/bB+XOYpjBFKNjp7LQi
|
||||
GlTD8eWTzfh1y7L5qFQHtv8WHu3pp2eWRU1Fz8qpMw0YNIZDCYllqPzZn8qWX1Ca
|
||||
M+oVZF8LIDRT01bqO2hAkBZWbJYdh0FQznwWjQcUAWjieb3+p5ZX/2i8gbWe+J5S
|
||||
8p1WFfZGMyEj+HVHMUPg+B2YCMcjkH3DdxB1EtWVWiKfIbqTsoBfMxkMibsxaM84
|
||||
OSOfVPoU9ckBtxZcEwZz/rANPoVtCwU21kiEptCH9UoB5VBKsS5aLI7kxgRuOYfa
|
||||
NmwM/aaNAgMBAAECggEAEYK8bzxf96tAq0SzXqAP6heSsV7AS28eN7CbpKJUnp+N
|
||||
OOePDnHWB46e31exoc82DAoY+EYqiiEvY2tRSD9wi8ZCyQQOz6w8kZUju42T3/ov
|
||||
Ooy+06upXYU3sIQXv8YM7bjridbv+JHRQ27D8BRGamB6l0yRinQvkbLf8d9mOYkj
|
||||
P5yYrpMPV/mfgkCir/aBlGOzmI+CuOv7FdF9DIz2OehtPXOzbExuab4xOQ4NQrN9
|
||||
TfzWWS798D86e5uDx+Ab0pfege8IJvEBjU5ngZo3aeS/F5i2us+BXImu1P6IrYdb
|
||||
ekXUo9VJPEHiD02iyLW/gFz3/AsWa3ztinXN0I069wKBgQD7yGPX6LG7MXlXEqL2
|
||||
DuCrFsKzVC4z0c/cpPXO8Xb8rGzvHR7Oa0i5Bo7i5wRiVXS87HT25iZmB78yjKnI
|
||||
bVmWA3tVWInx6fixbZUO7L4D/Q1Ddfin/DiXyNpAhKii0QgpD61P7HJnrfnwUar5
|
||||
Vpwd2grnPNCbuILZxAZhtIXRnwKBgQDIH5hmyiIUAvrz+4UpE55ecxTMOkj0+Pgx
|
||||
79KpSjXfEIk5V7UmCSk1SusQWq8Ri9d6QqPcTptVhxmC/geolp9bCW14JdORbjNv
|
||||
5+3JfAwgZJtbDP4l3GKf168fLQXzSpWCW3vT1lCBz4x4nNs2EudTdDCn5aUVLGEJ
|
||||
v15Iz0dQUwKBgHuZh8n55SXrx5FDCNSZwRi796Bo9rVhjhTWtgR87NhlHKTVOsZC
|
||||
TFToL0Sb+776DHCh81kw6jC0JNv/yWkmpQ/LbcQbzrv/C6KuFLpa5Xy3wMcZJpPw
|
||||
cSex5dI+TTqAOu1NUNsnS5IyCbw7mx8DsWfGHgweApovHa0hWbClGfwpAoGAfSt9
|
||||
6DTfkcK3cilMhX+2236BcKe4ADlFC/7jtW0sOsQeAFbCf/LU6ndchVMjEwdzlA3g
|
||||
bahg8eLZaxw2cBUdwRQpey+1n83csE7RZOeIsi4bGZ0LzWSF71I5P3eqtBxfXTSZ
|
||||
Q8tVeYv2YW5CkhTKyWDwGePCGHc0jqM6drHm+e8CgYEA+IkvplnK76zx3M579TpI
|
||||
M2ffiC2b12FtJMpgnNrk6HZ19o2mhbte/7wf9SHVqsRw4V7/n6rzBJ5wzEHOWre7
|
||||
7PrkLgS0mY2SRfMmeT74m59dA8GpvhBUW/Xa4wlDtZkU2iIcDkKnYLjgrTKjlK86
|
||||
ER+evzmHeTqYJzuK8Mfq93I=
|
||||
-----END PRIVATE KEY-----
|
259
Server Software/relayserver/relayserver.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <HttpRequest.hpp>
|
||||
#include <netConfig.hpp>
|
||||
#include <pem.hpp>
|
||||
#include <Promise.hpp>
|
||||
#include <Scheduler.hpp>
|
||||
#include <Server.hpp>
|
||||
#include <ServerWebService.hpp>
|
||||
#include <Socket.hpp>
|
||||
#include <string.hpp>
|
||||
#include <TlsServerRsaData.hpp>
|
||||
#include <WebSocketMessage.hpp>
|
||||
|
||||
struct RelayClientData
|
||||
{
|
||||
bool is_mod = false;
|
||||
std::string key{};
|
||||
std::string line_buf{};
|
||||
};
|
||||
|
||||
static soup::Server serv{};
|
||||
|
||||
[[nodiscard]] static soup::Socket* getSocket(bool mod, const std::string& key)
|
||||
{
|
||||
for (const auto& w : serv.workers)
|
||||
{
|
||||
auto s = reinterpret_cast<soup::Socket*>(w.get());
|
||||
RelayClientData& cd = s->custom_data.getStructFromMap(RelayClientData);
|
||||
if (cd.is_mod == mod
|
||||
&& cd.key == key
|
||||
)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] static soup::Socket* getMod(const std::string& key)
|
||||
{
|
||||
return getSocket(true, key);
|
||||
}
|
||||
|
||||
[[nodiscard]] static soup::Socket* getWeb(const std::string& key)
|
||||
{
|
||||
return getSocket(false, key);
|
||||
}
|
||||
|
||||
static void handleDisconnect(soup::Socket& s)
|
||||
{
|
||||
RelayClientData& cd = s.custom_data.getStructFromMap(RelayClientData);
|
||||
if (!cd.key.empty())
|
||||
{
|
||||
if (cd.is_mod)
|
||||
{
|
||||
if (auto ws = getWeb(cd.key))
|
||||
{
|
||||
soup::ServerWebService::wsSend(*ws, "lost_mod", true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto ms = getMod(cd.key))
|
||||
{
|
||||
ms->send("lost_web\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void modRecvLoop(soup::Socket& s) SOUP_EXCAL
|
||||
{
|
||||
s.recv([](soup::Socket& s, std::string&& data, soup::Capture&&) SOUP_EXCAL
|
||||
{
|
||||
RelayClientData& cd = s.custom_data.getStructFromMap(RelayClientData);
|
||||
if (!cd.key.empty())
|
||||
{
|
||||
cd.line_buf.append(data);
|
||||
auto off = cd.line_buf.find('\n');
|
||||
if (off != std::string::npos)
|
||||
{
|
||||
if (auto ws = getWeb(cd.key))
|
||||
{
|
||||
do
|
||||
{
|
||||
soup::ServerWebService::wsSend(*ws, cd.line_buf.substr(0, off), true);
|
||||
cd.line_buf.erase(0, off + 1);
|
||||
} while (off = cd.line_buf.find('\n'), off != std::string::npos);
|
||||
}
|
||||
}
|
||||
modRecvLoop(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static soup::TlsServerRsaData server_rsa_data;
|
||||
|
||||
static void cert_selector(soup::TlsServerRsaData& out, const std::string& server_name) SOUP_EXCAL
|
||||
{
|
||||
out = server_rsa_data;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
server_rsa_data.der_encoded_certchain = soup::pem::decodeChain(soup::string::fromFile("cert/certplusissuer.pem"));
|
||||
server_rsa_data.private_key = soup::RsaPrivateKey::fromPem(soup::string::fromFile("cert/privkey.pem"));
|
||||
|
||||
serv.on_work_done = [](soup::Worker& w, soup::Scheduler&)
|
||||
{
|
||||
soup::Socket& s = reinterpret_cast<soup::Socket&>(w);
|
||||
std::cout << s.peer.toString() << " - work done" << std::endl;
|
||||
handleDisconnect(s);
|
||||
};
|
||||
serv.on_connection_lost = [](soup::Socket& s, soup::Scheduler&)
|
||||
{
|
||||
std::cout << s.peer.toString() << " - connection lost" << std::endl;
|
||||
handleDisconnect(s);
|
||||
};
|
||||
serv.on_exception = [](soup::Worker& w, const std::exception& e, soup::Scheduler&)
|
||||
{
|
||||
soup::Socket& s = reinterpret_cast<soup::Socket&>(w);
|
||||
std::cout << s.peer.toString() << " - exception: " << e.what() << std::endl;
|
||||
handleDisconnect(s);
|
||||
};
|
||||
|
||||
soup::ServerService stand_srv{
|
||||
[](soup::Socket& s, soup::ServerService&, soup::Server&) SOUP_EXCAL
|
||||
{
|
||||
std::cout << s.peer.toString() << " + mod connection established" << std::endl;
|
||||
s.send("Go ahead\n");
|
||||
s.recv([](soup::Socket& s, std::string&& data, soup::Capture&&) SOUP_EXCAL
|
||||
{
|
||||
std::cout << s.peer.toString() << " > " << data << std::endl;
|
||||
if (data.substr(0, 6) == "Stand:")
|
||||
{
|
||||
if (data.substr(6, 2) != "1:")
|
||||
{
|
||||
s.send("notify_above_map Your version of Stand is not supported by this relay.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string key = data.substr(8);
|
||||
if (auto ms = getMod(key))
|
||||
{
|
||||
ms->custom_data.getStructFromMap(RelayClientData).key.clear();
|
||||
ms->close();
|
||||
}
|
||||
RelayClientData& cd = s.custom_data.getStructFromMap(RelayClientData);
|
||||
cd.is_mod = true;
|
||||
cd.key = key;
|
||||
auto p = soup::make_unique<soup::Promise<bool>>([](soup::Capture&& cap) -> bool
|
||||
{
|
||||
// This takes too long if we actually validate the cert
|
||||
soup::netConfig::get().certchain_validator = &soup::Socket::certchain_validator_none;
|
||||
|
||||
std::string path = "internal_get_privilege/?0=";
|
||||
path.append(cap.get<std::string>());
|
||||
soup::HttpRequest req{ "backend-services.stand.sh", std::move(path) };
|
||||
auto res = req.execute();
|
||||
if (!res.has_value())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return soup::string::toInt<uint8_t>(res->body) >= 2;
|
||||
}, std::move(key));
|
||||
soup::PromiseBase* pp = p.get();
|
||||
s.awaitPromiseCompletion(pp, [](soup::Worker& w, soup::Capture&& cap)
|
||||
{
|
||||
auto& p = cap.get<soup::UniquePtr<soup::Promise<bool>>>();
|
||||
if (p.get() && p->getResult())
|
||||
{
|
||||
soup::Socket& s = reinterpret_cast<soup::Socket&>(w);
|
||||
if (auto ws = getWeb(s.custom_data.getStructFromMap(RelayClientData).key))
|
||||
{
|
||||
s.send("got_web\n");
|
||||
}
|
||||
modRecvLoop(s);
|
||||
}
|
||||
}, std::move(p));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
soup::ServerWebService web_srv{
|
||||
[](soup::Socket& s, soup::HttpRequest&& req, soup::ServerWebService&)
|
||||
{
|
||||
soup::ServerWebService::disableKeepAlive(s);
|
||||
soup::ServerWebService::sendText(s, ":)");
|
||||
}
|
||||
};
|
||||
web_srv.on_connection_established = [](soup::Socket& s, soup::ServerService&, soup::Server&) SOUP_EXCAL
|
||||
{
|
||||
std::cout << s.peer.toString() << " + web connection established" << std::endl;
|
||||
};
|
||||
web_srv.should_accept_websocket_connection = [](soup::Socket& s, const soup::HttpRequest& req, soup::ServerWebService&) SOUP_EXCAL
|
||||
{
|
||||
std::cout << s.peer.toString() << " > WEBSOCKET " << req.path << std::endl;
|
||||
return true;
|
||||
};
|
||||
web_srv.on_websocket_message = [](soup::WebSocketMessage& msg, soup::Socket& s, soup::ServerWebService&)
|
||||
{
|
||||
RelayClientData& cd = s.custom_data.getStructFromMap(RelayClientData);
|
||||
if (cd.key.empty())
|
||||
{
|
||||
if (msg.data.substr(0, 8) == "license ")
|
||||
{
|
||||
auto key = msg.data.substr(8);
|
||||
if (auto ws = getWeb(key))
|
||||
{
|
||||
ws->custom_data.getStructFromMap(RelayClientData).key.clear();
|
||||
ws->close();
|
||||
}
|
||||
cd.key = std::move(key);
|
||||
if (auto ms = getMod(cd.key))
|
||||
{
|
||||
ms->send("got_web\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
soup::ServerWebService::wsSend(s, "no_mod", true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msg.data.substr(0, 2) == "p "
|
||||
|| msg.data.substr(0, 2) == "k "
|
||||
|| msg.data.substr(0, 2) == "c "
|
||||
|| msg.data.substr(0, 2) == "s "
|
||||
)
|
||||
{
|
||||
if (auto ms = getMod(cd.key))
|
||||
{
|
||||
msg.data.push_back('\n');
|
||||
ms->send(std::move(msg.data));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
s.close();
|
||||
};
|
||||
|
||||
if (!serv.bind(25769, &stand_srv))
|
||||
{
|
||||
std::cout << "Failed to bind to port 25769." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (!serv.bindCrypto(4269, &web_srv, &cert_selector))
|
||||
{
|
||||
std::cout << "Failed to bind to port 4269." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
std::cout << "Listening on ports 25769 and 4269." << std::endl;
|
||||
serv.run();
|
||||
}
|
3
Server Software/relayserver/start.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
screen -dmS "relayserver" ./relayserver
|
8
Server Software/vpn-node-tools/renew.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
$myhostname = gethostbyaddr(file_get_contents("https://ipv4.apimon.de/"));
|
||||
echo "Detected hostname: $myhostname\n";
|
||||
|
||||
passthru("certbot certonly -m letsencrypt@sai.navy --agree-tos -d $myhostname --manual --preferred-challenges dns");
|
||||
copy("/etc/letsencrypt/live/$myhostname/chain.pem", "/etc/ipsec.d/cacerts/chain.pem");
|
||||
|
||||
passthru("ipsec reload");
|
6
Server Software/vpn-node-tools/run.sh
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
while true
|
||||
do
|
||||
php vpn-auth-updater.php
|
||||
done
|
74
Server Software/vpn-node-tools/setup.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
$myhostname = gethostbyaddr(file_get_contents("https://ipv4.apimon.de/"));
|
||||
echo "Detected hostname: $myhostname\n";
|
||||
|
||||
passthru("apt-get install -y php-cli php-curl screen certbot strongswan strongswan-pki libcharon-extra-plugins libcharon-extauth-plugins libstrongswan-extra-plugins");
|
||||
|
||||
passthru("certbot certonly -m letsencrypt@sai.navy --agree-tos -d $myhostname --manual --preferred-challenges dns");
|
||||
copy("/etc/letsencrypt/live/$myhostname/chain.pem", "/etc/ipsec.d/cacerts/chain.pem");
|
||||
|
||||
file_put_contents("/etc/ipsec.conf", str_replace("\r", "", <<<EOC
|
||||
# ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
charondebug="ike 0, enc 0, net 0, cfg 0"
|
||||
uniqueids=no
|
||||
|
||||
conn ikev2-vpn
|
||||
auto=add
|
||||
compress=no
|
||||
type=tunnel
|
||||
keyexchange=ikev2
|
||||
fragmentation=yes
|
||||
forceencaps=yes
|
||||
dpdaction=clear
|
||||
dpddelay=300s
|
||||
ike=chacha20poly1305-sha512-curve25519-prfsha512,aes256gcm16-sha384-prfsha384-ecp384,aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024
|
||||
esp=chacha20poly1305-sha512,aes256gcm16-ecp384,aes256-sha256,aes256-sha1,3des-sha1
|
||||
rekey=no
|
||||
left=%any
|
||||
leftid=@$myhostname
|
||||
leftauth=pubkey
|
||||
leftcert=/etc/letsencrypt/live/$myhostname/cert.pem
|
||||
leftsendcert=always
|
||||
leftsubnet=0.0.0.0/0
|
||||
right=%any
|
||||
rightid=%any
|
||||
rightauth=eap-mschapv2
|
||||
rightsendcert=never
|
||||
rightsourceip=13.37.0.0/16
|
||||
eap_identity=%identity
|
||||
|
||||
EOC));
|
||||
|
||||
file_put_contents("/etc/strongswan.conf", str_replace("\r", "", <<<EOC
|
||||
# strongswan.conf - strongSwan configuration file
|
||||
#
|
||||
# Refer to the strongswan.conf(5) manpage for details
|
||||
#
|
||||
# Configuration changes should be made in the included files
|
||||
|
||||
charon {
|
||||
load_modular = yes
|
||||
plugins {
|
||||
include strongswan.d/charon/*.conf
|
||||
}
|
||||
dns1 = 8.8.8.8
|
||||
dns2 = 1.1.1.1
|
||||
nbns1 = 8.8.8.8
|
||||
nbns2 = 1.1.1.1
|
||||
}
|
||||
|
||||
include strongswan.d/*.conf
|
||||
|
||||
EOC));
|
||||
|
||||
file_put_contents("/etc/sysctl.conf", file_get_contents("/etc/sysctl.conf")."\nnet.ipv4.ip_forward=1\nnet.ipv4.conf.all.accept_redirects = 0\nnet.ipv4.conf.all.send_redirects = 0\nnet.ipv4.ip_no_pmtu_disc = 1\n");
|
||||
passthru("sysctl -w net.ipv4.ip_forward=1");
|
||||
passthru("sysctl -w net.ipv4.conf.all.accept_redirects=0");
|
||||
passthru("sysctl -w net.ipv4.conf.all.send_redirects=0");
|
||||
passthru("sysctl -w net.ipv4.ip_no_pmtu_disc=1");
|
||||
|
||||
passthru("ipsec restart");
|
||||
|
||||
passthru("sh start.sh");
|
8
Server Software/vpn-node-tools/setup.sh
Normal file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
apt-get update
|
||||
apt-get remove -y man-db apparmor
|
||||
apt-get upgrade -y
|
||||
apt-get install -y php-cli php-curl screen certbot strongswan strongswan-pki libcharon-extra-plugins libcharon-extauth-plugins libstrongswan-extra-plugins iptables
|
||||
|
||||
php setup.php
|
5
Server Software/vpn-node-tools/start.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
screen -dmS "auth-servant" sh run.sh
|
59
Server Software/vpn-node-tools/vpn-auth-updater.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
$myhostname = gethostbyaddr(file_get_contents("https://ipv4.apimon.de/"));
|
||||
$last_users = "";
|
||||
|
||||
echo "$myhostname is up and running!\n";
|
||||
|
||||
function getNumConnections()
|
||||
{
|
||||
foreach(explode("\n", shell_exec("ipsec statusall")) as $line)
|
||||
{
|
||||
if(substr($line, 0, 23) == "Security Associations (")
|
||||
{
|
||||
return intval(substr($line, 23));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
$clients = getNumConnections();
|
||||
echo "Syncing at $clients clients...";
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => "https://stand.gg/vpn/authsync",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query([
|
||||
"key" => '#8%o6!nLGFZE8fNBS89$SjHrr59bL!Ra$vu4JD7n44NrKkt8Tx3^fohfUVh8pwD9FkiX&%@E',
|
||||
"hostname" => $myhostname,
|
||||
"clients" => $clients,
|
||||
])
|
||||
]);
|
||||
$users = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
if($users == $last_users)
|
||||
{
|
||||
echo " Still up-to-date.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$last_users = $users;
|
||||
$users = explode(",", $users);
|
||||
$c = count($users);
|
||||
if($c == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
echo " Need update, remote reports ".$c." users...";
|
||||
$cont = ": RSA /etc/letsencrypt/live/$myhostname/privkey.pem\n\n";
|
||||
foreach($users as $user)
|
||||
{
|
||||
$cont .= "Stand-Activate-{$user} : EAP \"a\"\n";
|
||||
}
|
||||
file_put_contents("/etc/ipsec.secrets", $cont);
|
||||
shell_exec("ipsec rereadsecrets");
|
||||
echo " Done.\n";
|
||||
}
|
||||
sleep(5 * 60);
|
||||
}
|
BIN
Special Characters/U+0000.png
Normal file
After Width: | Height: | Size: 178 B |
BIN
Special Characters/U+1F480.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
Special Characters/U+1F4AF.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
Special Characters/U+1F525.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
Special Characters/U+1F602.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
Special Characters/U+1F60A.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
Special Characters/U+1F629.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
Special Characters/U+1F633.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
Special Characters/U+26A0.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Special Characters/U+2728.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
Special Characters/U+2764.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
Special Characters/blankbox.png
Normal file
After Width: | Height: | Size: 374 B |
BIN
Special Characters/lock.png
Normal file
After Width: | Height: | Size: 348 B |
BIN
Special Characters/newline.png
Normal file
After Width: | Height: | Size: 349 B |
BIN
Special Characters/reset.png
Normal file
After Width: | Height: | Size: 660 B |
BIN
Special Characters/rs-created.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Special Characters/rs-verified.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Special Characters/rs.png
Normal file
After Width: | Height: | Size: 636 B |
BIN
Special Characters/ws.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
76
Stand.cv
Normal file
@ -0,0 +1,76 @@
|
||||
[SECURE_ENGINE]
|
||||
SOFTWARE_NAME=Stand
|
||||
ADVANCED_OPTIONS_NUMBER=0
|
||||
OPTION_MACROS_MAP_FUNCTIONS_NUMBER=27
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_0=soup::RsaPublicKeyBase<struct soup::RsaPublicKey>::verify<struct soup::sha1>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class soup::Bigint const &)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_0=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_1=soup::sha1::State::finalise(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_1=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_2=soup::sha1::State::getDigest(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_2=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_3=soup::sha1::State::getDigest(unsigned char * const)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_3=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_4=Stand::AntiDbg::getRunningDebuggerId(bool)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_4=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_5=Stand::Auth::verifyPermSig(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_5=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_6=Stand::gotPermSigJob(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_6=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_7=Stand::processConnectionError(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_7=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_8=Stand::Auth::processHeartbeatResponse(__int64,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &&)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_8=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_9=Stand::Auth::discoverActivationKey(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_9=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_10=Stand::Auth::sendHeartbeat(unsigned __int64)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_10=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_11=Stand::Auth::reportEvent(struct Stand::Codename const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_11=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_12=Stand::Auth::processEventResponse(struct soup::HttpResponse &&)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_12=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_13=Stand::Auth::logOutManual(class Stand::Click &)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_13=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_14=Stand::logOut_job(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_14=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_15=Stand::Click::isBasicEdition(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_15=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_16=Stand::Click::isRegularEdition(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_16=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_17=Stand::Click::isRegularEditionOrSp(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_17=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_18=Stand::Click::isUltimateEdition(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_18=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_19=Stand::lua_menu_get_edition(struct lua_State *)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_19=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_20=Stand::ComponentCrashPatch::addPatterns(class Stand::PatternBatch &)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_20=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_21=Stand::activatePaste_onClick(class Stand::Click &)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_21=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_22=Stand::get_root_list(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_22=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_23=Stand::onDllAttach(struct HINSTANCE__ *)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_23=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_24=Stand::mainRunningLoopIteration(struct Stand::RunningLoopState &)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_24=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_25=Stand::yeet_job(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_25=0x00000000
|
||||
OPTION_MACROS_MAP_FUNCTION_NAME_AT_26=Stand::yeet_now(void)
|
||||
OPTION_MACROS_MAP_FUNCTION_TYPE_AT_26=0x00000000
|
||||
OPTION_MACROS_DISABLE_AT_RVA_NUMBER=0
|
||||
OPTION_VIRTUAL_MACHINE_NUMBER=1
|
||||
OPTION_VIRTUAL_MACHINE_ID_AT_0=0x2C27C001
|
||||
OPTION_VIRTUAL_MACHINE_CPUS_AT_0=1
|
||||
OPTION_VIRTUAL_MACHINE_PROTECTION_BOOT_ID=0x2C27C001
|
||||
OPTION_VIRTUAL_MACHINE_OLD_VM_MACROS_ID=0x2C27C001
|
||||
INPUT_FILE_NAME=Stand\bin\Release\Stand_unprotected.dll
|
||||
OUTPUT_FILE_NAME=Stand\bin\Release\Stand_uncompressed.dll
|
||||
OPTION_PROTECTION_INSERT_IN_NEW_SECTION=false
|
||||
OPTION_PROTECTION_INSERT_IN_LAST_SECTION=true
|
||||
OPTION_PROTECTION_INSERT_IN_STEALTH_AREA=false
|
||||
OPTION_MACROS_ENCRYPT_ANSI_STRINGS=false
|
||||
OPTION_MACROS_ENCRYPT_UNICODE_STRINGS=false
|
||||
OPTION_PROTECTION_IS_ENTRYPOINT_OBFUSCATION=true
|
||||
OPTION_COMPRESSION_COMPRESS_SECUREENGINE=false
|
||||
OPTION_PROTECTION_STRIP_RELOCS=false
|
||||
OPTION_PROTECTION_IS_OPTIMIZE_WINDOWS_ARM=true
|
||||
|
55
Stand.sln
Normal file
@ -0,0 +1,55 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32328.378
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stand", "Stand\Stand.vcxproj", "{BAF9F07A-2664-A5F1-6FA2-5697DB4B8346}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{715E3842-0D57-4068-BA22-9D4FA46DE633} = {715E3842-0D57-4068-BA22-9D4FA46DE633}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScriptHookV", "ScriptHookV\ScriptHookV.vcxproj", "{01FE0637-6BCC-4ADA-B0DD-7B7FF09541A2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ISaidNoRTTI", "ISaidNoRTTI\ISaidNoRTTI.vcxproj", "{874EB20E-DF0C-4496-9325-27476BF86E48}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Third-Party Libraries", "Stand\lib\Third-Party Libraries.vcxproj", "{715E3842-0D57-4068-BA22-9D4FA46DE633}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Dev Build|x64 = Dev Build|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BAF9F07A-2664-A5F1-6FA2-5697DB4B8346}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BAF9F07A-2664-A5F1-6FA2-5697DB4B8346}.Debug|x64.Build.0 = Debug|x64
|
||||
{BAF9F07A-2664-A5F1-6FA2-5697DB4B8346}.Dev Build|x64.ActiveCfg = Dev Build|x64
|
||||
{BAF9F07A-2664-A5F1-6FA2-5697DB4B8346}.Dev Build|x64.Build.0 = Dev Build|x64
|
||||
{BAF9F07A-2664-A5F1-6FA2-5697DB4B8346}.Release|x64.ActiveCfg = Release|x64
|
||||
{BAF9F07A-2664-A5F1-6FA2-5697DB4B8346}.Release|x64.Build.0 = Release|x64
|
||||
{01FE0637-6BCC-4ADA-B0DD-7B7FF09541A2}.Debug|x64.ActiveCfg = Release|x64
|
||||
{01FE0637-6BCC-4ADA-B0DD-7B7FF09541A2}.Debug|x64.Build.0 = Release|x64
|
||||
{01FE0637-6BCC-4ADA-B0DD-7B7FF09541A2}.Dev Build|x64.ActiveCfg = Release|x64
|
||||
{01FE0637-6BCC-4ADA-B0DD-7B7FF09541A2}.Dev Build|x64.Build.0 = Release|x64
|
||||
{01FE0637-6BCC-4ADA-B0DD-7B7FF09541A2}.Release|x64.ActiveCfg = Release|x64
|
||||
{01FE0637-6BCC-4ADA-B0DD-7B7FF09541A2}.Release|x64.Build.0 = Release|x64
|
||||
{874EB20E-DF0C-4496-9325-27476BF86E48}.Debug|x64.ActiveCfg = Release|x64
|
||||
{874EB20E-DF0C-4496-9325-27476BF86E48}.Debug|x64.Build.0 = Release|x64
|
||||
{874EB20E-DF0C-4496-9325-27476BF86E48}.Dev Build|x64.ActiveCfg = Release|x64
|
||||
{874EB20E-DF0C-4496-9325-27476BF86E48}.Dev Build|x64.Build.0 = Release|x64
|
||||
{874EB20E-DF0C-4496-9325-27476BF86E48}.Release|x64.ActiveCfg = Release|x64
|
||||
{874EB20E-DF0C-4496-9325-27476BF86E48}.Release|x64.Build.0 = Release|x64
|
||||
{715E3842-0D57-4068-BA22-9D4FA46DE633}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{715E3842-0D57-4068-BA22-9D4FA46DE633}.Debug|x64.Build.0 = Debug|x64
|
||||
{715E3842-0D57-4068-BA22-9D4FA46DE633}.Dev Build|x64.ActiveCfg = Release|x64
|
||||
{715E3842-0D57-4068-BA22-9D4FA46DE633}.Dev Build|x64.Build.0 = Release|x64
|
||||
{715E3842-0D57-4068-BA22-9D4FA46DE633}.Release|x64.ActiveCfg = Release|x64
|
||||
{715E3842-0D57-4068-BA22-9D4FA46DE633}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5E101A67-74C8-4B22-A519-AF25C9B7C86C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
3083
Stand/AbstractEntity.cpp
Normal file
317
Stand/AbstractEntity.hpp
Normal file
@ -0,0 +1,317 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "fwddecl.hpp"
|
||||
#include "gta_fwddecl.hpp"
|
||||
#include "natives_decl.hpp"
|
||||
|
||||
#include "nullsub.hpp"
|
||||
|
||||
namespace Stand
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
class AbstractEntity
|
||||
{
|
||||
public:
|
||||
inline static bool player_ped_was_on_foot = true;
|
||||
inline static bool player_ped_was_aiming = true;
|
||||
|
||||
inline static std::unordered_map<Entity, std::pair<time_t, std::unordered_map<Hash, std::pair<std::function<void(AbstractEntity&)>, std::function<void(AbstractEntity&)>>>>> control_requests = {};
|
||||
|
||||
static void updatePlayerPed();
|
||||
static void updatePlayerVehAndEnt();
|
||||
static void updatePlayerEnt();
|
||||
static void updatePlayerPedVehAndEnt();
|
||||
static void updateCamEnt();
|
||||
static void onTick();
|
||||
|
||||
static AbstractEntity get(AbstractEntity) = delete;
|
||||
[[nodiscard]] static AbstractEntity get(Entity handle) { return AbstractEntity(handle); }
|
||||
[[nodiscard]] static AbstractEntity get(CPhysical* ptr) { return AbstractEntity(ptr); }
|
||||
static void get(AbstractEntity&) = delete;
|
||||
[[nodiscard]] static AbstractEntity getSmart(int64_t handle_or_ptr);
|
||||
[[nodiscard]] static AbstractEntity getNetwork(uint16_t network_id);
|
||||
|
||||
[[nodiscard]] static v3 getEffectiveUserPos();
|
||||
|
||||
[[nodiscard]] static AbstractEntity getPersonalVehicle();
|
||||
|
||||
[[nodiscard]] static AbstractEntity getNearestVisible(std::vector<AbstractEntity>& entites, bool los_check = true);
|
||||
|
||||
[[nodiscard]] static AbstractEntity invalid() { return AbstractEntity(); }
|
||||
|
||||
private:
|
||||
CPhysical* ptr;
|
||||
Entity handle;
|
||||
|
||||
public:
|
||||
constexpr AbstractEntity()
|
||||
: ptr(nullptr), handle(INVALID_GUID)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr AbstractEntity(const AbstractEntity& ent)
|
||||
: ptr(ent.ptr), handle(ent.handle)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
explicit constexpr AbstractEntity(Entity handle)
|
||||
: ptr(nullptr), handle(handle)
|
||||
{
|
||||
}
|
||||
|
||||
explicit constexpr AbstractEntity(CPhysical* ptr)
|
||||
: ptr(ptr), handle(INVALID_GUID)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static void getAll(const std::function<bool(AbstractEntity&&)>& collector);
|
||||
static bool getAllPeds(const std::function<bool(AbstractEntity&&)>& collector);
|
||||
static bool getAllVehicles(const std::function<bool(AbstractEntity&&)>& collector);
|
||||
static bool getAllObjects(const std::function<bool(AbstractEntity&&)>& collector);
|
||||
static void getAllPickups(const std::function<bool(AbstractEntity&&)>& collector);
|
||||
static void getAllObjectsIncludingPickups(const std::function<bool(AbstractEntity&&)>& collector);
|
||||
|
||||
static void getAllPeds(std::vector<AbstractEntity>& vec);
|
||||
static void getAllVehicles(std::vector<AbstractEntity>& vec);
|
||||
static void getAllObjects(std::vector<AbstractEntity>& vec);
|
||||
static void getAllPickups(std::vector<AbstractEntity>& vec);
|
||||
|
||||
[[nodiscard]] bool hasHandle() const;
|
||||
bool ensureHandle();
|
||||
private:
|
||||
bool findHandle();
|
||||
public:
|
||||
[[nodiscard]] bool isHandleEquals(Entity handle);
|
||||
// Experimental stuff, not recommended to be used.
|
||||
void releaseHandle();
|
||||
bool setHandle(Entity desired_handle);
|
||||
void setHandleReference(uint8_t reference);
|
||||
|
||||
bool ensurePointer();
|
||||
private:
|
||||
bool findPointer();
|
||||
public:
|
||||
bool ensureHandleAndPointer();
|
||||
|
||||
[[nodiscard]] Entity getHandle();
|
||||
[[nodiscard]] CPhysical* getPointer();
|
||||
|
||||
[[nodiscard]] CPed* getCPed()
|
||||
{
|
||||
return reinterpret_cast<CPed*>(getPointer());
|
||||
}
|
||||
|
||||
[[nodiscard]] CVehicle* getCVehicle()
|
||||
{
|
||||
return reinterpret_cast<CVehicle*>(getPointer());
|
||||
}
|
||||
|
||||
[[nodiscard]] CObject* getCObject()
|
||||
{
|
||||
return reinterpret_cast<CObject*>(getPointer());
|
||||
}
|
||||
|
||||
[[nodiscard]] CPhysical* getPointerRaw() const noexcept
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] CPed* getCPedRaw() const noexcept
|
||||
{
|
||||
return reinterpret_cast<CPed*>(ptr);
|
||||
}
|
||||
|
||||
[[nodiscard]] void* getNetObjectImpl();
|
||||
|
||||
template <typename T = rage::netObject>
|
||||
[[nodiscard]] T* getNetObject()
|
||||
{
|
||||
return reinterpret_cast<T*>(getNetObjectImpl());
|
||||
}
|
||||
|
||||
operator bool() = delete;
|
||||
operator Entity();
|
||||
operator CPed* ();
|
||||
operator CVehicle* ();
|
||||
bool operator==(AbstractEntity& b);
|
||||
bool operator==(AbstractEntity&& b);
|
||||
bool operator!=(AbstractEntity& b);
|
||||
void operator=(const AbstractEntity& b);
|
||||
[[nodiscard]] std::size_t hash() const noexcept;
|
||||
void reset() noexcept;
|
||||
|
||||
// General
|
||||
[[nodiscard]] bool isValid() const noexcept;
|
||||
[[nodiscard]] bool isFullyUsable();
|
||||
[[nodiscard]] bool exists();
|
||||
[[nodiscard]] eEntityType getType();
|
||||
[[nodiscard]] bool isPed();
|
||||
[[nodiscard]] bool isVehicle();
|
||||
[[nodiscard]] bool isObject();
|
||||
[[nodiscard]] bool isPickup();
|
||||
[[nodiscard]] std::string getName(name_t gender);
|
||||
[[nodiscard]] std::string getName(bool include_owner = true);
|
||||
[[nodiscard]] v3 getPos();
|
||||
[[nodiscard]] v3 getVisualPos();
|
||||
void setPos(const v3& pos);
|
||||
void setOrigin(const v3& pos);
|
||||
[[nodiscard]] v3 getRot();
|
||||
void setRot(const v3& rot);
|
||||
[[nodiscard]] bool isInLineOfSight();
|
||||
[[nodiscard]] bool isInLineOfSight(const v3& observer_pos);
|
||||
[[nodiscard]] bool isInLineOfSight(const v3& observer_pos, const v3& pos);
|
||||
[[nodiscard]] AbstractModel getModel();
|
||||
[[nodiscard]] CBaseModelInfo* getModelInfo();
|
||||
[[nodiscard]] Hash getModelHash();
|
||||
[[nodiscard]] AbstractPlayer getOwner();
|
||||
[[nodiscard]] bool isOwner();
|
||||
void requestControl(Hash reason, std::function<void(AbstractEntity&)>&& callback, std::function<void(AbstractEntity&)>&& = &nullsub<AbstractEntity&>);
|
||||
|
||||
[[nodiscard]] bool canBeDeleted();
|
||||
void removeFromPlaneOfExistence();
|
||||
void removeFromPlaneOfExistenceNocheck();
|
||||
private:
|
||||
void removeFromPlaneOfExistenceRemoveRelationships();
|
||||
void removeFromPlaneOfExistenceAfterControlRequest();
|
||||
public:
|
||||
bool removeFromPlaneOfExistenceForce();
|
||||
private:
|
||||
bool removeFromPlaneOfExistenceInner();
|
||||
|
||||
public:
|
||||
[[nodiscard]] bool isInvulnerable();
|
||||
[[nodiscard]] float getHealth();
|
||||
void setHealth(float health);
|
||||
[[nodiscard]] bool isDead();
|
||||
[[nodiscard]] bool isFrozen();
|
||||
void freeze();
|
||||
void unfreeze();
|
||||
[[nodiscard]] Vector3 getDimensions();
|
||||
[[nodiscard]] Vector3 getOrigin();
|
||||
[[nodiscard]] v3 getOriginOffset();
|
||||
[[nodiscard]] Box getBox();
|
||||
[[nodiscard]] float airDistance(AbstractEntity& b);
|
||||
[[nodiscard]] bool canTarget(const TargetingData& data, bool ped_to_vehicle, bool consider_veh_as_player = false);
|
||||
[[nodiscard]] rage::fwExtension* getExtension(uint32_t id);
|
||||
private:
|
||||
[[nodiscard]] rage::fwExtension* getExtensionInner(uint32_t id) const;
|
||||
public:
|
||||
void setCanMigrate(bool can_migrate);
|
||||
[[nodiscard]] bool getCanMigrate();
|
||||
void setAlwaysSynch(bool always_synch);
|
||||
[[nodiscard]] uint16_t getNetObjId();
|
||||
[[nodiscard]] bool isNetObjId(uint16_t id);
|
||||
void giveControl(AbstractPlayer p);
|
||||
[[nodiscard]] bool isInWater();
|
||||
[[nodiscard]] float getSpeed();
|
||||
|
||||
// Ped Specific
|
||||
[[nodiscard]] Vector3 getBonePos(PedBoneId boneId);
|
||||
[[nodiscard]] Vector3 getHeadPos();
|
||||
[[nodiscard]] bool isAiming();
|
||||
[[nodiscard]] bool isAPlayer();
|
||||
[[nodiscard]] bool couldBePlayer();
|
||||
[[nodiscard]] CPlayerInfo* getPlayerInfo();
|
||||
[[nodiscard]] compactplayer_t getPlayerId();
|
||||
[[nodiscard]] AbstractPlayer getPlayer();
|
||||
[[nodiscard]] float getMaxHealth();
|
||||
[[nodiscard]] float getArmour();
|
||||
void setMaxHealth(float max_health);
|
||||
void setArmour(float armor);
|
||||
[[nodiscard]] static float getMaxArmour();
|
||||
[[nodiscard]] bool isFriend();
|
||||
[[nodiscard]] bool isInAnyVehicle();
|
||||
[[nodiscard]] int getSeat(AbstractEntity& veh);
|
||||
void giveWeapons(std::vector<hash_t>&& weapons, const bool force = false);
|
||||
void giveAllWeapons();
|
||||
void removeWeapons(std::vector<hash_t>&& weapons);
|
||||
void removeAllWeapons();
|
||||
[[nodiscard]] AbstractEntity getCurrentWeaponEntity();
|
||||
[[nodiscard]] v3 getCurrentWeaponPos();
|
||||
[[nodiscard]] CPedHeadBlendData* getHeadBlendData();
|
||||
[[nodiscard]] int getComponentTexture(int component_id);
|
||||
[[nodiscard]] int getComponentMaxDrawable(int component_id);
|
||||
void ensureHasParachute();
|
||||
void giveParachute();
|
||||
void randomiseOutfit();
|
||||
void godmodeEnable(const bool no_ragdoll = true);
|
||||
void godmodeDisable();
|
||||
void revive();
|
||||
[[nodiscard]] bool isInBubble();
|
||||
[[nodiscard]] AbstractEntity getVehicle(bool include_last = false);
|
||||
[[nodiscard]] bool isOnGround();
|
||||
[[nodiscard]] bool hasHeadroom();
|
||||
void setConfigFlag(int flag, bool value);
|
||||
void setCombatAttr(int flag, bool value);
|
||||
void cage(Hash cage_model = 0);
|
||||
void ragdoll();
|
||||
[[nodiscard]] Hash getSelectedWeapon();
|
||||
void sendMagicBullet(Hash weapon, float damage, bool nullify);
|
||||
[[nodiscard]] AbstractEntity getWeapon();
|
||||
[[nodiscard]] v3 getWeaponMuzzlePos();
|
||||
[[nodiscard]] bool isPassiveMode();
|
||||
[[nodiscard]] bool isParachuting();
|
||||
|
||||
// Vehicle Specific
|
||||
[[nodiscard]] int getMaxPassengers();
|
||||
[[nodiscard]] int getFreeSeat();
|
||||
void makePassengersLeave();
|
||||
[[nodiscard]] AbstractEntity getPedInSeat(int seat);
|
||||
[[nodiscard]] AbstractEntity getDriver();
|
||||
[[nodiscard]] bool isAPlayerInAnySeat();
|
||||
[[nodiscard]] bool isOwnerOfVehicleAndDriver();
|
||||
void setVehicleCanBeDamaged(const bool toggle);
|
||||
void repair();
|
||||
void wash();
|
||||
[[nodiscard]] int getUpgradeValue(int modType);
|
||||
[[nodiscard]] int getUpgradeMaxValue(int modType);
|
||||
[[nodiscard]] bool isUpgradeApplicable(int modType);
|
||||
[[nodiscard]] bool hasUpgradeMax(int modType);
|
||||
void applyUpgrade(int modType, int value);
|
||||
void applyUpgradeMax(int modType);
|
||||
void fullyUpgrade();
|
||||
bool applyPerformanceUpgrade();
|
||||
bool applyNeonPerformanceUpgrade();
|
||||
bool applyPerformanceUpgradeWithSpoiler();
|
||||
void downgrade();
|
||||
void startEngine();
|
||||
[[nodiscard]] bool isVtolOn();
|
||||
void toggleVtolOff();
|
||||
void destroy();
|
||||
void call();
|
||||
[[nodiscard]] int getHeadlightsVariation();
|
||||
void setHeadlightsVariation(int value);
|
||||
[[nodiscard]] int getPrimaryColour();
|
||||
void setPrimaryColour(int value);
|
||||
[[nodiscard]] int getSecondaryColour();
|
||||
void setSecondaryColour(int value);
|
||||
[[nodiscard]] bool isUserPersonalVehicle();
|
||||
void slingshot();
|
||||
void slingshot(Direction direction);
|
||||
[[nodiscard]] std::optional<std::vector<uint8_t>> getNextGenRemapping(int modType);
|
||||
void makeIndestructible();
|
||||
void detachWheel(int wheelIndex);
|
||||
void setPlateText(const std::string& text);
|
||||
void setPlateText(const char* text);
|
||||
void setPlateBasedOnSeed();
|
||||
void randomiseSeedAndUpdatePlate();
|
||||
[[nodiscard]] bool isOnRoad();
|
||||
[[nodiscard]] AbstractPlayer getPersonalVehicleOwner();
|
||||
[[nodiscard]] std::pair<Vector3, Vector3> getBombBayPos();
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
inline AbstractEntity g_player_ped;
|
||||
inline AbstractEntity g_player_veh;
|
||||
inline AbstractEntity g_player_ent;
|
||||
inline bool g_overwriting_cam_ent = false;
|
||||
inline AbstractEntity g_cam_ped;
|
||||
inline AbstractEntity g_cam_veh;
|
||||
inline AbstractEntity g_cam_ent;
|
||||
inline AbstractEntity g_preview_ent;
|
||||
}
|
1077
Stand/AbstractModel.cpp
Normal file
115
Stand/AbstractModel.hpp
Normal file
@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
|
||||
#include "natives_decl.hpp"
|
||||
|
||||
#include "Label.hpp"
|
||||
|
||||
namespace Stand
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
class AbstractModel
|
||||
{
|
||||
private:
|
||||
Hash model;
|
||||
|
||||
public:
|
||||
constexpr AbstractModel(Hash model) noexcept
|
||||
: model(model)
|
||||
{
|
||||
}
|
||||
|
||||
void operator =(Hash model) noexcept
|
||||
{
|
||||
this->model = model;
|
||||
}
|
||||
|
||||
operator Hash() const noexcept
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isValidModel() const; // because of the get_model_info hook, this will return false for null models
|
||||
[[nodiscard]] bool isNull() const noexcept;
|
||||
[[nodiscard]] bool isNullVehicle() const noexcept;
|
||||
|
||||
[[nodiscard]] CBaseModelInfo* getModelInfo() const noexcept;
|
||||
[[nodiscard]] CVehicleModelInfo* getVehicleModelInfo() const noexcept;
|
||||
|
||||
[[nodiscard]] bool isPed() const noexcept;
|
||||
[[nodiscard]] bool isObject() const noexcept;
|
||||
[[nodiscard]] bool isObjectStrict() const noexcept;
|
||||
[[nodiscard]] bool isVehicle() const noexcept;
|
||||
|
||||
[[nodiscard]] Vector3 getDimensions() const;
|
||||
|
||||
[[nodiscard]] Label getLabel() const;
|
||||
[[nodiscard]] Label getLabelPed() const;
|
||||
|
||||
// Vehicle Specific
|
||||
|
||||
[[nodiscard]] VehicleType getVehicleType() const noexcept;
|
||||
[[nodiscard]] bool isSubmarine() const noexcept;
|
||||
[[nodiscard]] bool isTrailer() const noexcept;
|
||||
[[nodiscard]] bool isPlane() const noexcept;
|
||||
[[nodiscard]] bool isHeli() const noexcept;
|
||||
[[nodiscard]] bool isBike() const noexcept;
|
||||
[[nodiscard]] bool isBoat() const noexcept;
|
||||
[[nodiscard]] bool isBicycle() const noexcept;
|
||||
[[nodiscard]] bool isSubmarineCar() const noexcept;
|
||||
[[nodiscard]] bool isTrain() const noexcept;
|
||||
|
||||
[[nodiscard]] bool isAirborne() const noexcept;
|
||||
[[nodiscard]] bool isAquatic() const noexcept;
|
||||
|
||||
[[nodiscard]] int getNumSeats() const;
|
||||
|
||||
[[nodiscard]] bool isTank() const noexcept;
|
||||
[[nodiscard]] bool isTraffic() const noexcept;
|
||||
[[nodiscard]] bool isTowTruck() const noexcept;
|
||||
[[nodiscard]] bool isCargobob() const noexcept;
|
||||
[[nodiscard]] bool isBigVehicle() const noexcept;
|
||||
|
||||
[[nodiscard]] bool hasSpecialFlight() const noexcept;
|
||||
[[nodiscard]] bool hasVtol() const noexcept;
|
||||
[[nodiscard]] bool hasDriftTune() const noexcept;
|
||||
|
||||
[[nodiscard]] bool hasWindowTintMinusOne() const noexcept;
|
||||
[[nodiscard]] bool isStealthVehicle() const noexcept;
|
||||
[[nodiscard]] bool isRemoteControllable() const noexcept;
|
||||
[[nodiscard]] bool isRemoteControllablePv() const noexcept;
|
||||
[[nodiscard]] bool usesAttachmentCameras() const noexcept;
|
||||
[[nodiscard]] bool canBeStoodUpon() const noexcept;
|
||||
|
||||
// Object Specific
|
||||
|
||||
[[nodiscard]] bool isCageObject() const noexcept;
|
||||
[[nodiscard]] bool isScubaObject() const noexcept;
|
||||
|
||||
// Ped Specific
|
||||
|
||||
[[nodiscard]] bool isStoryCharacter() const noexcept;
|
||||
[[nodiscard]] bool isOnlineCharacter() const noexcept;
|
||||
[[nodiscard]] bool isPlayableOnlineCharacter() const noexcept;
|
||||
|
||||
[[nodiscard]] bool isAnimal() const noexcept;
|
||||
[[nodiscard]] bool isWaterAnimal() const noexcept;
|
||||
[[nodiscard]] bool isObtainableFromPeyote() const noexcept;
|
||||
|
||||
[[nodiscard]] bool canBecomeHostile() const noexcept;
|
||||
[[nodiscard]] bool canUseProjectiles() const noexcept;
|
||||
[[nodiscard]] bool canUseWeapons() const noexcept;
|
||||
|
||||
[[nodiscard]] bool isCsPed() const noexcept;
|
||||
[[nodiscard]] bool isHiResPed() const noexcept;
|
||||
|
||||
// Misc
|
||||
|
||||
[[nodiscard]] bool isSusAttachee() const noexcept;
|
||||
[[nodiscard]] bool isSusAttachment() const noexcept;
|
||||
[[nodiscard]] bool isValidParachute() const noexcept;
|
||||
|
||||
[[nodiscard]] bool supportsInteriorColours() const noexcept;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
static_assert(sizeof(AbstractModel) == sizeof(int));
|
||||
}
|
3555
Stand/AbstractPlayer.cpp
Normal file
386
Stand/AbstractPlayer.hpp
Normal file
@ -0,0 +1,386 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
#include <soup/Optional.hpp>
|
||||
#include <soup/ShortString.hpp>
|
||||
|
||||
#include "fwddecl.hpp"
|
||||
#include "gta_fwddecl.hpp"
|
||||
#include "gta_player.hpp"
|
||||
#include "typedecl.hpp"
|
||||
|
||||
#include "atStringHash.hpp"
|
||||
#include "BiString.hpp"
|
||||
#include "netIpAddress.hpp"
|
||||
#include "PlayerScope.hpp"
|
||||
|
||||
#define HAVE_BREAKUP_KICK false
|
||||
|
||||
namespace Stand
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
class AbstractPlayer
|
||||
{
|
||||
public:
|
||||
inline static bool is_freemode = false;
|
||||
inline static compactplayer_t host = MAX_PLAYERS;
|
||||
inline static compactplayer_t prev_host = MAX_PLAYERS;
|
||||
inline static time_t last_host_change = 0;
|
||||
inline static player_t script_host = MAX_PLAYERS;
|
||||
inline static time_t next_orgasm_kick = 0;
|
||||
inline static bool performing_love_letter_kick = false;
|
||||
|
||||
inline static std::array<soup::ShortString<16>, MAX_PLAYERS> redundant_names = {};
|
||||
|
||||
[[nodiscard]] static CNetworkPlayerMgr* getNetworkPlayerMgrIfApplicable();
|
||||
static void onInit();
|
||||
static void doWork();
|
||||
static void updateLocalPlayer();
|
||||
|
||||
[[nodiscard]] static int getPlayerCount();
|
||||
[[nodiscard]] static std::vector<AbstractPlayer> listAll();
|
||||
[[nodiscard]] static std::vector<AbstractPlayer> listOnly(const bool include_self = false, const bool include_friends = false, const bool include_crew_members = false, const bool include_stand_users = false, const bool include_org_members = false, const bool include_modders = false, const bool include_likely_modders = false);
|
||||
[[nodiscard]] static std::vector<AbstractPlayer> listExcept(const bool exclude_self = false, const bool exclude_friends = false, const bool exclude_crew_members = false, const bool exclude_stand_users = false, const bool exclude_org_members = false, const bool exclude_modders = false, const bool exclude_likely_modders = false);
|
||||
[[nodiscard]] static AbstractPlayer getRandom();
|
||||
[[nodiscard]] static AbstractPlayer getHost();
|
||||
[[nodiscard]] static AbstractPlayer getScriptHost();
|
||||
|
||||
[[nodiscard]] static constexpr AbstractPlayer invalid() noexcept
|
||||
{
|
||||
return MAX_PLAYERS;
|
||||
}
|
||||
|
||||
[[nodiscard]] static AbstractPlayer fromRockstarId(int64_t rid);
|
||||
[[nodiscard]] static AbstractPlayer fromStartupId(const rage::netPeerId peerId);
|
||||
[[nodiscard]] static AbstractPlayer fromPeerId(const rage::netPeerId peerId);
|
||||
[[nodiscard]] static AbstractPlayer fromEndpointId(uint32_t id);
|
||||
[[nodiscard]] static AbstractPlayer fromEndpointAddress(const rage::netSocketAddress& addr);
|
||||
[[nodiscard]] static AbstractPlayer getNextHost();
|
||||
|
||||
player_t p;
|
||||
|
||||
constexpr AbstractPlayer(player_t p = MAX_PLAYERS) noexcept
|
||||
: p(p)
|
||||
{
|
||||
}
|
||||
|
||||
operator player_t() const noexcept { return p; }
|
||||
|
||||
[[nodiscard]] bool isValid() const noexcept { return p < MAX_PLAYERS; }
|
||||
[[nodiscard]] bool exists() const;
|
||||
|
||||
inline static uint8_t streamer_spoof = 0;
|
||||
inline static playerscope_t hide_unfiltered_name = PlayerScope::NOONE;
|
||||
[[nodiscard]] static const char* getUserName();
|
||||
|
||||
[[nodiscard]] std::string getName() const; // filtered
|
||||
[[nodiscard]] std::string getNameWithFlags() const;
|
||||
[[nodiscard]] std::wstring getNameW() const;
|
||||
[[nodiscard]] std::wstring getNameW(bool with_flags) const;
|
||||
[[nodiscard]] std::u32string getFlagsStrings() const;
|
||||
[[nodiscard]] const char* getRedundantName() const; // filtered
|
||||
[[nodiscard]] uint32_t getNameHash() const;
|
||||
|
||||
[[nodiscard]] static const char* getMaskName(const std::string& name);
|
||||
void spoofName() const;
|
||||
void unspoofName() const;
|
||||
void forceCommandRecreationIfNotUser() const;
|
||||
void updateNameOnBlip() const;
|
||||
[[nodiscard]] Vector3 getBlipPos() const;
|
||||
|
||||
[[nodiscard]] std::string getUnoverriddenName() const;
|
||||
[[nodiscard]] const char* getOverrideName() const;
|
||||
void setOverrideName(const std::string& name) const;
|
||||
void clearOverrideName() const;
|
||||
|
||||
[[nodiscard]] std::string getSessionName() const;
|
||||
[[nodiscard]] std::wstring getSessionNameForUser() const;
|
||||
|
||||
inline static playerscope_t hide_rid = PlayerScope::NOONE;
|
||||
[[nodiscard]] const rage::rlGamerHandle& getGamerHandle() const;
|
||||
[[nodiscard]] int64_t getRockstarId() const;
|
||||
template <typename T>
|
||||
[[nodiscard]] T getRockstarIdForUser() const
|
||||
{
|
||||
if (isInScope(hide_rid))
|
||||
{
|
||||
return BiString<T>::fromLang(ATSTRINGHASH("RDCTD"));
|
||||
}
|
||||
return BiString<T>::fromValue(getRockstarId());
|
||||
}
|
||||
|
||||
inline static playerscope_t hide_ip = PlayerScope::NOONE;
|
||||
[[nodiscard]] rage::netSocketAddress getAddress() const;
|
||||
[[nodiscard]] rage::netSocketAddress getConnectAddress() const;
|
||||
[[nodiscard]] rage::netSocketAddress getLanAddress() const;
|
||||
|
||||
[[nodiscard]] std::string getIpAddressForUserA() const;
|
||||
[[nodiscard]] std::wstring getIpAddressForUserW() const;
|
||||
|
||||
[[nodiscard]] std::string getConnectedViaForPlayerHelpText() const;
|
||||
[[nodiscard]] std::wstring getConnectedViaForPlayerInfoValue() const;
|
||||
|
||||
inline static playerscope_t hide_geoip = PlayerScope::NOONE;
|
||||
[[nodiscard]] std::string getCountry() const;
|
||||
[[nodiscard]] Label getLanguageName() const;
|
||||
[[nodiscard]] int getLanguage() const;
|
||||
|
||||
[[nodiscard]] bool isUsingController() const;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] T get() const;
|
||||
[[nodiscard]] rage::netPeerId getPeerId() const;
|
||||
|
||||
using host_queue_sort_algo_t = bool(*)(const AbstractPlayer& a, const AbstractPlayer& b);
|
||||
static host_queue_sort_algo_t host_queue_sort_algos[4];
|
||||
[[nodiscard]] compactplayer_t getHostQueuePosition() const;
|
||||
|
||||
[[nodiscard]] rage::netPeerId getStartupId() const;
|
||||
[[nodiscard]] int64_t getAccountId() const;
|
||||
[[nodiscard]] uint32_t getMacId() const;
|
||||
[[nodiscard]] CNetGamePlayer* getCNetGamePlayer() const;
|
||||
[[nodiscard]] CPlayerInfo* getPlayerInfoNoFallback() const;
|
||||
[[nodiscard]] CPlayerInfo* getPlayerInfo() const;
|
||||
[[nodiscard]] rage::rlGamerInfo* getGamerInfoNoFallback() const;
|
||||
[[nodiscard]] rage::rlGamerInfo* getGamerInfo() const;
|
||||
[[nodiscard]] rage::netPeerAddress* getPeer() const;
|
||||
[[nodiscard]] rage::netEndpoint* getEndpoint() const;
|
||||
[[nodiscard]] uint32_t getEndpointId() const;
|
||||
[[nodiscard]] int32_t getCxnId(const uint32_t channel_id) const;
|
||||
[[nodiscard]] rage::rlClanMembershipData* getActiveClanMembership() const;
|
||||
[[nodiscard]] CPed* getCPedPtr() const;
|
||||
[[nodiscard]] bool hasPed() const;
|
||||
[[nodiscard]] AbstractEntity getPed() const;
|
||||
[[nodiscard]] AbstractEntity getVehicle() const;
|
||||
[[nodiscard]] AbstractEntity getVehicle(Click& click) const;
|
||||
[[nodiscard]] int32_t getWantedLevel() const;
|
||||
private:
|
||||
void incRemoteWantedLevel(int32_t wanted_level) const;
|
||||
void clearWantedLevel() const;
|
||||
public:
|
||||
void setWantedLevel(int32_t wanted_level) const;
|
||||
[[nodiscard]] v3 getPos() const;
|
||||
void tickAutoHeal() const;
|
||||
void givePickupReward(hash_t reward) const;
|
||||
void sendFreeze() const;
|
||||
|
||||
[[nodiscard]] CommandPlayer* getCommand() const noexcept;
|
||||
[[nodiscard]] CommandList* getCommandAsList() const noexcept;
|
||||
[[nodiscard]] bool satisfiesAnyOf(playerflag_t flags) const noexcept;
|
||||
[[nodiscard]] bool satisfiesAnyOf(bool is_friend, bool is_crew_member = false, bool is_stand_user = false, bool is_org_member = false, bool is_modder = false, bool is_likely_modder = false) const;
|
||||
[[nodiscard]] bool isFrozen() const;
|
||||
void freeze(const bool toggle = true) const;
|
||||
void unfreeze() const;
|
||||
void kill() const;
|
||||
playertype_t getType() const;
|
||||
|
||||
void onFlowEvent(flowevent_t event, playertype_t playertype) const;
|
||||
void setAttacked() const;
|
||||
[[nodiscard]] floweventreaction_t getReactions(flowevent_t event, bool event_is_being_dispatched = true, bool alternative_self_handling = false) const;
|
||||
[[nodiscard]] floweventreaction_t getReactions(flowevent_t event, playertype_t playertype, bool event_is_being_dispatched = true, bool alternative_self_handling = false) const;
|
||||
void addReactions(floweventreaction_t& reactions, flowevent_t event) const; // prefer to use EventAggregation
|
||||
[[nodiscard]] static floweventreaction_t getReactionsRaw(flowevent_t event, playertype_t playertype);
|
||||
floweventreaction_t triggerDetection(flowevent_t type, std::string&& extra_data = {}, uint8_t severity = 100) const;
|
||||
floweventreaction_t getAndApplyReactionsIn(flowevent_t type, const std::string& extra_data = {}) const;
|
||||
void applyReactions(floweventreaction_t reactions) const;
|
||||
void applyReactions(floweventreaction_t reactions, flowevent_t event) const;
|
||||
void applyReactions(floweventreaction_t reactions, flowevent_t event, const Label& name) const;
|
||||
void applyReactions(floweventreaction_t reactions, std::vector<flowevent_t>&& types, Label&& name) const;
|
||||
void applyReactions(floweventreaction_t reactions, EventAggregation&& event, uint8_t severity = 100) const;
|
||||
void applyReactions(floweventreaction_t reactions, NuancedEventWithExtraData&& event) const;
|
||||
void applyReactions(EventLabel&& label, std::vector<flowevent_t>&& types, floweventreaction_t reactions, hash_t format_string_key, uint8_t severity = 100) const;
|
||||
void applyReactionsIn(EventLabel&& label, std::vector<flowevent_t>&& types, floweventreaction_t reactions, uint8_t severity = 100) const;
|
||||
void applyReactionsIn(floweventreaction_t reactions, flowevent_t type, const std::string& extra_data = {}) const;
|
||||
void applyReactionsOut(EventLabel&& label, std::vector<flowevent_t>&& types, floweventreaction_t reactions) const;
|
||||
static void augmentReactionToast(std::string& toast, floweventreaction_t reactions);
|
||||
|
||||
[[nodiscard]] bool hasFlag(playerflag_t flag) const;
|
||||
void blockIncomingNetEvents(ThreadContext thread_context) const;
|
||||
[[nodiscard]] floweventreaction_t getOutgoingSyncReactions() const;
|
||||
[[nodiscard]] bool blockingOutgoingSyncs() const;
|
||||
|
||||
[[nodiscard]] bool isInTimeout() const noexcept;
|
||||
void putInTimeout(ThreadContext thread_context) const;
|
||||
|
||||
[[nodiscard]] bool areStatsReady() const;
|
||||
[[nodiscard]] bool areStatsBusted() const;
|
||||
[[nodiscard]] int getRp() const;
|
||||
[[nodiscard]] int getRank() const;
|
||||
[[nodiscard]] unsigned int getMoney() const;
|
||||
[[nodiscard]] unsigned int getWallet() const;
|
||||
[[nodiscard]] unsigned int getBank() const;
|
||||
[[nodiscard]] float getKd() const;
|
||||
[[nodiscard]] int getKills() const;
|
||||
[[nodiscard]] int getDeaths() const;
|
||||
[[nodiscard]] bool isOtr() const;
|
||||
[[nodiscard]] bool isOutOfSight() const;
|
||||
[[nodiscard]] bool isInInterior() const;
|
||||
[[nodiscard]] bool isHost() const noexcept;
|
||||
[[nodiscard]] bool canBecomeHost() const noexcept;
|
||||
[[nodiscard]] bool isNextHost() const;
|
||||
[[nodiscard]] bool isScriptHost() const;
|
||||
[[nodiscard]] bool isFriend() const;
|
||||
[[nodiscard]] bool isCrewMember() const;
|
||||
[[nodiscard]] bool isStandUser() const;
|
||||
[[nodiscard]] bool isStandDevDbg() const;
|
||||
[[nodiscard]] bool isRockstarAdmin() const;
|
||||
[[nodiscard]] static bool isAnyRockstarAdminInSession();
|
||||
[[nodiscard]] bool isTyping() const;
|
||||
[[nodiscard]] float* mentalState() const;
|
||||
[[nodiscard]] float getMentalState() const;
|
||||
[[nodiscard]] int getInteriorId() const;
|
||||
[[nodiscard]] int getShopId() const;
|
||||
[[nodiscard]] int getApartmentId() const;
|
||||
[[nodiscard]] AbstractModel getCurrentVehicleModel() const;
|
||||
[[nodiscard]] bool isInVehicle() const;
|
||||
[[nodiscard]] bool isUsingRcVehicle() const;
|
||||
[[nodiscard]] bool isBlockingRequestControl() const;
|
||||
[[nodiscard]] bool isInStore() const; // Shop IDs do not serve for this purpose. Shop ID 45 includes things like the Bunker or LSCM. Likely, wherever the player can "shop". Some stores do not have Shop IDs.
|
||||
|
||||
[[nodiscard]] bool inSameInterior(AbstractPlayer& other, std::optional<int> id = std::nullopt) const noexcept;
|
||||
|
||||
[[nodiscard]] std::optional<int> getBounty() const;
|
||||
[[nodiscard]] bool hasBounty() const;
|
||||
[[nodiscard]] int getBountyValue() const;
|
||||
|
||||
[[nodiscard]] bool isInAnOrg() const noexcept;
|
||||
[[nodiscard]] AbstractPlayer getBoss() const noexcept;
|
||||
[[nodiscard]] bool isBoss() const noexcept;
|
||||
[[nodiscard]] int getOrgType() const noexcept;
|
||||
[[nodiscard]] bool inOurOrg() const noexcept;
|
||||
[[nodiscard]] bool isInMc() const noexcept;
|
||||
[[nodiscard]] const char* getOrgName() const noexcept;
|
||||
void setOrgName(const char* name) const noexcept;
|
||||
void setOrgName(bool is_mc, const char* name) const noexcept;
|
||||
[[nodiscard]] int getColourSlot() const noexcept;
|
||||
[[nodiscard]] bool isBeast() const;
|
||||
[[nodiscard]] bool inCayo() const;
|
||||
[[nodiscard]] bool isVisible() const;
|
||||
|
||||
void giveOtr() const;
|
||||
|
||||
void openThirdEye(std::function<void(const AbstractPlayer&, AbstractEntity&, bool)>&& callback) const; // needs a yieldable script thread
|
||||
[[nodiscard]] bool openThirdEyeWouldBeUseful() const;
|
||||
bool openThirdEyeBegin() const;
|
||||
static void openThirdEyeTick(bool needs_cleanup);
|
||||
void openThirdEyeCleanup(bool needs_cleanup) const;
|
||||
|
||||
void fiberTeleport(Vector2Plus coords) const;
|
||||
void fiberTeleport(const v3& pos) const;
|
||||
[[nodiscard]] bool fiberTeleportVehicleTick(const v3& pos) const;
|
||||
void waypoint() const;
|
||||
|
||||
[[nodiscard]] soup::Optional<Vector2Plus> getWaypoint() const;
|
||||
|
||||
[[nodiscard]] bool canBeVoteKicked() const;
|
||||
[[nodiscard]] bool canBeVoteKickedNaive() const;
|
||||
[[nodiscard]] compactplayer_t getNumKickVoters() const;
|
||||
[[nodiscard]] static compactplayer_t getVoteKickThreshold();
|
||||
[[nodiscard]] static compactplayer_t getVoteKickThresholdUnclamped();
|
||||
[[nodiscard]] bool hasEnoughVotesToKick() const;
|
||||
|
||||
// A host kick generally a) sends MsgKickPlayer, b) adds to blacklist, c) removes from session. All diversions from these rules are documented below.
|
||||
enum eHostKickType : uint32_t
|
||||
{
|
||||
VOTE_KICK = 0,
|
||||
UNKNOWN_NETWORK_ERROR = 1, // doesn't add to blacklist
|
||||
DESYNC = 2, // doesn't send MsgKickPlayer, doesn't add to blacklist
|
||||
ADMIN = 4, // doesn't add to blacklist
|
||||
ADMIN_BLACKLIST = 5,
|
||||
UNKNOWN = 6,
|
||||
BATTLEYE_KICK = 7,
|
||||
BATTLEYE_BAN = 8, // Temporarily bans them from GTA Online
|
||||
};
|
||||
|
||||
[[nodiscard]] static Label getHkReasonString(uint32_t reason);
|
||||
|
||||
void onPreRemove() const;
|
||||
private:
|
||||
[[nodiscard]] bool kickFlowWait(time_t ms = 1000) const;
|
||||
public:
|
||||
void kickBail() const;
|
||||
void kick(bool use_pre_remove = true, bool can_take_script_host = true) const; // needs a yieldable script thread
|
||||
void kickHost(eHostKickType type) const;
|
||||
void kickHostNoprekick(eHostKickType type) const;
|
||||
void kickScriptHost() const;
|
||||
void kickBeUpdate() const;
|
||||
void sendBePacket(bool client, const void* data, uint32_t size) const;
|
||||
void kickNonHost() const;
|
||||
[[nodiscard]] bool checkAggressiveAction() const;
|
||||
[[nodiscard]] bool canUseUnblockableKick(bool karma_ourselves = true) const;
|
||||
void kickLoveLetter(bool call_pre_remove) const;
|
||||
[[nodiscard]] static bool isOrgasmKickOnCooldown();
|
||||
void kickOrgasm() const;
|
||||
void kickBreakup(int remove_reason = -1) const;
|
||||
#if HAVE_BREAKUP_KICK
|
||||
void kickConfusion() const;
|
||||
#endif
|
||||
void sessionDesync(int remove_reason = -1) const;
|
||||
void sessionDesync(const rage::rlGamerHandle& gamer_handle, int remove_reason) const;
|
||||
void remoteDesync(const rage::rlGamerHandle& target, int remove_reason = -1) const;
|
||||
void desyncBealone() const;
|
||||
void desyncBreakup(int remove_reason = -1) const;
|
||||
void removeFromPlayerMgr() const;
|
||||
void removeFromSessionMgr(int remove_reason = -1) const;
|
||||
void kickPickup() const;
|
||||
|
||||
[[nodiscard]] static bool canSendNetEvents(int count = 1);
|
||||
|
||||
void crash() const; // needs script thread context
|
||||
void sendCloneDelete(uint16_t netobjid) const;
|
||||
|
||||
[[nodiscard]] bool isInScope(playerscope_t scope) const;
|
||||
|
||||
static void onComm(const std::string& _text, rage::netPeerId recipient_startup_id);
|
||||
[[nodiscard]] bool isKnownAdvertiser() const;
|
||||
[[nodiscard]] uint8_t getMessageAdLevel(const std::string& text) const;
|
||||
[[nodiscard]] uint8_t getMessageAdLevel(std::wstring text) const;
|
||||
[[nodiscard]] static void normaliseForAdFilters(std::wstring& str) noexcept;
|
||||
[[nodiscard]] static bool checkKnownAggressiveSpammer(const std::wstring& msg) noexcept;
|
||||
[[nodiscard]] static bool nameIsCallToAction(const std::wstring& name);
|
||||
[[nodiscard]] static bool messageHasCallToAction(const std::wstring& msg);
|
||||
[[nodiscard]] static bool messageHasPromiseOfGoodThings(const std::wstring& msg);
|
||||
[[nodiscard]] static bool messageIsEmptyOrMiscPromotion(const std::wstring& msg);
|
||||
|
||||
void sendSms(const std::string& text) const; // Receipient must be a friend or member of the same non-Rockstar crew; doesn't work on self. Message must be 1-255 characters.
|
||||
|
||||
void directPacketSend(DirectPacket a0, uint64_t a1 = 0, uint64_t a2 = 0, uint64_t a3 = 0, uint64_t a4 = 0, uint64_t a5 = 0, uint64_t a6 = 0) const;
|
||||
void directPacketSendIdentify(DirectPacket a0) const;
|
||||
[[nodiscard]] uint8_t getAuthInfo() const;
|
||||
|
||||
[[nodiscard]] v3 getCamPos() const;
|
||||
[[nodiscard]] v3 getCamRot() const;
|
||||
[[nodiscard]] AbstractPlayer getSpectateTarget() const;
|
||||
[[nodiscard]] bool isThisPositionInCameraOrbit(const v3& pos) const;
|
||||
|
||||
[[nodiscard]] float getWeaponDamageModifier() const;
|
||||
[[nodiscard]] float getMeleeWeaponDamageModifier() const;
|
||||
|
||||
void giveVehicleRepair() const;
|
||||
void giveBounty(int value) const;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
static_assert(sizeof(AbstractPlayer) <= sizeof(uintptr_t), "AbstractPlayer is bigger than a pointer/reference");
|
||||
|
||||
inline AbstractPlayer g_player = 0;
|
||||
|
||||
template <>
|
||||
inline compactplayer_t AbstractPlayer::get() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline CNetGamePlayer* AbstractPlayer::get() const
|
||||
{
|
||||
return getCNetGamePlayer();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const rage::netPlayer* AbstractPlayer::get() const
|
||||
{
|
||||
return reinterpret_cast<const rage::netPlayer*>(getCNetGamePlayer());
|
||||
}
|
||||
}
|
42
Stand/AbstractRenderer.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "AbstractRenderer.hpp"
|
||||
|
||||
#include "DrawUtil3d.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace Stand
|
||||
{
|
||||
void AbstractRendererDx::drawLine(const rage::Vector2& pos1, const rage::Vector2& pos2, DirectX::SimpleMath::Color& colour) const
|
||||
{
|
||||
g_renderer.drawLineCP(pos1, pos2, colour);
|
||||
}
|
||||
|
||||
void AbstractRendererDx::drawLine(const v3& pos1, const v3& pos2, DirectX::SimpleMath::Color& colour) const
|
||||
{
|
||||
g_renderer.drawLineCP(pos1.getScreenPos(), pos2.getScreenPos(), colour);
|
||||
}
|
||||
|
||||
void AbstractRendererDx::drawText(const v3& pos, std::wstring&& text, float scale, DirectX::SimpleMath::Color& colour) const
|
||||
{
|
||||
const rage::Vector2 screen_pos = pos.getScreenPos();
|
||||
if (screen_pos.isInBounds())
|
||||
{
|
||||
auto posC = g_renderer.CP2C(screen_pos.x, screen_pos.y);
|
||||
g_renderer.drawTextC(posC.x, posC.y, std::move(text), ALIGN_CENTRE, scale * g_renderer.resolution_text_scale, colour, g_renderer.m_font_user, false);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRendererNative::drawLine(const rage::Vector2& pos1, const rage::Vector2& pos2, DirectX::SimpleMath::Color& colour) const
|
||||
{
|
||||
g_renderer.drawLineThisTickCP(pos1, pos2, colour);
|
||||
}
|
||||
|
||||
void AbstractRendererNative::drawLine(const v3& pos1, const v3& pos2, DirectX::SimpleMath::Color& colour) const
|
||||
{
|
||||
DrawUtil3d::draw_line_native(pos1, pos2, colour);
|
||||
}
|
||||
|
||||
void AbstractRendererNative::drawText(const v3& pos, std::wstring&& text, float scale, DirectX::SimpleMath::Color& colour) const
|
||||
{
|
||||
g_renderer.drawUnscaled3dTextThisTickH(pos, std::move(text), scale, colour);
|
||||
}
|
||||
}
|
33
Stand/AbstractRenderer.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gta_fwddecl.hpp"
|
||||
#include "Renderer.hpp"
|
||||
|
||||
namespace Stand
|
||||
{
|
||||
struct AbstractRenderer
|
||||
{
|
||||
virtual void drawLine(const rage::Vector2& pos1, const rage::Vector2& pos2, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const = 0;
|
||||
virtual void drawLine(const v3& pos1, const v3& pos2, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const = 0;
|
||||
virtual void drawText(const v3& pos, std::wstring&& text, float scale, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const = 0;
|
||||
};
|
||||
|
||||
struct AbstractRendererDx : public AbstractRenderer
|
||||
{
|
||||
void drawLine(const rage::Vector2& pos1, const rage::Vector2& pos2, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const final;
|
||||
void drawLine(const v3& pos1, const v3& pos2, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const final;
|
||||
void drawText(const v3& pos, std::wstring&& text, float scale, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const final;
|
||||
};
|
||||
|
||||
struct AbstractRendererNative : public AbstractRenderer
|
||||
{
|
||||
void drawLine(const rage::Vector2& pos1, const rage::Vector2& pos2, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const final;
|
||||
void drawLine(const v3& pos1, const v3& pos2, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const final;
|
||||
void drawText(const v3& pos, std::wstring&& text, float scale, DirectX::SimpleMath::Color& colour = g_renderer.arColour) const final;
|
||||
};
|
||||
|
||||
inline AbstractRendererDx g_dx_render{};
|
||||
inline AbstractRendererNative g_native_render{};
|
||||
}
|
31
Stand/AcThingData.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <soup/joaat.hpp>
|
||||
|
||||
#include "atMap.hpp"
|
||||
#include "sysObfuscated.hpp"
|
||||
|
||||
struct AcThingData
|
||||
{
|
||||
/* 0x00 */ rage::sysObfuscated_Mutate<uint32_t> timer_1;
|
||||
/* 0x10 */ rage::sysObfuscated_Mutate<uint32_t> timer_1_interval;
|
||||
PAD(0x20, 0xA78) rage::atMap<uint32_t, uint32_t> mm_metric_reported_modules;
|
||||
/* 0xA88 */ uint32_t mm_metric_last_check;
|
||||
/* 0xA8C */ uint32_t mm_metric_interval;
|
||||
|
||||
[[nodiscard]] static uint32_t getModuleHash(const std::wstring& name)
|
||||
{
|
||||
return soup::joaat::hashRange((const char*)name.data(), name.size() * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
[[nodiscard]] bool wasModuleReported(uint32_t hash)
|
||||
{
|
||||
return mm_metric_reported_modules.accessDirect(hash) != nullptr;
|
||||
}
|
||||
|
||||
void markModuleAsReported(uint32_t hash)
|
||||
{
|
||||
mm_metric_reported_modules.insert(hash, 1);
|
||||
}
|
||||
};
|
||||
static_assert(offsetof(AcThingData, mm_metric_interval) == 0xA8C);
|
81
Stand/AddressGamers.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "AddressGamers.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "fmt_arg.hpp"
|
||||
#include "lang.hpp"
|
||||
|
||||
namespace Stand
|
||||
{
|
||||
using Gamer = AddressGamers::Gamer;
|
||||
using Peer = AddressGamers::Peer;
|
||||
|
||||
void Gamer::reset(const std::string& name, int64_t rid_2)
|
||||
{
|
||||
this->name = name;
|
||||
this->rid_2 = rid_2;
|
||||
}
|
||||
|
||||
Peer* AddressGamers::findPeer(rage::netIpAddress ip)
|
||||
{
|
||||
for (auto& peer : peers)
|
||||
{
|
||||
if (peer.ip == ip)
|
||||
{
|
||||
return &peer;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Peer* AddressGamers::findOrCreatePeer(rage::netIpAddress ip)
|
||||
{
|
||||
auto peer = findPeer(ip);
|
||||
if (peer == nullptr)
|
||||
{
|
||||
peer = &peers.emplace_back(ip);
|
||||
}
|
||||
return peer;
|
||||
}
|
||||
|
||||
Gamer* AddressGamers::findGamerByRid2(int64_t rid_2)
|
||||
{
|
||||
for (auto& peer : peers)
|
||||
{
|
||||
if (peer.gamer.rid_2 == rid_2)
|
||||
{
|
||||
return &peer.gamer;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AddressGamers::onDiscoveredName(rage::netIpAddress ip, const char* name)
|
||||
{
|
||||
findOrCreatePeer(ip)->gamer.name = name;
|
||||
}
|
||||
|
||||
void AddressGamers::onDiscoveredGamer(rage::netIpAddress ip, const rage::rlGamerInfo& gamerInfo)
|
||||
{
|
||||
findOrCreatePeer(ip)->gamer.reset(gamerInfo.name, gamerInfo.getHandle().rockstar_id);
|
||||
}
|
||||
|
||||
std::string AddressGamers::getNameForUser(const rage::netIpAddress& ip)
|
||||
{
|
||||
return getNameForUser(findPeer(ip), ip);
|
||||
}
|
||||
|
||||
std::string AddressGamers::getNameForUser(const Peer* peer, const rage::netIpAddress& ip)
|
||||
{
|
||||
if (peer && !peer->gamer.name.empty())
|
||||
{
|
||||
return LANG_FMT("IPNAM", FMT_ARG("ip", ip.toString<std::string>()), FMT_ARG("name", peer->gamer.name.c_str()));
|
||||
}
|
||||
return ip.toString<std::string>();
|
||||
}
|
||||
|
||||
void AddressGamers::deinit()
|
||||
{
|
||||
peers.clear();
|
||||
}
|
||||
}
|
73
Stand/AddressGamers.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <soup/ShortString.hpp>
|
||||
|
||||
#include "netIpAddress.hpp"
|
||||
#include "rlGamerInfo.hpp"
|
||||
|
||||
#include "RateLimit.hpp"
|
||||
|
||||
namespace Stand
|
||||
{
|
||||
struct PacketRateLimit
|
||||
{
|
||||
RateLimit ratelimit;
|
||||
bool did_reaction = false;
|
||||
bool should_block = false;
|
||||
|
||||
constexpr PacketRateLimit(time_t window_duration_ms, unsigned int max_window_requests)
|
||||
: ratelimit(window_duration_ms, max_window_requests)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class AddressGamers
|
||||
{
|
||||
public:
|
||||
struct Gamer
|
||||
{
|
||||
soup::ShortString<16> name;
|
||||
int64_t rid_2;
|
||||
|
||||
void reset(const std::string& name, int64_t rid_2);
|
||||
|
||||
PacketRateLimit msg_script_migrate_host_ratelimit{ 1000, 3 };
|
||||
PacketRateLimit msg_radio_station_sync_request_ratelimit{ 1000, 3 };
|
||||
PacketRateLimit msg_session_established_request_ratelimit{ 1000, 3 };
|
||||
PacketRateLimit gamer_info_request_ratelimit{ 1000, 3 };
|
||||
PacketRateLimit roaming_bubble_request_ratelimit{ 1000, 3 };
|
||||
};
|
||||
|
||||
struct Peer
|
||||
{
|
||||
rage::netIpAddress ip;
|
||||
|
||||
// There could be multiple gamers on the same IP address but we don't need to be that precise
|
||||
Gamer gamer;
|
||||
|
||||
Peer(rage::netIpAddress ip)
|
||||
: ip(ip)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
inline static std::vector<Peer> peers;
|
||||
|
||||
public:
|
||||
[[nodiscard]] static Peer* findPeer(rage::netIpAddress ip);
|
||||
[[nodiscard]] static Peer* findOrCreatePeer(rage::netIpAddress ip);
|
||||
[[nodiscard]] static Gamer* findGamerByRid2(int64_t rid_2);
|
||||
|
||||
static void onDiscoveredName(rage::netIpAddress ip, const char* name);
|
||||
static void onDiscoveredGamer(rage::netIpAddress ip, const rage::rlGamerInfo& gamerInfo);
|
||||
[[nodiscard]] static std::string getNameForUser(const rage::netIpAddress& ip);
|
||||
[[nodiscard]] static std::string getNameForUser(const Peer* peer, const rage::netIpAddress& ip);
|
||||
|
||||
static void deinit();
|
||||
};
|
||||
}
|