This commit is contained in:
expvintl 2024-10-16 11:20:42 +08:00
commit ce19babcf4
4231 changed files with 701180 additions and 0 deletions

11
.gitattributes vendored Normal file
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

BIN
Default Theme/Disabled.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Default Theme/Edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
Default Theme/Enabled.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
Default Theme/Friends.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
Default Theme/Link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
Default Theme/List.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

BIN
Default Theme/Search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Default Theme/Tabs/Game.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
Default Theme/Tabs/Self.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
Default Theme/Toggle On.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Default Theme/User.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
Default Theme/Users.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

1
Directory.Build.props Normal file
View File

@ -0,0 +1 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <EnableUnitySupport>true</EnableUnitySupport> </PropertyGroup> </Project>

2656
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View 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;
}

View 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>

View 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>

View 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
View 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.

View 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>

View 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>

View 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>

View 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();
}

View 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');

View File

@ -0,0 +1 @@
screen -dmS "guilded-bot" node index.js

View 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;
}

View File

@ -0,0 +1,5 @@
{
"require": {
"hell-sh/smw": "^1.0"
}
}

View 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";

View 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";

View 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";

View 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";

View 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";

View 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";

View 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");

View 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");
}

View 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);

View 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"

View File

@ -0,0 +1,5 @@
{
"require": {
"hell-sh/mail-transfer": "dev-senpai"
}
}

View 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();

View File

@ -0,0 +1,2 @@
+*.cpp
require ../Soup/soup

View File

@ -0,0 +1 @@
certbot certonly -m letsencrypt@sai.navy --agree-tos -d relay1.stand.gg --manual --preferred-challenges dns --force-interactive

View 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-----

View 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-----

View 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();
}

View File

@ -0,0 +1,3 @@
#!/bin/bash
screen -dmS "relayserver" ./relayserver

View 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");

View File

@ -0,0 +1,6 @@
#!/bin/bash
while true
do
php vpn-auth-updater.php
done

View 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");

View 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

View File

@ -0,0 +1,5 @@
#!/bin/bash
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
screen -dmS "auth-servant" sh run.sh

View 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);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

BIN
Special Characters/lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Special Characters/rs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

BIN
Special Characters/ws.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

76
Stand.cv Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

317
Stand/AbstractEntity.hpp Normal file
View 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

File diff suppressed because it is too large Load Diff

115
Stand/AbstractModel.hpp Normal file
View 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

File diff suppressed because it is too large Load Diff

386
Stand/AbstractPlayer.hpp Normal file
View 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());
}
}

View 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);
}
}

View 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
View 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
View 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
View 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();
};
}

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