Merge branch 'dev' into dev
This commit is contained in:
commit
d17334b11a
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@ -58,12 +58,12 @@ jobs:
|
|||||||
dir /s /b /a:-d build\win
|
dir /s /b /a:-d build\win
|
||||||
|
|
||||||
### remove linker files
|
### remove linker files
|
||||||
- name: Remove linker files
|
### - name: Remove linker files
|
||||||
shell: cmd
|
### shell: cmd
|
||||||
working-directory: ${{ github.workspace }}
|
### working-directory: ${{ github.workspace }}
|
||||||
run: |
|
### run: |
|
||||||
del /f /s /q build\win\*.exp,build\win\*.lib
|
### del /f /s /q build\win\*.exp,build\win\*.lib
|
||||||
exit /b 0
|
### exit /b 0
|
||||||
|
|
||||||
### package (release mode)
|
### package (release mode)
|
||||||
- name: Package build (release)
|
- name: Package build (release)
|
||||||
|
1675
CREDITS.md
1675
CREDITS.md
File diff suppressed because it is too large
Load Diff
@ -1,120 +1,117 @@
|
|||||||
@echo off
|
@echo off
|
||||||
setlocal
|
setlocal EnableDelayedExpansion
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
:: use 70%
|
set /a "MAX_THREADS=2"
|
||||||
set /a build_threads=2
|
|
||||||
if defined NUMBER_OF_PROCESSORS (
|
if defined NUMBER_OF_PROCESSORS (
|
||||||
set /a build_threads=NUMBER_OF_PROCESSORS*70/100
|
:: use 70%
|
||||||
|
set /a "MAX_THREADS=%NUMBER_OF_PROCESSORS% * 70 / 100"
|
||||||
|
if %MAX_THREADS% lss 1 (
|
||||||
|
set /a "MAX_THREADS=1"
|
||||||
)
|
)
|
||||||
if %build_threads% lss 1 (
|
|
||||||
set /a build_threads=1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set /a BUILD_DEPS=0
|
set /a "BUILD_DEPS=0"
|
||||||
|
|
||||||
:args_loop
|
:args_loop
|
||||||
if "%~1"=="" (
|
if "%~1" equ "" (
|
||||||
goto :args_loop_end
|
goto :args_loop_end
|
||||||
) else if "%~1"=="--deps" (
|
) else if "%~1" equ "--deps" (
|
||||||
set /a BUILD_DEPS=1
|
set /a "BUILD_DEPS=1"
|
||||||
) else if "%~1"=="--help" (
|
) else if "%~1" equ "--help" (
|
||||||
call :help_page
|
goto :help_page
|
||||||
goto :end_script
|
|
||||||
) else (
|
) else (
|
||||||
1>&2 echo "invalid arg %~1"
|
1>&2 echo: invalid arg %~1
|
||||||
goto :end_script_with_err
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
shift /1
|
shift /1
|
||||||
goto :args_loop
|
goto :args_loop
|
||||||
:args_loop_end
|
|
||||||
|
|
||||||
set "premake_exe=third-party\common\win\premake\premake5.exe"
|
:args_loop_end
|
||||||
if not exist "%premake_exe%" (
|
:: check premake
|
||||||
1>&2 echo "preamke wasn't found"
|
set "PREMAKE_EXE=third-party\common\win\premake\premake5.exe"
|
||||||
|
if not exist "%PREMAKE_EXE%" (
|
||||||
|
1>&2 echo: premake wasn't found
|
||||||
goto :end_script_with_err
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
:: build deps
|
:: build deps
|
||||||
if %BUILD_DEPS%==0 (
|
if %BUILD_DEPS% equ 1 (
|
||||||
goto :build_deps_end
|
|
||||||
)
|
|
||||||
set "CMAKE_GENERATOR=Visual Studio 17 2022"
|
set "CMAKE_GENERATOR=Visual Studio 17 2022"
|
||||||
call "%premake_exe%" --file="premake5-deps.lua" --all-ext --all-build --64-build --32-build --verbose --clean --os=windows vs2022
|
call "%PREMAKE_EXE%" --file="premake5-deps.lua" --64-build --32-build --all-ext --all-build --j=2 --verbose --clean --os=windows vs2022
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
goto :end_script_with_err
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
:build_deps_end
|
goto :end_script
|
||||||
|
)
|
||||||
|
|
||||||
:: VS WHERE to get MSBUILD
|
:: check vswhere
|
||||||
set "vswhere_exe=third-party\common\win\vswhere\vswhere.exe"
|
set "VSWHERE_EXE=third-party\common\win\vswhere\vswhere.exe"
|
||||||
if not exist "%vswhere_exe%" (
|
if not exist "%VSWHERE_EXE%" (
|
||||||
1>&2 echo "vswhere wasn't found"
|
1>&2 echo: vswhere wasn't found
|
||||||
goto :end_script_with_err
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
:: .sln file
|
:: check msbuild
|
||||||
set "sln_file=build\project\vs2022\win\gbe.sln"
|
set "MSBUILD_EXE="
|
||||||
|
for /f "tokens=* delims=" %%A in ('"%VSWHERE_EXE%" -prerelease -latest -nocolor -nologo -property installationPath 2^>nul') do (
|
||||||
:: get msbuild path
|
set "MSBUILD_EXE=%%~A\MSBuild\Current\Bin\MSBuild.exe"
|
||||||
set "my_vs_path="
|
|
||||||
for /f "tokens=* delims=" %%A in ('"%vswhere_exe%" -prerelease -latest -nocolor -nologo -property installationPath 2^>nul') do (
|
|
||||||
set "my_vs_path=%%~A\MSBuild\Current\Bin\MSBuild.exe"
|
|
||||||
)
|
)
|
||||||
if not exist "%my_vs_path%" (
|
if not exist "%MSBUILD_EXE%" (
|
||||||
1>&2 echo "MSBuild wasn't found"
|
1>&2 echo: MSBuild wasn't found
|
||||||
goto :end_script_with_err
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
call "%premake_exe%" --file="premake5.lua" --dosstub --winrsrc --winsign --genproto --os=windows vs2022
|
:: create .sln
|
||||||
if %errorlevel% neq 0 (
|
call "%PREMAKE_EXE%" --file="premake5.lua" --genproto --dosstub --winrsrc --winsign --os=windows vs2022
|
||||||
goto :end_script_with_err
|
|
||||||
)
|
|
||||||
if not exist "%sln_file%" (
|
|
||||||
1>&2 echo "project solution file wasn't found"
|
|
||||||
goto :end_script_with_err
|
|
||||||
)
|
|
||||||
|
|
||||||
:: -v:n make it so we can actually see what commands it runs
|
|
||||||
echo: & echo building debug x64
|
|
||||||
call "%my_vs_path%" /nologo "%sln_file%" /p:Configuration=debug /p:Platform=x64 -v:n -m:%build_threads%
|
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
goto :end_script_with_err
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
echo: & echo building debug x32
|
:: check .sln
|
||||||
call "%my_vs_path%" /nologo "%sln_file%" /p:Configuration=debug /p:Platform=Win32 -v:n -m:%build_threads%
|
set "SLN_FILE=build\project\vs2022\win\gbe.sln"
|
||||||
if %errorlevel% neq 0 (
|
if not exist "%SLN_FILE%" (
|
||||||
|
1>&2 echo: .sln file wasn't found
|
||||||
goto :end_script_with_err
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
echo: & echo building release x64
|
:: build .sln
|
||||||
call "%my_vs_path%" /nologo "%sln_file%" /p:Configuration=release /p:Platform=x64 -v:n -m:%build_threads%
|
set "BUILD_TYPES=release debug"
|
||||||
|
set "BUILD_PLATFORMS=x64 Win32"
|
||||||
|
set "BUILD_TARGETS=api_regular api_experimental steamclient_experimental_stub steamclient_experimental steamclient_experimental_loader steamclient_experimental_extra lib_game_overlay_renderer tool_lobby_connect tool_generate_interfaces"
|
||||||
|
|
||||||
|
for %%A in (%BUILD_TYPES%) do (
|
||||||
|
set "BUILD_TYPE=%%A"
|
||||||
|
for %%B in (%BUILD_PLATFORMS%) do (
|
||||||
|
set "BUILD_PLATFORM=%%B"
|
||||||
|
for %%C in (%BUILD_TARGETS%) do (
|
||||||
|
set "BUILD_TARGET=%%C"
|
||||||
|
echo. & echo: building !BUILD_TARGET! !BUILD_TYPE! !BUILD_PLATFORM!
|
||||||
|
call "%MSBUILD_EXE%" /nologo -m:%MAX_THREADS% -v:n /p:Configuration=!BUILD_TYPE!,Platform=!BUILD_PLATFORM! /target:!BUILD_TARGET! "%SLN_FILE%"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
goto :end_script_with_err
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
)
|
||||||
echo: & echo building release x32
|
)
|
||||||
call "%my_vs_path%" /nologo "%sln_file%" /p:Configuration=release /p:Platform=Win32 -v:n -m:%build_threads%
|
|
||||||
if %errorlevel% neq 0 (
|
|
||||||
goto :end_script_with_err
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
goto :end_script
|
||||||
|
|
||||||
:: if all ok
|
:: exit without error
|
||||||
:end_script
|
:end_script
|
||||||
endlocal
|
endlocal
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
|
||||||
:: exit with error
|
:: exit with error
|
||||||
:end_script_with_err
|
:end_script_with_err
|
||||||
endlocal
|
endlocal
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
|
:: show help page
|
||||||
:help_page
|
:help_page
|
||||||
echo:
|
echo: "%~nx0" [switches]
|
||||||
echo "%~nx0" [switches]
|
echo: switches:
|
||||||
echo switches:
|
echo: --deps: rebuild third-party dependencies
|
||||||
echo --deps: rebuild third-party dependencies
|
echo: --help: show this page
|
||||||
echo --help: show this page
|
goto :end_script
|
||||||
exit /b 0
|
|
||||||
|
@ -1 +1,3 @@
|
|||||||
build_win_premake.bat --deps
|
@echo off
|
||||||
|
|
||||||
|
call "build_win_premake.bat" --deps
|
||||||
|
60
dev.notes/how to add a branch as a submodule.md
Normal file
60
dev.notes/how to add a branch as a submodule.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
1. create an orphan branch
|
||||||
|
```shell
|
||||||
|
git checkout --orphan 'third-party/my-branch'
|
||||||
|
```
|
||||||
|
2. make sure no files are staged yet
|
||||||
|
```shell
|
||||||
|
git rm -r -f --cached .
|
||||||
|
```
|
||||||
|
3. copy some new files (or add ones that already exist)
|
||||||
|
```shell
|
||||||
|
cp ~/myfile.txt ./
|
||||||
|
```
|
||||||
|
4. stage the required files
|
||||||
|
```shell
|
||||||
|
git add myfile.txt
|
||||||
|
```
|
||||||
|
you can also stage all files in the current directory
|
||||||
|
```shell
|
||||||
|
git add .
|
||||||
|
```
|
||||||
|
5. commit the files
|
||||||
|
```shell
|
||||||
|
git commit -m 'my commit msg'
|
||||||
|
```
|
||||||
|
6. add the branch as submodule
|
||||||
|
```shell
|
||||||
|
git -c protocol.file.allow=always submodule add -f -b 'third-party/my-branch' file://"$(pwd)" 'my-relative-dir/without/dot/at/beginning'
|
||||||
|
```
|
||||||
|
git by default disallow local repos, this option `protocol.file.allow=always` forces git to allow it
|
||||||
|
this will:
|
||||||
|
- look for a **local** repo in the directory shown by `pwd` (current folder),
|
||||||
|
notice how we don't simply use `./` because if we did that git will try to use the `origin` of the repo,
|
||||||
|
and since the origin (github/gitlab/etc...) doesn't have this branch yet it will fail, using the file protocol (`file://absolute_path`) forces git to use the local repo files
|
||||||
|
you can of course push the branch to origin before doing this step
|
||||||
|
- look for a branch named `third-party/my-branch`
|
||||||
|
- create a submodule pointing at this branch inside a new folder `my-relative-dir/without/dot/at/beginning`
|
||||||
|
notice that the new folder does **not** start with `./` as usual
|
||||||
|
7. fix the submodule path
|
||||||
|
after the last command, the file `.gitmodules` will point at the absolute path of the repo on disk, fix it to be relative
|
||||||
|
```shell
|
||||||
|
git -c protocol.file.allow=always submodule add -f -b 'third-party/my-branch' ./ 'my-relative-dir/without/dot/at/beginning'
|
||||||
|
```
|
||||||
|
this time git won't try to grab the data from origin, it will just edit `.gitmodules`
|
||||||
|
8. new git management objects/files will be staged, you can view them
|
||||||
|
```shell
|
||||||
|
git status
|
||||||
|
```
|
||||||
|
possible output
|
||||||
|
```shell
|
||||||
|
On branch third-party/my-branch
|
||||||
|
|
||||||
|
Changes to be committed:
|
||||||
|
(use "git restore --staged <file>..." to unstage)
|
||||||
|
modified: .gitmodules
|
||||||
|
new file: third-party/my-branch
|
||||||
|
```
|
||||||
|
9. commit these 2 files
|
||||||
|
```shell
|
||||||
|
git commit -m 'add branch third-party/my-branch as submodule'
|
||||||
|
```
|
@ -29,7 +29,7 @@ const std::chrono::time_point<std::chrono::high_resolution_clock> startup_counte
|
|||||||
const std::chrono::time_point<std::chrono::system_clock> startup_time = std::chrono::system_clock::now();
|
const std::chrono::time_point<std::chrono::system_clock> startup_time = std::chrono::system_clock::now();
|
||||||
|
|
||||||
#ifndef EMU_RELEASE_BUILD
|
#ifndef EMU_RELEASE_BUILD
|
||||||
dbg_log dbg_logger(get_full_program_path() + "STEAM_LOG.txt");
|
dbg_log dbg_logger(get_full_program_path() + "STEAM_LOG_" + std::to_string(common_helpers::rand_number(UINT32_MAX)) + ".log");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1333,7 +1333,13 @@ STEAMCLIENT_API steam_bool Steam_GetAPICallResult( HSteamPipe hSteamPipe, SteamA
|
|||||||
STEAMCLIENT_API void *CreateInterface( const char *pName, int *pReturnCode )
|
STEAMCLIENT_API void *CreateInterface( const char *pName, int *pReturnCode )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("%s %p", pName, pReturnCode);
|
PRINT_DEBUG("%s %p", pName, pReturnCode);
|
||||||
return create_client_interface(pName);
|
auto ptr = create_client_interface(pName);
|
||||||
|
if (ptr) {
|
||||||
|
if (pReturnCode) *pReturnCode = 1;
|
||||||
|
} else {
|
||||||
|
if (pReturnCode) *pReturnCode = 0;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
STEAMCLIENT_API void Breakpad_SteamMiniDumpInit( uint32 a, const char *b, const char *c )
|
STEAMCLIENT_API void Breakpad_SteamMiniDumpInit( uint32 a, const char *b, const char *c )
|
||||||
|
@ -208,11 +208,15 @@ private:
|
|||||||
std::map<std::string, Leaderboard_config> leaderboards{};
|
std::map<std::string, Leaderboard_config> leaderboards{};
|
||||||
std::map<std::string, Stat_config> stats{};
|
std::map<std::string, Stat_config> stats{};
|
||||||
|
|
||||||
|
std::map<size_t, struct Image_Data> images{};
|
||||||
|
|
||||||
//supported languages
|
//supported languages
|
||||||
std::set<std::string> supported_languages_set{};
|
std::set<std::string> supported_languages_set{};
|
||||||
std::string supported_languages{};
|
std::string supported_languages{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
constexpr const static int INVALID_IMAGE_HANDLE = 0;
|
||||||
|
|
||||||
//Depots
|
//Depots
|
||||||
std::vector<DepotId_t> depots{};
|
std::vector<DepotId_t> depots{};
|
||||||
|
|
||||||
@ -253,6 +257,9 @@ public:
|
|||||||
// when a stat that's tied to an achievement gets a new value, should the emu save that progress only if it's higher?
|
// when a stat that's tied to an achievement gets a new value, should the emu save that progress only if it's higher?
|
||||||
// the stat itself is always saved regardless of that flag, only affects the achievement progress
|
// the stat itself is always saved regardless of that flag, only affects the achievement progress
|
||||||
bool save_only_higher_stat_achievement_progress = true;
|
bool save_only_higher_stat_achievement_progress = true;
|
||||||
|
// the emulator loads the achievements icons is memory mainly for `ISteamUserStats::GetAchievementIcon()`
|
||||||
|
// true means load icons lazily when they are requested, otherwise load icons as soon as the interface ISteamUserStats is initialized
|
||||||
|
bool lazy_load_achievements_icons = true;
|
||||||
|
|
||||||
// bypass to make SetAchievement() always return true, prevent some games from breaking
|
// bypass to make SetAchievement() always return true, prevent some games from breaking
|
||||||
bool achievement_bypass = false;
|
bool achievement_bypass = false;
|
||||||
@ -265,8 +272,6 @@ public:
|
|||||||
// enable owning Steam Applications IDs (mostly builtin apps + dedicated servers)
|
// enable owning Steam Applications IDs (mostly builtin apps + dedicated servers)
|
||||||
bool enable_builtin_preowned_ids = false;
|
bool enable_builtin_preowned_ids = false;
|
||||||
|
|
||||||
std::map<int, struct Image_Data> images{};
|
|
||||||
|
|
||||||
//subscribed lobby/group ids
|
//subscribed lobby/group ids
|
||||||
std::set<uint64> subscribed_groups{};
|
std::set<uint64> subscribed_groups{};
|
||||||
std::vector<Group_Clans> subscribed_groups_clans{};
|
std::vector<Group_Clans> subscribed_groups_clans{};
|
||||||
@ -295,6 +300,9 @@ public:
|
|||||||
// synchronize user stats/achievements with game servers as soon as possible instead of caching them.
|
// synchronize user stats/achievements with game servers as soon as possible instead of caching them.
|
||||||
bool immediate_gameserver_stats = false;
|
bool immediate_gameserver_stats = false;
|
||||||
|
|
||||||
|
// steam_game_stats
|
||||||
|
std::string steam_game_stats_reports_dir{};
|
||||||
|
|
||||||
//overlay
|
//overlay
|
||||||
bool disable_overlay = true;
|
bool disable_overlay = true;
|
||||||
int overlay_hook_delay_sec = 0; // "Saints Row (2022)" needs a lot of time to initialize, otherwise detection will fail
|
int overlay_hook_delay_sec = 0; // "Saints Row (2022)" needs a lot of time to initialize, otherwise detection will fail
|
||||||
@ -383,6 +391,7 @@ public:
|
|||||||
|
|
||||||
//images
|
//images
|
||||||
int add_image(const std::string &data, uint32 width, uint32 height);
|
int add_image(const std::string &data, uint32 width, uint32 height);
|
||||||
|
Image_Data* get_image(int handle);
|
||||||
|
|
||||||
// overlay auto accept stuff
|
// overlay auto accept stuff
|
||||||
void acceptAnyOverlayInvites(bool value);
|
void acceptAnyOverlayInvites(bool value);
|
||||||
|
@ -64,11 +64,14 @@ private:
|
|||||||
|
|
||||||
struct Session_t
|
struct Session_t
|
||||||
{
|
{
|
||||||
|
bool ended = false;
|
||||||
|
bool saved_to_disk = false;
|
||||||
|
uint64 account_id{};
|
||||||
|
|
||||||
EGameStatsAccountType nAccountType{};
|
EGameStatsAccountType nAccountType{};
|
||||||
RTime32 rtTimeStarted{};
|
RTime32 rtTimeStarted{};
|
||||||
RTime32 rtTimeEnded{};
|
RTime32 rtTimeEnded{};
|
||||||
int nReasonCode{};
|
int nReasonCode{};
|
||||||
bool ended = false;
|
|
||||||
std::map<std::string, Attribute_t> attributes{};
|
std::map<std::string, Attribute_t> attributes{};
|
||||||
|
|
||||||
std::vector<std::pair<std::string, Table_t>> tables{};
|
std::vector<std::pair<std::string, Table_t>> tables{};
|
||||||
@ -90,6 +93,8 @@ private:
|
|||||||
Attribute_t *get_or_create_row_att(uint64 ulRowID, const char *att_name, Table_t &table, AttributeType_t type_if_create);
|
Attribute_t *get_or_create_row_att(uint64 ulRowID, const char *att_name, Table_t &table, AttributeType_t type_if_create);
|
||||||
Session_t* get_last_active_session();
|
Session_t* get_last_active_session();
|
||||||
|
|
||||||
|
std::string sanitize_csv_value(std::string_view value);
|
||||||
|
void save_session_to_disk(Steam_GameStats::Session_t &session, uint64 session_id);
|
||||||
void steam_run_callback();
|
void steam_run_callback();
|
||||||
|
|
||||||
// user connect/disconnect
|
// user connect/disconnect
|
||||||
|
@ -30,12 +30,15 @@ struct Steam_Http_Request {
|
|||||||
bool requires_valid_ssl = false;
|
bool requires_valid_ssl = false;
|
||||||
|
|
||||||
constexpr const static char STEAM_DEFAULT_USER_AGENT[] = "Valve/Steam HTTP Client 1.0";
|
constexpr const static char STEAM_DEFAULT_USER_AGENT[] = "Valve/Steam HTTP Client 1.0";
|
||||||
// GET or POST parameter value on the request
|
// check Steam_HTTP::SetHTTPRequestHeaderValue() and make sure to bypass the ones that should be reserved
|
||||||
std::map<std::string, std::string> headers{
|
std::map<std::string, std::string> headers{
|
||||||
{ "User-Agent", STEAM_DEFAULT_USER_AGENT },
|
{ "User-Agent", STEAM_DEFAULT_USER_AGENT },
|
||||||
|
{ "Cache-Control", "max-age=0" },
|
||||||
|
{ "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" },
|
||||||
|
{ "Upgrade-Insecure-Requests", "1" },
|
||||||
};
|
};
|
||||||
|
|
||||||
// GET or POST parameter value on the request
|
// GET or POST parameter value of the request
|
||||||
std::map<std::string, std::string> get_or_post_params{};
|
std::map<std::string, std::string> get_or_post_params{};
|
||||||
std::string post_raw{};
|
std::string post_raw{};
|
||||||
|
|
||||||
@ -64,7 +67,7 @@ public ISteamHTTP
|
|||||||
std::vector<Steam_Http_Request> requests{};
|
std::vector<Steam_Http_Request> requests{};
|
||||||
|
|
||||||
Steam_Http_Request *get_request(HTTPRequestHandle hRequest);
|
Steam_Http_Request *get_request(HTTPRequestHandle hRequest);
|
||||||
void online_http_request(Steam_Http_Request *request, SteamAPICall_t *pCallHandle);
|
void online_http_request(Steam_Http_Request *request, SteamAPICall_t call_res_id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Steam_HTTP(class Settings *settings, class Networking *network, class SteamCallResults *callback_results, class SteamCallBacks *callbacks);
|
Steam_HTTP(class Settings *settings, class Networking *network, class SteamCallResults *callback_results, class SteamCallBacks *callbacks);
|
||||||
|
@ -81,6 +81,8 @@ public ISteamNetworkingSockets004,
|
|||||||
public ISteamNetworkingSockets006,
|
public ISteamNetworkingSockets006,
|
||||||
public ISteamNetworkingSockets008,
|
public ISteamNetworkingSockets008,
|
||||||
public ISteamNetworkingSockets009,
|
public ISteamNetworkingSockets009,
|
||||||
|
public ISteamNetworkingSockets010,
|
||||||
|
public ISteamNetworkingSockets011,
|
||||||
public ISteamNetworkingSockets
|
public ISteamNetworkingSockets
|
||||||
{
|
{
|
||||||
class Settings *settings{};
|
class Settings *settings{};
|
||||||
@ -488,6 +490,9 @@ public:
|
|||||||
/// - k_EResultInvalidParam - nLanes is bad
|
/// - k_EResultInvalidParam - nLanes is bad
|
||||||
EResult GetConnectionRealTimeStatus( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus, int nLanes, SteamNetConnectionRealTimeLaneStatus_t *pLanes );
|
EResult GetConnectionRealTimeStatus( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus, int nLanes, SteamNetConnectionRealTimeLaneStatus_t *pLanes );
|
||||||
|
|
||||||
|
// based on reversing the vftable returned from original steamclient64.dll
|
||||||
|
bool GetConnectionRealTimeStatus_old( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus );
|
||||||
|
|
||||||
/// Fetch the next available message(s) from the socket, if any.
|
/// Fetch the next available message(s) from the socket, if any.
|
||||||
/// Returns the number of messages returned into your array, up to nMaxMessages.
|
/// Returns the number of messages returned into your array, up to nMaxMessages.
|
||||||
/// If the connection handle is invalid, -1 is returned.
|
/// If the connection handle is invalid, -1 is returned.
|
||||||
|
@ -77,6 +77,7 @@ public ISteamRemoteStorage011,
|
|||||||
public ISteamRemoteStorage012,
|
public ISteamRemoteStorage012,
|
||||||
public ISteamRemoteStorage013,
|
public ISteamRemoteStorage013,
|
||||||
public ISteamRemoteStorage014,
|
public ISteamRemoteStorage014,
|
||||||
|
public ISteamRemoteStorage015,
|
||||||
public ISteamRemoteStorage
|
public ISteamRemoteStorage
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -44,6 +44,7 @@ public ISteamUGC007,
|
|||||||
public ISteamUGC008,
|
public ISteamUGC008,
|
||||||
public ISteamUGC009,
|
public ISteamUGC009,
|
||||||
public ISteamUGC010,
|
public ISteamUGC010,
|
||||||
|
public ISteamUGC011,
|
||||||
public ISteamUGC012,
|
public ISteamUGC012,
|
||||||
public ISteamUGC013,
|
public ISteamUGC013,
|
||||||
public ISteamUGC014,
|
public ISteamUGC014,
|
||||||
|
@ -71,6 +71,7 @@ public ISteamUserStats
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto achievements_user_file = "achievements.json";
|
static constexpr auto achievements_user_file = "achievements.json";
|
||||||
|
static constexpr int UNLOADED_ACH_ICON = -1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -94,6 +95,8 @@ private:
|
|||||||
nlohmann::json defined_achievements{};
|
nlohmann::json defined_achievements{};
|
||||||
nlohmann::json user_achievements{};
|
nlohmann::json user_achievements{};
|
||||||
std::vector<std::string> sorted_achievement_names{};
|
std::vector<std::string> sorted_achievement_names{};
|
||||||
|
bool achievements_icons_loaded = false;
|
||||||
|
|
||||||
std::map<std::string, int32> stats_cache_int{};
|
std::map<std::string, int32> stats_cache_int{};
|
||||||
std::map<std::string, float> stats_cache_float{};
|
std::map<std::string, float> stats_cache_float{};
|
||||||
|
|
||||||
@ -109,6 +112,8 @@ private:
|
|||||||
void load_achievements();
|
void load_achievements();
|
||||||
void save_achievements();
|
void save_achievements();
|
||||||
|
|
||||||
|
int load_ach_icon(nlohmann::json &defined_ach, bool achieved);
|
||||||
|
|
||||||
nlohmann::detail::iter_impl<nlohmann::json> defined_achievements_find(const std::string &key);
|
nlohmann::detail::iter_impl<nlohmann::json> defined_achievements_find(const std::string &key);
|
||||||
std::string get_value_for_language(const nlohmann::json &json, std::string_view key, std::string_view language);
|
std::string get_value_for_language(const nlohmann::json &json, std::string_view key, std::string_view language);
|
||||||
|
|
||||||
@ -132,6 +137,7 @@ private:
|
|||||||
InternalSetResult<bool> clear_achievement_internal( const char *pchName );
|
InternalSetResult<bool> clear_achievement_internal( const char *pchName );
|
||||||
|
|
||||||
void send_updated_stats();
|
void send_updated_stats();
|
||||||
|
void load_achievements_icons();
|
||||||
void steam_run_callback();
|
void steam_run_callback();
|
||||||
|
|
||||||
// requests from server
|
// requests from server
|
||||||
@ -207,7 +213,9 @@ public:
|
|||||||
// specified achievement.
|
// specified achievement.
|
||||||
int GetAchievementIcon( const char *pchName );
|
int GetAchievementIcon( const char *pchName );
|
||||||
|
|
||||||
std::string get_achievement_icon_name( const char *pchName, bool pbAchieved );
|
int get_achievement_icon_handle( const std::string &ach_name, bool pbAchieved );
|
||||||
|
|
||||||
|
std::string get_achievement_icon_name( const char *pchName, bool achieved );
|
||||||
|
|
||||||
|
|
||||||
// Get general attributes for an achievement. Accepts the following keys:
|
// Get general attributes for an achievement. Accepts the following keys:
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define STBI_ONLY_JPEG
|
#define STBI_ONLY_JPEG
|
||||||
#if defined(__WINDOWS__)
|
#if defined(__WINDOWS__)
|
||||||
#define STBI_WINDOWS_UTF8
|
#define STBI_WINDOWS_UTF8
|
||||||
|
#define STBIW_WINDOWS_UTF8
|
||||||
#endif
|
#endif
|
||||||
#include "stb/stb_image.h"
|
#include "stb/stb_image.h"
|
||||||
|
|
||||||
@ -31,7 +32,7 @@
|
|||||||
#include "stb/stb_image_write.h"
|
#include "stb/stb_image_write.h"
|
||||||
|
|
||||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||||
#include "stb/stb_image_resize.h"
|
#include "stb/stb_image_resize2.h"
|
||||||
|
|
||||||
struct File_Data {
|
struct File_Data {
|
||||||
std::string name{};
|
std::string name{};
|
||||||
@ -859,8 +860,8 @@ std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_pa
|
|||||||
std::vector<image_pixel_t> res{};
|
std::vector<image_pixel_t> res{};
|
||||||
int width{}, height{};
|
int width{}, height{};
|
||||||
image_pixel_t* img = (image_pixel_t*)stbi_load(image_path.c_str(), &width, &height, nullptr, 4);
|
image_pixel_t* img = (image_pixel_t*)stbi_load(image_path.c_str(), &width, &height, nullptr, 4);
|
||||||
if (img != nullptr)
|
PRINT_DEBUG("stbi_load('%s') -> %s", image_path.c_str(), (img ? "loaded" : stbi_failure_reason()));
|
||||||
{
|
if (img) {
|
||||||
res.resize(width * height);
|
res.resize(width * height);
|
||||||
std::copy(img, img + width * height, res.begin());
|
std::copy(img, img + width * height, res.begin());
|
||||||
|
|
||||||
@ -875,21 +876,20 @@ std::string Local_Storage::load_image_resized(std::string const& image_path, std
|
|||||||
{
|
{
|
||||||
std::string resized_image{};
|
std::string resized_image{};
|
||||||
const size_t resized_img_size = resolution * resolution * 4;
|
const size_t resized_img_size = resolution * resolution * 4;
|
||||||
|
if (image_path.size()) {
|
||||||
if (image_path.length() > 0) {
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
unsigned char *img = stbi_load(image_path.c_str(), &width, &height, nullptr, 4);
|
unsigned char *img = stbi_load(image_path.c_str(), &width, &height, nullptr, 4);
|
||||||
PRINT_DEBUG("stbi_load('%s') -> %s", image_path.c_str(), (img == nullptr ? stbi_failure_reason() : "loaded"));
|
PRINT_DEBUG("stbi_load('%s') -> %s", image_path.c_str(), (img ? "loaded" : stbi_failure_reason()));
|
||||||
if (img != nullptr) {
|
if (img) {
|
||||||
std::vector<char> out_resized(resized_img_size);
|
std::vector<char> out_resized(resized_img_size);
|
||||||
stbir_resize_uint8(img, width, height, 0, (unsigned char*)&out_resized[0], resolution, resolution, 0, 4);
|
stbir_resize_uint8_linear(img, width, height, 0, (unsigned char*)&out_resized[0], resolution, resolution, 0, STBIR_RGBA);
|
||||||
resized_image = std::string((char*)&out_resized[0], out_resized.size());
|
resized_image = std::string((char*)&out_resized[0], out_resized.size());
|
||||||
stbi_image_free(img);
|
stbi_image_free(img);
|
||||||
}
|
}
|
||||||
} else if (image_data.length() > 0) {
|
} else if (image_data.size()) {
|
||||||
std::vector<char> out_resized(resized_img_size);
|
std::vector<char> out_resized(resized_img_size);
|
||||||
stbir_resize_uint8((unsigned char*)image_data.c_str(), 184, 184, 0, (unsigned char*)&out_resized[0], resolution, resolution, 0, 4);
|
stbir_resize_uint8_linear((unsigned char*)image_data.c_str(), 184, 184, 0, (unsigned char*)&out_resized[0], resolution, resolution, 0, STBIR_RGBA);
|
||||||
resized_image = std::string((char*)&out_resized[0], out_resized.size());
|
resized_image = std::string((char*)&out_resized[0], out_resized.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ static void run_at_startup()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(STEAM_WIN32)
|
#if defined(STEAM_WIN32)
|
||||||
WSADATA wsaData;
|
WSADATA wsaData{};
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
|
||||||
PRINT_DEBUG("Networking WSAStartup error");
|
PRINT_DEBUG("Networking WSAStartup error");
|
||||||
return;
|
return;
|
||||||
@ -257,8 +257,13 @@ static void run_at_startup()
|
|||||||
|
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
//hack: the game Full Mojo Rampage calls WSACleanup on startup so we call WSAStartup a few times so it doesn't get deallocated.
|
//hack: the game Full Mojo Rampage calls WSACleanup on startup so we call WSAStartup a few times so it doesn't get deallocated.
|
||||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
WSADATA wsaData{};
|
||||||
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
|
||||||
|
PRINT_DEBUG("Networking WSAStartup error");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
PRINT_DEBUG("Networking WSAStartup success!");
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -353,13 +353,37 @@ std::map<std::string, Stat_config>::const_iterator Settings::setStatDefiniton(co
|
|||||||
|
|
||||||
int Settings::add_image(const std::string &data, uint32 width, uint32 height)
|
int Settings::add_image(const std::string &data, uint32 width, uint32 height)
|
||||||
{
|
{
|
||||||
int last = static_cast<int>(images.size()) + 1;
|
auto previous_it = std::find_if(images.begin(), images.end(), [&](const std::pair<const size_t, Image_Data> &item) {
|
||||||
struct Image_Data dt;
|
return item.second.data == data
|
||||||
|
&& item.second.height == height
|
||||||
|
&& item.second.width == width;
|
||||||
|
});
|
||||||
|
if (images.end() != previous_it) {
|
||||||
|
return static_cast<int>(previous_it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Image_Data dt{};
|
||||||
dt.width = width;
|
dt.width = width;
|
||||||
dt.height = height;
|
dt.height = height;
|
||||||
dt.data = data;
|
dt.data = data;
|
||||||
images[last] = dt;
|
|
||||||
return last;
|
auto new_handle = images.size() + 1; // never return 0, it is a bad handle for most ISteamUserStats APIs
|
||||||
|
images[new_handle] = dt;
|
||||||
|
|
||||||
|
return static_cast<int>(new_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
Image_Data* Settings::get_image(int handle)
|
||||||
|
{
|
||||||
|
if (INVALID_IMAGE_HANDLE == handle) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto image_it = images.find(handle);
|
||||||
|
if (images.end() == image_it) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &image_it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1345,6 +1345,20 @@ static void parse_overlay_general_config(class Settings *settings_client, class
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// main::misc::steam_game_stats_reports_dir
|
||||||
|
static void parse_steam_game_stats_reports_dir(class Settings *settings_client, class Settings *settings_server)
|
||||||
|
{
|
||||||
|
std::string line(common_helpers::string_strip(ini.GetValue("main::misc", "steam_game_stats_reports_dir", "")));
|
||||||
|
if (line.size()) {
|
||||||
|
auto folder = common_helpers::to_absolute(line, get_full_program_path());
|
||||||
|
if (folder.size()) {
|
||||||
|
PRINT_DEBUG("ISteamGameStats reports will be saved to '%s'", folder.c_str());
|
||||||
|
settings_client->steam_game_stats_reports_dir = folder;
|
||||||
|
settings_server->steam_game_stats_reports_dir = folder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// mainly enable/disable features
|
// mainly enable/disable features
|
||||||
static void parse_simple_features(class Settings *settings_client, class Settings *settings_server)
|
static void parse_simple_features(class Settings *settings_client, class Settings *settings_server)
|
||||||
{
|
{
|
||||||
@ -1364,18 +1378,6 @@ static void parse_simple_features(class Settings *settings_client, class Setting
|
|||||||
settings_client->steam_deck = ini.GetBoolValue("main::general", "steam_deck", settings_client->steam_deck);
|
settings_client->steam_deck = ini.GetBoolValue("main::general", "steam_deck", settings_client->steam_deck);
|
||||||
settings_server->steam_deck = ini.GetBoolValue("main::general", "steam_deck", settings_server->steam_deck);
|
settings_server->steam_deck = ini.GetBoolValue("main::general", "steam_deck", settings_server->steam_deck);
|
||||||
|
|
||||||
settings_client->disable_leaderboards_create_unknown = ini.GetBoolValue("main::general", "disable_leaderboards_create_unknown", settings_client->disable_leaderboards_create_unknown);
|
|
||||||
settings_server->disable_leaderboards_create_unknown = ini.GetBoolValue("main::general", "disable_leaderboards_create_unknown", settings_server->disable_leaderboards_create_unknown);
|
|
||||||
|
|
||||||
settings_client->allow_unknown_stats = ini.GetBoolValue("main::general", "allow_unknown_stats", settings_client->allow_unknown_stats);
|
|
||||||
settings_server->allow_unknown_stats = ini.GetBoolValue("main::general", "allow_unknown_stats", settings_server->allow_unknown_stats);
|
|
||||||
|
|
||||||
settings_client->stat_achievement_progress_functionality = ini.GetBoolValue("main::general", "stat_achievement_progress_functionality", settings_client->stat_achievement_progress_functionality);
|
|
||||||
settings_server->stat_achievement_progress_functionality = ini.GetBoolValue("main::general", "stat_achievement_progress_functionality", settings_server->stat_achievement_progress_functionality);
|
|
||||||
|
|
||||||
settings_client->save_only_higher_stat_achievement_progress = ini.GetBoolValue("main::general", "save_only_higher_stat_achievement_progress", settings_client->save_only_higher_stat_achievement_progress);
|
|
||||||
settings_server->save_only_higher_stat_achievement_progress = ini.GetBoolValue("main::general", "save_only_higher_stat_achievement_progress", settings_server->save_only_higher_stat_achievement_progress);
|
|
||||||
|
|
||||||
settings_client->immediate_gameserver_stats = ini.GetBoolValue("main::general", "immediate_gameserver_stats", settings_client->immediate_gameserver_stats);
|
settings_client->immediate_gameserver_stats = ini.GetBoolValue("main::general", "immediate_gameserver_stats", settings_client->immediate_gameserver_stats);
|
||||||
settings_server->immediate_gameserver_stats = ini.GetBoolValue("main::general", "immediate_gameserver_stats", settings_server->immediate_gameserver_stats);
|
settings_server->immediate_gameserver_stats = ini.GetBoolValue("main::general", "immediate_gameserver_stats", settings_server->immediate_gameserver_stats);
|
||||||
|
|
||||||
@ -1420,6 +1422,25 @@ static void parse_simple_features(class Settings *settings_client, class Setting
|
|||||||
settings_server->enable_builtin_preowned_ids = ini.GetBoolValue("main::misc", "enable_steam_preowned_ids", settings_server->enable_builtin_preowned_ids);
|
settings_server->enable_builtin_preowned_ids = ini.GetBoolValue("main::misc", "enable_steam_preowned_ids", settings_server->enable_builtin_preowned_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [main::stats]
|
||||||
|
static void parse_stats_features(class Settings *settings_client, class Settings *settings_server)
|
||||||
|
{
|
||||||
|
settings_client->disable_leaderboards_create_unknown = ini.GetBoolValue("main::stats", "disable_leaderboards_create_unknown", settings_client->disable_leaderboards_create_unknown);
|
||||||
|
settings_server->disable_leaderboards_create_unknown = ini.GetBoolValue("main::stats", "disable_leaderboards_create_unknown", settings_server->disable_leaderboards_create_unknown);
|
||||||
|
|
||||||
|
settings_client->allow_unknown_stats = ini.GetBoolValue("main::stats", "allow_unknown_stats", settings_client->allow_unknown_stats);
|
||||||
|
settings_server->allow_unknown_stats = ini.GetBoolValue("main::stats", "allow_unknown_stats", settings_server->allow_unknown_stats);
|
||||||
|
|
||||||
|
settings_client->stat_achievement_progress_functionality = ini.GetBoolValue("main::stats", "stat_achievement_progress_functionality", settings_client->stat_achievement_progress_functionality);
|
||||||
|
settings_server->stat_achievement_progress_functionality = ini.GetBoolValue("main::stats", "stat_achievement_progress_functionality", settings_server->stat_achievement_progress_functionality);
|
||||||
|
|
||||||
|
settings_client->save_only_higher_stat_achievement_progress = ini.GetBoolValue("main::stats", "save_only_higher_stat_achievement_progress", settings_client->save_only_higher_stat_achievement_progress);
|
||||||
|
settings_server->save_only_higher_stat_achievement_progress = ini.GetBoolValue("main::stats", "save_only_higher_stat_achievement_progress", settings_server->save_only_higher_stat_achievement_progress);
|
||||||
|
|
||||||
|
settings_client->lazy_load_achievements_icons = ini.GetBoolValue("main::stats", "lazy_load_achievements_icons", settings_client->lazy_load_achievements_icons);
|
||||||
|
settings_server->lazy_load_achievements_icons = ini.GetBoolValue("main::stats", "lazy_load_achievements_icons", settings_server->lazy_load_achievements_icons);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static std::map<SettingsItf, std::string> old_itfs_map{};
|
static std::map<SettingsItf, std::string> old_itfs_map{};
|
||||||
@ -1673,6 +1694,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
|
|||||||
settings_server->set_supported_languages(supported_languages);
|
settings_server->set_supported_languages(supported_languages);
|
||||||
|
|
||||||
parse_simple_features(settings_client, settings_server);
|
parse_simple_features(settings_client, settings_server);
|
||||||
|
parse_stats_features(settings_client, settings_server);
|
||||||
|
|
||||||
parse_dlc(settings_client, settings_server);
|
parse_dlc(settings_client, settings_server);
|
||||||
parse_installed_app_Ids(settings_client, settings_server);
|
parse_installed_app_Ids(settings_client, settings_server);
|
||||||
@ -1697,6 +1719,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
|
|||||||
|
|
||||||
parse_overlay_general_config(settings_client, settings_server);
|
parse_overlay_general_config(settings_client, settings_server);
|
||||||
load_overlay_appearance(settings_client, settings_server, local_storage);
|
load_overlay_appearance(settings_client, settings_server, local_storage);
|
||||||
|
parse_steam_game_stats_reports_dir(settings_client, settings_server);
|
||||||
|
|
||||||
*settings_client_out = settings_client;
|
*settings_client_out = settings_client;
|
||||||
*settings_server_out = settings_server;
|
*settings_server_out = settings_server;
|
||||||
|
@ -311,16 +311,16 @@ void *Steam_Client::GetISteamGenericInterface( HSteamUser hSteamUser, HSteamPipe
|
|||||||
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets004 *>( steam_networking_sockets_temp));
|
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets004 *>( steam_networking_sockets_temp));
|
||||||
} else if (strcmp(pchVersion, "SteamNetworkingSockets006") == 0) {
|
} else if (strcmp(pchVersion, "SteamNetworkingSockets006") == 0) {
|
||||||
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets006 *>( steam_networking_sockets_temp));
|
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets006 *>( steam_networking_sockets_temp));
|
||||||
|
} else if (strcmp(pchVersion, "SteamNetworkingSockets007") == 0) { // Not found in public Archive, real steamclient64.dll returns null
|
||||||
// SteamNetworkingSockets007 Not found in public Archive, must be between 1.47-1.48
|
return nullptr;
|
||||||
|
|
||||||
} else if (strcmp(pchVersion, "SteamNetworkingSockets008") == 0) {
|
} else if (strcmp(pchVersion, "SteamNetworkingSockets008") == 0) {
|
||||||
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets008 *>( steam_networking_sockets_temp));
|
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets008 *>( steam_networking_sockets_temp));
|
||||||
} else if (strcmp(pchVersion, "SteamNetworkingSockets009") == 0) {
|
} else if (strcmp(pchVersion, "SteamNetworkingSockets009") == 0) {
|
||||||
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets009 *>( steam_networking_sockets_temp));
|
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets009 *>( steam_networking_sockets_temp));
|
||||||
|
} else if (strcmp(pchVersion, "SteamNetworkingSockets010") == 0) { // Not found in public Archive, based on reversing
|
||||||
// SteamNetworkingSockets010-011 Not found in public Archive, must be between 1.52-1.53
|
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets010 *>( steam_networking_sockets_temp));
|
||||||
|
} else if (strcmp(pchVersion, "SteamNetworkingSockets011") == 0) { // Not found in public Archive, based on reversing, requested by appid 1492070
|
||||||
|
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets011 *>( steam_networking_sockets_temp));
|
||||||
} else if (strcmp(pchVersion, STEAMNETWORKINGSOCKETS_INTERFACE_VERSION) == 0) {
|
} else if (strcmp(pchVersion, STEAMNETWORKINGSOCKETS_INTERFACE_VERSION) == 0) {
|
||||||
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets *>( steam_networking_sockets_temp));
|
return reinterpret_cast<void *>(static_cast<ISteamNetworkingSockets *>( steam_networking_sockets_temp));
|
||||||
}
|
}
|
||||||
@ -572,9 +572,8 @@ ISteamRemoteStorage *Steam_Client::GetISteamRemoteStorage( HSteamUser hSteamuser
|
|||||||
return reinterpret_cast<ISteamRemoteStorage *>(static_cast<ISteamRemoteStorage013 *>(steam_remote_storage));
|
return reinterpret_cast<ISteamRemoteStorage *>(static_cast<ISteamRemoteStorage013 *>(steam_remote_storage));
|
||||||
} else if (strcmp(pchVersion, "STEAMREMOTESTORAGE_INTERFACE_VERSION014") == 0) {
|
} else if (strcmp(pchVersion, "STEAMREMOTESTORAGE_INTERFACE_VERSION014") == 0) {
|
||||||
return reinterpret_cast<ISteamRemoteStorage *>(static_cast<ISteamRemoteStorage014 *>(steam_remote_storage));
|
return reinterpret_cast<ISteamRemoteStorage *>(static_cast<ISteamRemoteStorage014 *>(steam_remote_storage));
|
||||||
|
} else if (strcmp(pchVersion, "STEAMREMOTESTORAGE_INTERFACE_VERSION015") == 0) { // Not found in public Archive, based on reversing
|
||||||
// STEAMREMOTESTORAGE_INTERFACE_VERSION015 Not found in public Archive, must be between 1.51-1.52
|
return reinterpret_cast<ISteamRemoteStorage *>(static_cast<ISteamRemoteStorage015 *>(steam_remote_storage));
|
||||||
|
|
||||||
} else if (strcmp(pchVersion, STEAMREMOTESTORAGE_INTERFACE_VERSION) == 0) {
|
} else if (strcmp(pchVersion, STEAMREMOTESTORAGE_INTERFACE_VERSION) == 0) {
|
||||||
return reinterpret_cast<ISteamRemoteStorage *>(static_cast<ISteamRemoteStorage *>(steam_remote_storage));
|
return reinterpret_cast<ISteamRemoteStorage *>(static_cast<ISteamRemoteStorage *>(steam_remote_storage));
|
||||||
}
|
}
|
||||||
@ -710,9 +709,8 @@ ISteamUGC *Steam_Client::GetISteamUGC( HSteamUser hSteamUser, HSteamPipe hSteamP
|
|||||||
return reinterpret_cast<ISteamUGC *>(static_cast<ISteamUGC009 *>(steam_ugc_temp));
|
return reinterpret_cast<ISteamUGC *>(static_cast<ISteamUGC009 *>(steam_ugc_temp));
|
||||||
} else if (strcmp(pchVersion, "STEAMUGC_INTERFACE_VERSION010") == 0) {
|
} else if (strcmp(pchVersion, "STEAMUGC_INTERFACE_VERSION010") == 0) {
|
||||||
return reinterpret_cast<ISteamUGC *>(static_cast<ISteamUGC010 *>(steam_ugc_temp));
|
return reinterpret_cast<ISteamUGC *>(static_cast<ISteamUGC010 *>(steam_ugc_temp));
|
||||||
|
} else if (strcmp(pchVersion, "STEAMUGC_INTERFACE_VERSION011") == 0) { // Not found in public Archive, based on reversing
|
||||||
// STEAMUGC_INTERFACE_VERSION011 Not found in public Archive, must be between 1.42-1.43
|
return reinterpret_cast<ISteamUGC *>(static_cast<ISteamUGC011 *>(steam_ugc_temp));
|
||||||
|
|
||||||
} else if (strcmp(pchVersion, "STEAMUGC_INTERFACE_VERSION012") == 0) {
|
} else if (strcmp(pchVersion, "STEAMUGC_INTERFACE_VERSION012") == 0) {
|
||||||
return reinterpret_cast<ISteamUGC *>(static_cast<ISteamUGC012 *>(steam_ugc_temp));
|
return reinterpret_cast<ISteamUGC *>(static_cast<ISteamUGC012 *>(steam_ugc_temp));
|
||||||
} else if (strcmp(pchVersion, "STEAMUGC_INTERFACE_VERSION013") == 0) {
|
} else if (strcmp(pchVersion, "STEAMUGC_INTERFACE_VERSION013") == 0) {
|
||||||
|
@ -1280,9 +1280,15 @@ void Steam_Friends::Callback(Common_Message *msg)
|
|||||||
f->set_name(settings->get_local_name());
|
f->set_name(settings->get_local_name());
|
||||||
f->set_appid(settings->get_local_game_id().AppID());
|
f->set_appid(settings->get_local_game_id().AppID());
|
||||||
f->set_lobby_id(settings->get_lobby().ConvertToUint64());
|
f->set_lobby_id(settings->get_lobby().ConvertToUint64());
|
||||||
|
|
||||||
int avatar_number = GetLargeFriendAvatar(settings->get_local_steam_id());
|
int avatar_number = GetLargeFriendAvatar(settings->get_local_steam_id());
|
||||||
if (settings->images[avatar_number].data.length() > 0) f->set_avatar(settings->images[avatar_number].data);
|
auto avatar_info = settings->get_image(avatar_number);
|
||||||
else f->set_avatar("");
|
if (avatar_info && avatar_info->data.size()) {
|
||||||
|
f->set_avatar(avatar_info->data);
|
||||||
|
} else {
|
||||||
|
f->set_avatar("");
|
||||||
|
}
|
||||||
|
|
||||||
msg_.set_allocated_friend_(f);
|
msg_.set_allocated_friend_(f);
|
||||||
network->sendTo(&msg_, true);
|
network->sendTo(&msg_, true);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dll/steam_gamestats.h"
|
#include "dll/steam_gamestats.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
Steam_GameStats::Attribute_t::Attribute_t(AttributeType_t type)
|
Steam_GameStats::Attribute_t::Attribute_t(AttributeType_t type)
|
||||||
@ -194,6 +195,7 @@ SteamAPICall_t Steam_GameStats::GetNewSession( int8 nAccountType, uint64 ulAccou
|
|||||||
|
|
||||||
auto session_id = create_session_id();
|
auto session_id = create_session_id();
|
||||||
Session_t new_session{};
|
Session_t new_session{};
|
||||||
|
new_session.account_id = ulAccountID;
|
||||||
new_session.nAccountType = (EGameStatsAccountType)nAccountType;
|
new_session.nAccountType = (EGameStatsAccountType)nAccountType;
|
||||||
new_session.rtTimeStarted = rtTimeStarted;
|
new_session.rtTimeStarted = rtTimeStarted;
|
||||||
sessions.insert_or_assign(session_id, new_session);
|
sessions.insert_or_assign(session_id, new_session);
|
||||||
@ -484,6 +486,113 @@ EResult Steam_GameStats::AddRowAttributeInt64( uint64 ulRowID, const char *pstrN
|
|||||||
|
|
||||||
// --- steam callbacks
|
// --- steam callbacks
|
||||||
|
|
||||||
|
std::string Steam_GameStats::sanitize_csv_value(std::string_view value)
|
||||||
|
{
|
||||||
|
// ref: https://en.wikipedia.org/wiki/Comma-separated_values
|
||||||
|
// double quotes must be represented by a pair of double quotes
|
||||||
|
auto val_str = common_helpers::str_replace_all(value, "\"", "\"\"");
|
||||||
|
// multiline values aren't supported by all parsers
|
||||||
|
val_str = common_helpers::str_replace_all(val_str, "\r\n", "\n");
|
||||||
|
val_str = common_helpers::str_replace_all(val_str, "\n", " ");
|
||||||
|
return val_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_GameStats::save_session_to_disk(Steam_GameStats::Session_t &session, uint64 session_id)
|
||||||
|
{
|
||||||
|
auto folder = std::to_string(session.account_id) + "_" + std::to_string(session.rtTimeStarted) + "_" + std::to_string(session_id);
|
||||||
|
auto folder_p = std::filesystem::u8path(settings->steam_game_stats_reports_dir) / std::filesystem::u8path(folder);
|
||||||
|
auto folder_u8_str = folder_p.u8string();
|
||||||
|
|
||||||
|
// save session attributes
|
||||||
|
if (session.attributes.size()) {
|
||||||
|
std::stringstream ss{};
|
||||||
|
ss << "Session attribute,Value\n";
|
||||||
|
for (const auto& [name, val] : session.attributes) {
|
||||||
|
std::string val_str{};
|
||||||
|
switch (val.type) {
|
||||||
|
case AttributeType_t::Int: val_str = std::to_string(val.n_data); break;
|
||||||
|
case AttributeType_t::Str: val_str = val.s_data; break;
|
||||||
|
case AttributeType_t::Float: val_str = std::to_string(val.f_data); break;
|
||||||
|
case AttributeType_t::Int64: val_str = std::to_string(val.ll_data); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
val_str = sanitize_csv_value(val_str);
|
||||||
|
auto name_str = sanitize_csv_value(name);
|
||||||
|
ss << "\"" << name_str << "\",\"" << val_str << "\"\n";
|
||||||
|
}
|
||||||
|
auto ss_str = ss.str();
|
||||||
|
Local_Storage::store_file_data(folder_u8_str, "session_attributes.csv", ss_str.c_str(), (unsigned int)ss_str.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// save each table
|
||||||
|
for (const auto& [table_name, table_data] : session.tables) {
|
||||||
|
bool rows_has_attributes = std::any_of(table_data.rows.begin(), table_data.rows.end(), [](const Steam_GameStats::Row_t &item) {
|
||||||
|
return item.attributes.size() > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!rows_has_attributes) continue;
|
||||||
|
|
||||||
|
// convert the data representation to be column oriented
|
||||||
|
// key=column header/title
|
||||||
|
// value = list of column values
|
||||||
|
std::unordered_map<std::string, std::vector<const Attribute_t*>> columns{};
|
||||||
|
for (size_t row_idx = 0; row_idx < table_data.rows.size(); ++row_idx) {
|
||||||
|
const auto &row = table_data.rows[row_idx];
|
||||||
|
for (const auto& [att_name, att_val] : row.attributes) {
|
||||||
|
auto [column_it, new_column] = columns.emplace(att_name, std::vector<const Attribute_t*>{});
|
||||||
|
auto &column_values = column_it->second;
|
||||||
|
// when adding new column make sure we have correct rows count
|
||||||
|
if (new_column) {
|
||||||
|
column_values.assign(table_data.rows.size(), nullptr);
|
||||||
|
}
|
||||||
|
// add the row value in its correct place
|
||||||
|
column_values[row_idx] = &att_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss_table{};
|
||||||
|
// write header
|
||||||
|
bool first_header_atom = true;
|
||||||
|
for (const auto& [col_name, _] : columns) {
|
||||||
|
auto csv_col_name = sanitize_csv_value(col_name);
|
||||||
|
if (first_header_atom) {
|
||||||
|
first_header_atom = false;
|
||||||
|
ss_table << "\"" << csv_col_name << "\"";
|
||||||
|
} else {
|
||||||
|
ss_table << ",\"" << csv_col_name << "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss_table << "\n";
|
||||||
|
// write values
|
||||||
|
for (size_t row_idx = 0; row_idx < table_data.rows.size(); ++row_idx) {
|
||||||
|
bool first_col_cell = true;
|
||||||
|
for (const auto& [_, col_values] : columns) {
|
||||||
|
auto &cell_val = col_values[row_idx];
|
||||||
|
|
||||||
|
std::string val_str{};
|
||||||
|
switch (cell_val->type) {
|
||||||
|
case AttributeType_t::Int: val_str = std::to_string(cell_val->n_data); break;
|
||||||
|
case AttributeType_t::Str: val_str = cell_val->s_data; break;
|
||||||
|
case AttributeType_t::Float: val_str = std::to_string(cell_val->f_data); break;
|
||||||
|
case AttributeType_t::Int64: val_str = std::to_string(cell_val->ll_data); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
val_str = sanitize_csv_value(val_str);
|
||||||
|
if (first_col_cell) {
|
||||||
|
first_col_cell = false;
|
||||||
|
ss_table << "\"" << val_str << "\"";
|
||||||
|
} else {
|
||||||
|
ss_table << ",\"" << val_str << "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss_table << "\n";
|
||||||
|
auto ss_str = ss_table.str();
|
||||||
|
Local_Storage::store_file_data(folder_u8_str, table_name.c_str(), ss_str.c_str(), (unsigned int)ss_str.size());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Steam_GameStats::steam_run_callback()
|
void Steam_GameStats::steam_run_callback()
|
||||||
{
|
{
|
||||||
// remove ended sessions that are inactive
|
// remove ended sessions that are inactive
|
||||||
@ -496,6 +605,13 @@ void Steam_GameStats::steam_run_callback()
|
|||||||
|
|
||||||
auto &session = session_it->second;
|
auto &session = session_it->second;
|
||||||
if (session.ended) {
|
if (session.ended) {
|
||||||
|
if (!session.saved_to_disk) {
|
||||||
|
session.saved_to_disk = true;
|
||||||
|
if (settings->steam_game_stats_reports_dir.size()) {
|
||||||
|
save_session_to_disk(session, session_it->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( (now_epoch_sec.count() - (long long)session.rtTimeEnded) >= MAX_DEAD_SESSION_SECONDS ) {
|
if ( (now_epoch_sec.count() - (long long)session.rtTimeEnded) >= MAX_DEAD_SESSION_SECONDS ) {
|
||||||
should_remove = true;
|
should_remove = true;
|
||||||
PRINT_DEBUG("removing outdated session id=%llu", session_it->first);
|
PRINT_DEBUG("removing outdated session id=%llu", session_it->first);
|
||||||
|
@ -38,7 +38,7 @@ Steam_Http_Request *Steam_HTTP::get_request(HTTPRequestHandle hRequest)
|
|||||||
// or such.
|
// or such.
|
||||||
HTTPRequestHandle Steam_HTTP::CreateHTTPRequest( EHTTPMethod eHTTPRequestMethod, const char *pchAbsoluteURL )
|
HTTPRequestHandle Steam_HTTP::CreateHTTPRequest( EHTTPMethod eHTTPRequestMethod, const char *pchAbsoluteURL )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("%i %s", eHTTPRequestMethod, pchAbsoluteURL);
|
PRINT_DEBUG("%i '%s'", eHTTPRequestMethod, pchAbsoluteURL);
|
||||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
if (!pchAbsoluteURL) return INVALID_HTTPREQUEST_HANDLE;
|
if (!pchAbsoluteURL) return INVALID_HTTPREQUEST_HANDLE;
|
||||||
@ -83,7 +83,7 @@ HTTPRequestHandle Steam_HTTP::CreateHTTPRequest( EHTTPMethod eHTTPRequestMethod,
|
|||||||
// sending the request. This is just so the caller can easily keep track of which callbacks go with which request data.
|
// sending the request. This is just so the caller can easily keep track of which callbacks go with which request data.
|
||||||
bool Steam_HTTP::SetHTTPRequestContextValue( HTTPRequestHandle hRequest, uint64 ulContextValue )
|
bool Steam_HTTP::SetHTTPRequestContextValue( HTTPRequestHandle hRequest, uint64 ulContextValue )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG_ENTRY();
|
PRINT_DEBUG("%llu", ulContextValue);
|
||||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
Steam_Http_Request *request = get_request(hRequest);
|
Steam_Http_Request *request = get_request(hRequest);
|
||||||
@ -122,15 +122,19 @@ bool Steam_HTTP::SetHTTPRequestHeaderValue( HTTPRequestHandle hRequest, const ch
|
|||||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
if (!pchHeaderName || !pchHeaderValue) return false;
|
if (!pchHeaderName || !pchHeaderValue) return false;
|
||||||
std::string headerName(pchHeaderName);
|
if (common_helpers::str_cmp_insensitive(pchHeaderName, "User-Agent")) return false;
|
||||||
std::transform(headerName.begin(), headerName.end(), headerName.begin(), [](char c){ return (char)std::toupper(c); });
|
|
||||||
if (headerName == "USER-AGENT") return false;
|
|
||||||
|
|
||||||
Steam_Http_Request *request = get_request(hRequest);
|
Steam_Http_Request *request = get_request(hRequest);
|
||||||
if (!request) {
|
if (!request) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIX: appid 1902490 adds the header "Cache-Control: only-if-cached, max-stale=2678400"
|
||||||
|
// which means a response is returned back only if it was already cached, otherwise the server has to send a 504 "Gateway Timeout"
|
||||||
|
// just bypass the known ones to be on the safe side
|
||||||
|
if (common_helpers::str_cmp_insensitive(pchHeaderName, "Cache-Control")) return true;
|
||||||
|
if (common_helpers::str_cmp_insensitive(pchHeaderName, "Accept")) return true;
|
||||||
|
|
||||||
request->headers[pchHeaderName] = pchHeaderValue;
|
request->headers[pchHeaderName] = pchHeaderValue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -160,13 +164,37 @@ bool Steam_HTTP::SetHTTPRequestGetOrPostParameter( HTTPRequestHandle hRequest, c
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int curl_debug_trace(
|
||||||
|
CURL *handle, curl_infotype type,
|
||||||
|
char *data, size_t size,
|
||||||
|
void *clientp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// https://curl.se/libcurl/c/CURLOPT_DEBUGFUNCTION.html
|
||||||
|
std::string text{};
|
||||||
|
switch (type) {
|
||||||
|
case CURLINFO_TEXT: text = "Info: " + std::string(data, size); break;
|
||||||
|
case CURLINFO_HEADER_IN: text = "<= Recv header"; break;
|
||||||
|
case CURLINFO_HEADER_OUT: text = "=> Send header"; break;
|
||||||
|
case CURLINFO_DATA_IN: text = "<= Recv data"; break;
|
||||||
|
case CURLINFO_DATA_OUT: text = "=> Send data"; break;
|
||||||
|
case CURLINFO_SSL_DATA_OUT: text = "=> Send SSL data"; break;
|
||||||
|
case CURLINFO_SSL_DATA_IN: text = "<= Recv SSL data"; break;
|
||||||
|
|
||||||
void Steam_HTTP::online_http_request(Steam_Http_Request *request, SteamAPICall_t *pCallHandle)
|
default: text = "[X] ERROR: unknown callback type"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_DEBUG("%s", text.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_HTTP::online_http_request(Steam_Http_Request *request, SteamAPICall_t call_res_id)
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("attempting to download from url: '%s', target filepath: '%s'",
|
PRINT_DEBUG("attempting to download from url: '%s', target filepath: '%s'",
|
||||||
request->url.c_str(), request->target_filepath.c_str());
|
request->url.c_str(), request->target_filepath.c_str());
|
||||||
|
|
||||||
const auto send_callresult = [&]() -> void {
|
const auto send_callresult = [=]() -> void {
|
||||||
struct HTTPRequestCompleted_t data{};
|
struct HTTPRequestCompleted_t data{};
|
||||||
data.m_hRequest = request->handle;
|
data.m_hRequest = request->handle;
|
||||||
data.m_ulContextValue = request->context_value;
|
data.m_ulContextValue = request->context_value;
|
||||||
@ -174,16 +202,13 @@ void Steam_HTTP::online_http_request(Steam_Http_Request *request, SteamAPICall_t
|
|||||||
if (request->response.empty() && !settings->force_steamhttp_success) {
|
if (request->response.empty() && !settings->force_steamhttp_success) {
|
||||||
data.m_bRequestSuccessful = false;
|
data.m_bRequestSuccessful = false;
|
||||||
data.m_eStatusCode = k_EHTTPStatusCode404NotFound;
|
data.m_eStatusCode = k_EHTTPStatusCode404NotFound;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
data.m_bRequestSuccessful = true;
|
data.m_bRequestSuccessful = true;
|
||||||
data.m_eStatusCode = k_EHTTPStatusCode200OK;
|
data.m_eStatusCode = k_EHTTPStatusCode200OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto callres = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
callback_results->addCallResult(call_res_id, data.k_iCallback, &data, sizeof(data));
|
||||||
if (pCallHandle) *pCallHandle = callres;
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
|
||||||
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::size_t filename_part = request->target_filepath.find_last_of("\\/");
|
std::size_t filename_part = request->target_filepath.find_last_of("\\/");
|
||||||
@ -214,6 +239,11 @@ void Steam_HTTP::online_http_request(Steam_Http_Request *request, SteamAPICall_t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef EMU_RELEASE_BUILD
|
||||||
|
curl_easy_setopt(chttp, CURLOPT_DEBUGFUNCTION, curl_debug_trace);
|
||||||
|
curl_easy_setopt(chttp, CURLOPT_VERBOSE, 1L);
|
||||||
|
#endif
|
||||||
|
|
||||||
// headers
|
// headers
|
||||||
std::vector<std::string> headers{};
|
std::vector<std::string> headers{};
|
||||||
for (const auto &hdr : request->headers) {
|
for (const auto &hdr : request->headers) {
|
||||||
@ -279,6 +309,7 @@ void Steam_HTTP::online_http_request(Steam_Http_Request *request, SteamAPICall_t
|
|||||||
curl_easy_setopt(chttp, CURLOPT_TIMEOUT, request->timeout_sec);
|
curl_easy_setopt(chttp, CURLOPT_TIMEOUT, request->timeout_sec);
|
||||||
curl_easy_setopt(chttp, CURLOPT_NOSIGNAL, 1L);
|
curl_easy_setopt(chttp, CURLOPT_NOSIGNAL, 1L);
|
||||||
curl_easy_setopt(chttp, CURLOPT_USE_SSL, request->requires_valid_ssl ? CURLUSESSL_TRY : CURLUSESSL_NONE);
|
curl_easy_setopt(chttp, CURLOPT_USE_SSL, request->requires_valid_ssl ? CURLUSESSL_TRY : CURLUSESSL_NONE);
|
||||||
|
curl_easy_setopt(chttp, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
|
||||||
// post data, or get params
|
// post data, or get params
|
||||||
std::string post_data{};
|
std::string post_data{};
|
||||||
@ -314,11 +345,12 @@ void Steam_HTTP::online_http_request(Steam_Http_Request *request, SteamAPICall_t
|
|||||||
fclose(hfile);
|
fclose(hfile);
|
||||||
headers.clear();
|
headers.clear();
|
||||||
|
|
||||||
PRINT_DEBUG("CURL error code for '%s' [%i] (OK == 0)", request->url.c_str(), (int)res_curl);
|
PRINT_DEBUG("CURL error code for '%s' [%i = '%s'] (OK == 0)", request->url.c_str(), (int)res_curl, curl_easy_strerror(res_curl));
|
||||||
|
|
||||||
unsigned int file_size = file_size_(request->target_filepath);
|
unsigned int file_size = file_size_(request->target_filepath);
|
||||||
if (file_size) {
|
if (file_size) {
|
||||||
long long read = Local_Storage::get_file_data(request->target_filepath, (char *)&request->response[0], file_size, 0);
|
request->response.resize(static_cast<size_t>(file_size));
|
||||||
|
long long read = Local_Storage::get_file_data(request->target_filepath, (char *)&request->response[0], file_size);
|
||||||
if (read < 0) read = 0;
|
if (read < 0) read = 0;
|
||||||
request->response.resize(static_cast<size_t>(read));
|
request->response.resize(static_cast<size_t>(read));
|
||||||
}
|
}
|
||||||
@ -343,7 +375,10 @@ bool Steam_HTTP::SendHTTPRequest( HTTPRequestHandle hRequest, SteamAPICall_t *pC
|
|||||||
|
|
||||||
if (request->response.empty() && request->target_filepath.size() &&
|
if (request->response.empty() && request->target_filepath.size() &&
|
||||||
!settings->disable_networking && settings->download_steamhttp_requests) {
|
!settings->disable_networking && settings->download_steamhttp_requests) {
|
||||||
std::thread(&Steam_HTTP::online_http_request, this, request, pCallHandle).detach();
|
auto call_res_id = callback_results->reserveCallResult();
|
||||||
|
if (pCallHandle) *pCallHandle = call_res_id;
|
||||||
|
|
||||||
|
std::thread(&Steam_HTTP::online_http_request, this, request, call_res_id).detach();
|
||||||
} else {
|
} else {
|
||||||
struct HTTPRequestCompleted_t data{};
|
struct HTTPRequestCompleted_t data{};
|
||||||
data.m_hRequest = request->handle;
|
data.m_hRequest = request->handle;
|
||||||
@ -352,7 +387,6 @@ bool Steam_HTTP::SendHTTPRequest( HTTPRequestHandle hRequest, SteamAPICall_t *pC
|
|||||||
if (request->response.empty() && !settings->force_steamhttp_success) {
|
if (request->response.empty() && !settings->force_steamhttp_success) {
|
||||||
data.m_bRequestSuccessful = false;
|
data.m_bRequestSuccessful = false;
|
||||||
data.m_eStatusCode = k_EHTTPStatusCode404NotFound;
|
data.m_eStatusCode = k_EHTTPStatusCode404NotFound;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
data.m_bRequestSuccessful = true;
|
data.m_bRequestSuccessful = true;
|
||||||
data.m_eStatusCode = k_EHTTPStatusCode200OK;
|
data.m_eStatusCode = k_EHTTPStatusCode200OK;
|
||||||
|
@ -362,7 +362,7 @@ int Steam_Matchmaking::AddFavoriteGame( AppId_t nAppID, uint32 nIP, uint16 nConn
|
|||||||
directory_path = file_path.substr(0, file_directory);
|
directory_path = file_path.substr(0, file_directory);
|
||||||
file_name = file_path.substr(file_directory);
|
file_name = file_path.substr(file_directory);
|
||||||
}
|
}
|
||||||
Local_Storage::store_file_data(directory_path, file_name, (char *)list.data(), list.size());
|
Local_Storage::store_file_data(directory_path, file_name, (char *)list.data(), (unsigned int)list.size());
|
||||||
|
|
||||||
++list_lines;
|
++list_lines;
|
||||||
return static_cast<int>(list_lines);
|
return static_cast<int>(list_lines);
|
||||||
@ -379,7 +379,7 @@ int Steam_Matchmaking::AddFavoriteGame( AppId_t nAppID, uint32 nIP, uint16 nConn
|
|||||||
directory_path = file_path.substr(0, file_directory);
|
directory_path = file_path.substr(0, file_directory);
|
||||||
file_name = file_path.substr(file_directory);
|
file_name = file_path.substr(file_directory);
|
||||||
}
|
}
|
||||||
Local_Storage::store_file_data(directory_path, file_name, (char *)newip_string.data(), newip_string.size());
|
Local_Storage::store_file_data(directory_path, file_name, (char *)newip_string.data(), (unsigned int)newip_string.size());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -429,7 +429,7 @@ bool Steam_Matchmaking::RemoveFavoriteGame( AppId_t nAppID, uint32 nIP, uint16 n
|
|||||||
directory_path = file_path.substr(0, file_directory);
|
directory_path = file_path.substr(0, file_directory);
|
||||||
file_name = file_path.substr(file_directory);
|
file_name = file_path.substr(file_directory);
|
||||||
}
|
}
|
||||||
Local_Storage::store_file_data(directory_path, file_name, (char *)list.data(), list.size());
|
Local_Storage::store_file_data(directory_path, file_name, (char *)list.data(), (unsigned int)list.size());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -923,7 +923,7 @@ bool Steam_Networking_Sockets::GetConnectionInfo( HSteamNetConnection hConn, Ste
|
|||||||
/// - k_EResultInvalidParam - nLanes is bad
|
/// - k_EResultInvalidParam - nLanes is bad
|
||||||
EResult Steam_Networking_Sockets::GetConnectionRealTimeStatus( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus, int nLanes, SteamNetConnectionRealTimeLaneStatus_t *pLanes )
|
EResult Steam_Networking_Sockets::GetConnectionRealTimeStatus( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus, int nLanes, SteamNetConnectionRealTimeLaneStatus_t *pLanes )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("%s %u %p %i %p", __FUNCTION__, hConn, pStatus, nLanes, pLanes);
|
PRINT_DEBUG("%u %p %i %p", hConn, pStatus, nLanes, pLanes);
|
||||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
auto connect_socket = sbcs->connect_sockets.find(hConn);
|
auto connect_socket = sbcs->connect_sockets.find(hConn);
|
||||||
if (connect_socket == sbcs->connect_sockets.end()) return k_EResultNoConnection;
|
if (connect_socket == sbcs->connect_sockets.end()) return k_EResultNoConnection;
|
||||||
@ -950,6 +950,24 @@ EResult Steam_Networking_Sockets::GetConnectionRealTimeStatus( HSteamNetConnecti
|
|||||||
return k_EResultOK;
|
return k_EResultOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// based on reversing the vftable returned from original steamclient64.dll
|
||||||
|
bool Steam_Networking_Sockets::GetConnectionRealTimeStatus_old( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("undocumented API, interface v10-11");
|
||||||
|
/*
|
||||||
|
...
|
||||||
|
xor r9d, r9d // int nLanes = 0
|
||||||
|
mov qword ptr ss:[rsp+0x20], 0x0 // SteamNetConnectionRealTimeLaneStatus_t *pLanes = nullptr
|
||||||
|
...
|
||||||
|
call qword ptr ds:[rax+0x80] // call GetConnectionRealTimeStatus(hConn, pStatus, nLanes, pLanes)
|
||||||
|
test eax, eax
|
||||||
|
setne al if (eax !=0) { al=1 } else { al=0 }
|
||||||
|
...
|
||||||
|
ret
|
||||||
|
*/
|
||||||
|
return GetConnectionRealTimeStatus(hConn, pStatus, 0, nullptr) != EResult::k_EResultNone;
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetch the next available message(s) from the socket, if any.
|
/// Fetch the next available message(s) from the socket, if any.
|
||||||
/// Returns the number of messages returned into your array, up to nMaxMessages.
|
/// Returns the number of messages returned into your array, up to nMaxMessages.
|
||||||
/// If the connection handle is invalid, -1 is returned.
|
/// If the connection handle is invalid, -1 is returned.
|
||||||
|
File diff suppressed because it is too large
Load Diff
799
dll/steam_user_stats_achievements.cpp
Normal file
799
dll/steam_user_stats_achievements.cpp
Normal file
@ -0,0 +1,799 @@
|
|||||||
|
/* Copyright (C) 2019 Mr Goldberg
|
||||||
|
This file is part of the Goldberg Emulator
|
||||||
|
|
||||||
|
The Goldberg Emulator is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The Goldberg Emulator is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the Goldberg Emulator; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include "dll/steam_user_stats.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
|
||||||
|
// --- achievement_trigger ---
|
||||||
|
bool achievement_trigger::should_unlock_ach(float stat) const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (std::stof(max_value) <= stat) return true;
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool achievement_trigger::should_unlock_ach(int32 stat) const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (std::stoi(max_value) <= stat) return true;
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool achievement_trigger::should_indicate_progress(float stat) const
|
||||||
|
{
|
||||||
|
// show progress if number < max
|
||||||
|
try {
|
||||||
|
if (std::stof(max_value) > stat) return true;
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool achievement_trigger::should_indicate_progress(int32 stat) const
|
||||||
|
{
|
||||||
|
// show progress if number < max
|
||||||
|
try {
|
||||||
|
if (std::stoi(max_value) > stat) return true;
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// --- achievement_trigger ---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_User_Stats::load_achievements_db()
|
||||||
|
{
|
||||||
|
std::string file_path = Local_Storage::get_game_settings_path() + achievements_user_file;
|
||||||
|
local_storage->load_json(file_path, defined_achievements);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_User_Stats::load_achievements()
|
||||||
|
{
|
||||||
|
local_storage->load_json_file("", achievements_user_file, user_achievements);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_User_Stats::save_achievements()
|
||||||
|
{
|
||||||
|
local_storage->write_json_file("", achievements_user_file, user_achievements);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Steam_User_Stats::load_ach_icon(nlohmann::json &defined_ach, bool achieved)
|
||||||
|
{
|
||||||
|
const char *icon_handle_key = achieved ? "icon_handle" : "icon_gray_handle";
|
||||||
|
int current_handle = defined_ach.value(icon_handle_key, UNLOADED_ACH_ICON);
|
||||||
|
if (UNLOADED_ACH_ICON != current_handle) { // already loaded
|
||||||
|
return current_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *icon_key = achieved ? "icon" : "icon_gray";
|
||||||
|
if (!achieved && !defined_ach.contains(icon_key)) {
|
||||||
|
icon_key = "icongray"; // old format
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string icon_filepath = defined_ach.value(icon_key, std::string{});
|
||||||
|
if (icon_filepath.empty()) {
|
||||||
|
defined_ach[icon_handle_key] = Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
return Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string file_path(Local_Storage::get_game_settings_path() + icon_filepath);
|
||||||
|
unsigned int file_size = file_size_(file_path);
|
||||||
|
if (!file_size) {
|
||||||
|
defined_ach[icon_handle_key] = Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
return Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icon_size = static_cast<int>(settings->overlay_appearance.icon_size);
|
||||||
|
std::string img(Local_Storage::load_image_resized(file_path, "", icon_size));
|
||||||
|
if (img.empty()) {
|
||||||
|
defined_ach[icon_handle_key] = Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
return Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle = settings->add_image(img, icon_size, icon_size);
|
||||||
|
defined_ach[icon_handle_key] = handle;
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> Steam_User_Stats::defined_achievements_find(const std::string &key)
|
||||||
|
{
|
||||||
|
return std::find_if(
|
||||||
|
defined_achievements.begin(), defined_achievements.end(),
|
||||||
|
[&key](const nlohmann::json& item) {
|
||||||
|
const std::string &name = static_cast<const std::string &>( item.value("name", std::string()) );
|
||||||
|
return common_helpers::str_cmp_insensitive(key, name);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Steam_User_Stats::get_value_for_language(const nlohmann::json &json, std::string_view key, std::string_view language)
|
||||||
|
{
|
||||||
|
auto x = json.find(key); // find "displayName", or "description", etc ...
|
||||||
|
if (json.end() == x) return "";
|
||||||
|
|
||||||
|
if (x.value().is_string()) { // ex: "displayName": "some description"
|
||||||
|
return x.value().get<std::string>();
|
||||||
|
} else if (x.value().is_object()) {
|
||||||
|
const auto &obj_kv_pairs = x.value().items();
|
||||||
|
|
||||||
|
// try to find target language
|
||||||
|
auto obj_itr = std::find_if(obj_kv_pairs.begin(), obj_kv_pairs.end(), [&]( decltype(*obj_kv_pairs.begin()) item ) {
|
||||||
|
return common_helpers::str_cmp_insensitive(item.key(), language);
|
||||||
|
});
|
||||||
|
if (obj_itr != obj_kv_pairs.end()) {
|
||||||
|
return obj_itr.value().get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to find english language
|
||||||
|
obj_itr = std::find_if(obj_kv_pairs.begin(), obj_kv_pairs.end(), [&]( decltype(*obj_kv_pairs.begin()) item ) {
|
||||||
|
return common_helpers::str_cmp_insensitive(item.key(), "english");
|
||||||
|
});
|
||||||
|
if (obj_itr != obj_kv_pairs.end()) {
|
||||||
|
return obj_itr.value().get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to find the first available language (not "token"),
|
||||||
|
// if not languages exist, try to find "token"
|
||||||
|
for (bool search_for_token : { false, true }) {
|
||||||
|
obj_itr = std::find_if(obj_kv_pairs.begin(), obj_kv_pairs.end(), [&]( decltype(*obj_kv_pairs.begin()) item ) {
|
||||||
|
return common_helpers::str_cmp_insensitive(item.key(), "token") == search_for_token;
|
||||||
|
});
|
||||||
|
if (obj_itr != obj_kv_pairs.end()) {
|
||||||
|
return obj_itr.value().get<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// change achievements without sending back to server
|
||||||
|
Steam_User_Stats::InternalSetResult<bool> Steam_User_Stats::set_achievement_internal( const char *pchName )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
Steam_User_Stats::InternalSetResult<bool> result{};
|
||||||
|
|
||||||
|
if (!pchName) return result;
|
||||||
|
|
||||||
|
std::string org_name(pchName);
|
||||||
|
|
||||||
|
if (settings->achievement_bypass) {
|
||||||
|
auto &trig = store_stats_trigger[common_helpers::to_lower(org_name)];
|
||||||
|
trig.m_bGroupAchievement = false;
|
||||||
|
trig.m_nCurProgress = 100;
|
||||||
|
trig.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
trig.m_nMaxProgress = 100;
|
||||||
|
memset(trig.m_rgchAchievementName, 0, sizeof(trig.m_rgchAchievementName));
|
||||||
|
org_name.copy(trig.m_rgchAchievementName, sizeof(trig.m_rgchAchievementName) - 1);
|
||||||
|
|
||||||
|
result.success = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(org_name);
|
||||||
|
} catch(...) { }
|
||||||
|
if (defined_achievements.end() == it) return result;
|
||||||
|
|
||||||
|
result.current_val = true;
|
||||||
|
result.internal_name = org_name;
|
||||||
|
result.success = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::string internal_name = it->value("name", std::string());
|
||||||
|
|
||||||
|
result.internal_name = internal_name;
|
||||||
|
|
||||||
|
auto ach = user_achievements.find(internal_name);
|
||||||
|
if (user_achievements.end() == ach || ach->value("earned", false) == false) {
|
||||||
|
user_achievements[internal_name]["earned"] = true;
|
||||||
|
user_achievements[internal_name]["earned_time"] =
|
||||||
|
std::chrono::duration_cast<std::chrono::duration<uint32>>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||||
|
|
||||||
|
save_achievements();
|
||||||
|
|
||||||
|
result.notify_server = !settings->disable_sharing_stats_with_gameserver;
|
||||||
|
|
||||||
|
overlay->AddAchievementNotification(internal_name, user_achievements[internal_name], false);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
auto &trig = store_stats_trigger[common_helpers::to_lower(org_name)];
|
||||||
|
trig.m_bGroupAchievement = false;
|
||||||
|
trig.m_nCurProgress = 100;
|
||||||
|
trig.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
trig.m_nMaxProgress = 100;
|
||||||
|
memset(trig.m_rgchAchievementName, 0, sizeof(trig.m_rgchAchievementName));
|
||||||
|
org_name.copy(trig.m_rgchAchievementName, sizeof(trig.m_rgchAchievementName) - 1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_User_Stats::InternalSetResult<bool> Steam_User_Stats::clear_achievement_internal( const char *pchName )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
Steam_User_Stats::InternalSetResult<bool> result{};
|
||||||
|
|
||||||
|
if (!pchName) return result;
|
||||||
|
|
||||||
|
std::string org_name(pchName);
|
||||||
|
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(org_name);
|
||||||
|
} catch(...) { }
|
||||||
|
if (defined_achievements.end() == it) return result;
|
||||||
|
|
||||||
|
result.current_val = false;
|
||||||
|
result.internal_name = org_name;
|
||||||
|
result.success = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::string internal_name = it->value("name", std::string());
|
||||||
|
|
||||||
|
result.internal_name = internal_name;
|
||||||
|
|
||||||
|
auto ach = user_achievements.find(internal_name);
|
||||||
|
// assume "earned" is true in case the json obj exists, but the key is absent
|
||||||
|
// assume "earned_time" is UINT32_MAX in case the json obj exists, but the key is absent
|
||||||
|
if (user_achievements.end() == ach ||
|
||||||
|
ach->value("earned", true) == true ||
|
||||||
|
ach->value("earned_time", static_cast<uint32>(UINT32_MAX)) == UINT32_MAX) {
|
||||||
|
|
||||||
|
user_achievements[internal_name]["earned"] = false;
|
||||||
|
user_achievements[internal_name]["earned_time"] = static_cast<uint32>(0);
|
||||||
|
save_achievements();
|
||||||
|
|
||||||
|
result.notify_server = !settings->disable_sharing_stats_with_gameserver;
|
||||||
|
|
||||||
|
overlay->AddAchievementNotification(internal_name, user_achievements[internal_name], false);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
store_stats_trigger.erase(common_helpers::to_lower(org_name));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Achievement flag accessors
|
||||||
|
bool Steam_User_Stats::GetAchievement( const char *pchName, bool *pbAchieved )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(pchName);
|
||||||
|
} catch(...) { }
|
||||||
|
if (defined_achievements.end() == it) return false;
|
||||||
|
|
||||||
|
// according to docs, the function returns true if the achievement was found,
|
||||||
|
// regardless achieved or not
|
||||||
|
if (!pbAchieved) return true;
|
||||||
|
|
||||||
|
*pbAchieved = false;
|
||||||
|
try {
|
||||||
|
std::string pch_name = it->value("name", std::string());
|
||||||
|
auto ach = user_achievements.find(pch_name);
|
||||||
|
if (user_achievements.end() != ach) {
|
||||||
|
*pbAchieved = ach->value("earned", false);
|
||||||
|
}
|
||||||
|
} catch (...) { }
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Steam_User_Stats::SetAchievement( const char *pchName )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
auto ret = set_achievement_internal(pchName);
|
||||||
|
if (ret.success && ret.notify_server) {
|
||||||
|
auto &new_ach = (*pending_server_updates.mutable_user_achievements())[ret.internal_name];
|
||||||
|
new_ach.set_achieved(ret.current_val);
|
||||||
|
|
||||||
|
if (settings->immediate_gameserver_stats) send_updated_stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Steam_User_Stats::ClearAchievement( const char *pchName )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
auto ret = clear_achievement_internal(pchName);
|
||||||
|
if (ret.success && ret.notify_server) {
|
||||||
|
auto &new_ach = (*pending_server_updates.mutable_user_achievements())[ret.internal_name];
|
||||||
|
new_ach.set_achieved(ret.current_val);
|
||||||
|
|
||||||
|
if (settings->immediate_gameserver_stats) send_updated_stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get the achievement status, and the time it was unlocked if unlocked.
|
||||||
|
// If the return value is true, but the unlock time is zero, that means it was unlocked before Steam
|
||||||
|
// began tracking achievement unlock times (December 2009). Time is seconds since January 1, 1970.
|
||||||
|
bool Steam_User_Stats::GetAchievementAndUnlockTime( const char *pchName, bool *pbAchieved, uint32 *punUnlockTime )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(pchName);
|
||||||
|
} catch(...) { }
|
||||||
|
if (defined_achievements.end() == it) return false;
|
||||||
|
|
||||||
|
if (pbAchieved) *pbAchieved = false;
|
||||||
|
if (punUnlockTime) *punUnlockTime = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::string pch_name = it->value("name", std::string());
|
||||||
|
auto ach = user_achievements.find(pch_name);
|
||||||
|
if (user_achievements.end() != ach) {
|
||||||
|
if (pbAchieved) *pbAchieved = ach->value("earned", false);
|
||||||
|
if (punUnlockTime) *punUnlockTime = ach->value("earned_time", static_cast<uint32>(0));
|
||||||
|
}
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Achievement / GroupAchievement metadata
|
||||||
|
|
||||||
|
// Gets the icon of the achievement, which is a handle to be used in ISteamUtils::GetImageRGBA(), or 0 if none set.
|
||||||
|
// A return value of 0 may indicate we are still fetching data, and you can wait for the UserAchievementIconFetched_t callback
|
||||||
|
// which will notify you when the bits are ready. If the callback still returns zero, then there is no image set for the
|
||||||
|
// specified achievement.
|
||||||
|
int Steam_User_Stats::GetAchievementIcon( const char *pchName )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (!pchName) return Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
|
||||||
|
bool achieved = false;
|
||||||
|
GetAchievement(pchName, &achieved);
|
||||||
|
|
||||||
|
std::string ach_name(pchName);
|
||||||
|
int handle = get_achievement_icon_handle(ach_name, achieved);
|
||||||
|
|
||||||
|
UserAchievementIconFetched_t data{};
|
||||||
|
data.m_bAchieved = achieved ;
|
||||||
|
data.m_nGameID = settings->get_local_game_id();
|
||||||
|
data.m_nIconHandle = handle;
|
||||||
|
ach_name.copy(data.m_rgchAchievementName, sizeof(data.m_rgchAchievementName));
|
||||||
|
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Steam_User_Stats::get_achievement_icon_handle( const std::string &ach_name, bool achieved )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s', %i", ach_name.c_str(), (int)achieved);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (ach_name.empty()) return Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(ach_name);
|
||||||
|
} catch(...) { }
|
||||||
|
if (defined_achievements.end() == it) return Settings::INVALID_IMAGE_HANDLE;
|
||||||
|
|
||||||
|
int handle = load_ach_icon(*it, achieved);
|
||||||
|
PRINT_DEBUG("returned handle = %i", handle);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Steam_User_Stats::get_achievement_icon_name( const char *pchName, bool pbAchieved )
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (!pchName) return "";
|
||||||
|
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(pchName);
|
||||||
|
} catch(...) { }
|
||||||
|
if (defined_achievements.end() == it) return "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (pbAchieved) return it.value()["icon"].get<std::string>();
|
||||||
|
|
||||||
|
std::string locked_icon = it.value().value("icon_gray", std::string());
|
||||||
|
if (locked_icon.size()) return locked_icon;
|
||||||
|
else return it.value().value("icongray", std::string()); // old format
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get general attributes for an achievement. Accepts the following keys:
|
||||||
|
// - "name" and "desc" for retrieving the localized achievement name and description (returned in UTF8)
|
||||||
|
// - "hidden" for retrieving if an achievement is hidden (returns "0" when not hidden, "1" when hidden)
|
||||||
|
const char * Steam_User_Stats::GetAchievementDisplayAttribute( const char *pchName, const char *pchKey )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("[%s] [%s]", pchName, pchKey);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName || !pchKey || !pchKey[0]) return "";
|
||||||
|
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(pchName);
|
||||||
|
} catch(...) { }
|
||||||
|
if (defined_achievements.end() == it) return "";
|
||||||
|
|
||||||
|
if (strncmp(pchKey, "name", sizeof("name")) == 0) {
|
||||||
|
try {
|
||||||
|
return it.value()["displayName"].get_ptr<std::string*>()->c_str();
|
||||||
|
} catch (...) {}
|
||||||
|
} else if (strncmp(pchKey, "desc", sizeof("desc")) == 0) {
|
||||||
|
try {
|
||||||
|
return it.value()["description"].get_ptr<std::string*>()->c_str();
|
||||||
|
} catch (...) {}
|
||||||
|
} else if (strncmp(pchKey, "hidden", sizeof("hidden")) == 0) {
|
||||||
|
try {
|
||||||
|
return it.value()["hidden"].get_ptr<std::string*>()->c_str();
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Achievement progress - triggers an AchievementProgress callback, that is all.
|
||||||
|
// Calling this w/ N out of N progress will NOT set the achievement, the game must still do that.
|
||||||
|
bool Steam_User_Stats::IndicateAchievementProgress( const char *pchName, uint32 nCurProgress, uint32 nMaxProgress )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s' %u %u", pchName, nCurProgress, nMaxProgress);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
if (nCurProgress >= nMaxProgress) return false;
|
||||||
|
|
||||||
|
std::string ach_name(pchName);
|
||||||
|
|
||||||
|
// find in achievements.json
|
||||||
|
nlohmann::detail::iter_impl<nlohmann::json> it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(ach_name);
|
||||||
|
} catch(...) { }
|
||||||
|
if (defined_achievements.end() == it) return false;
|
||||||
|
|
||||||
|
// get actual name from achievements.json
|
||||||
|
std::string actual_ach_name{};
|
||||||
|
try {
|
||||||
|
actual_ach_name = it->value("name", std::string());
|
||||||
|
} catch (...) { }
|
||||||
|
if (actual_ach_name.empty()) { // fallback
|
||||||
|
actual_ach_name = ach_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if already achieved
|
||||||
|
bool achieved = false;
|
||||||
|
try {
|
||||||
|
auto ach = user_achievements.find(actual_ach_name);
|
||||||
|
if (ach != user_achievements.end()) {
|
||||||
|
achieved = ach->value("earned", false);
|
||||||
|
}
|
||||||
|
} catch (...) { }
|
||||||
|
if (achieved) return false;
|
||||||
|
|
||||||
|
// save new progress
|
||||||
|
try {
|
||||||
|
auto old_progress = user_achievements.value(actual_ach_name, nlohmann::json{}).value("progress", ~nCurProgress);
|
||||||
|
if (old_progress != nCurProgress) {
|
||||||
|
user_achievements[actual_ach_name]["progress"] = nCurProgress;
|
||||||
|
user_achievements[actual_ach_name]["max_progress"] = nMaxProgress;
|
||||||
|
|
||||||
|
save_achievements();
|
||||||
|
|
||||||
|
overlay->AddAchievementNotification(actual_ach_name, user_achievements[actual_ach_name], true);
|
||||||
|
}
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
{
|
||||||
|
UserStatsStored_t data{};
|
||||||
|
data.m_eResult = EResult::k_EResultOK;
|
||||||
|
data.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
UserAchievementStored_t data{};
|
||||||
|
data.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
data.m_bGroupAchievement = false;
|
||||||
|
data.m_nCurProgress = nCurProgress;
|
||||||
|
data.m_nMaxProgress = nMaxProgress;
|
||||||
|
ach_name.copy(data.m_rgchAchievementName, sizeof(data.m_rgchAchievementName) - 1);
|
||||||
|
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Used for iterating achievements. In general games should not need these functions because they should have a
|
||||||
|
// list of existing achievements compiled into them
|
||||||
|
uint32 Steam_User_Stats::GetNumAchievements()
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_ENTRY();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
return (uint32)defined_achievements.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get achievement name iAchievement in [0,GetNumAchievements)
|
||||||
|
const char * Steam_User_Stats::GetAchievementName( uint32 iAchievement )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_ENTRY();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (iAchievement >= sorted_achievement_names.size()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted_achievement_names[iAchievement].c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Friends achievements
|
||||||
|
|
||||||
|
bool Steam_User_Stats::GetUserAchievement( CSteamID steamIDUser, const char *pchName, bool *pbAchieved )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%s", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
|
||||||
|
if (steamIDUser == settings->get_local_steam_id()) {
|
||||||
|
return GetAchievement(pchName, pbAchieved);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See notes for GetAchievementAndUnlockTime above
|
||||||
|
bool Steam_User_Stats::GetUserAchievementAndUnlockTime( CSteamID steamIDUser, const char *pchName, bool *pbAchieved, uint32 *punUnlockTime )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%s", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
|
||||||
|
if (steamIDUser == settings->get_local_steam_id()) {
|
||||||
|
return GetAchievementAndUnlockTime(pchName, pbAchieved, punUnlockTime);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Requests that Steam fetch data on the percentage of players who have received each achievement
|
||||||
|
// for the game globally.
|
||||||
|
// This call is asynchronous, with the result returned in GlobalAchievementPercentagesReady_t.
|
||||||
|
STEAM_CALL_RESULT( GlobalAchievementPercentagesReady_t )
|
||||||
|
SteamAPICall_t Steam_User_Stats::RequestGlobalAchievementPercentages()
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_ENTRY();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
GlobalAchievementPercentagesReady_t data{};
|
||||||
|
data.m_eResult = EResult::k_EResultOK;
|
||||||
|
data.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get the info on the most achieved achievement for the game, returns an iterator index you can use to fetch
|
||||||
|
// the next most achieved afterwards. Will return -1 if there is no data on achievement
|
||||||
|
// percentages (ie, you haven't called RequestGlobalAchievementPercentages and waited on the callback).
|
||||||
|
int Steam_User_Stats::GetMostAchievedAchievementInfo( char *pchName, uint32 unNameBufLen, float *pflPercent, bool *pbAchieved )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_ENTRY();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (!pchName) return -1;
|
||||||
|
|
||||||
|
std::string name(GetAchievementName(0));
|
||||||
|
if (name.empty()) return -1;
|
||||||
|
|
||||||
|
if (pchName && unNameBufLen) {
|
||||||
|
memset(pchName, 0, unNameBufLen);
|
||||||
|
name.copy(pchName, unNameBufLen - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pflPercent) *pflPercent = 90;
|
||||||
|
if (pbAchieved) {
|
||||||
|
bool achieved = false;
|
||||||
|
GetAchievement(name.c_str(), &achieved);
|
||||||
|
*pbAchieved = achieved;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get the info on the next most achieved achievement for the game. Call this after GetMostAchievedAchievementInfo or another
|
||||||
|
// GetNextMostAchievedAchievementInfo call passing the iterator from the previous call. Returns -1 after the last
|
||||||
|
// achievement has been iterated.
|
||||||
|
int Steam_User_Stats::GetNextMostAchievedAchievementInfo( int iIteratorPrevious, char *pchName, uint32 unNameBufLen, float *pflPercent, bool *pbAchieved )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_ENTRY();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (iIteratorPrevious < 0) return -1;
|
||||||
|
|
||||||
|
unsigned iIteratorCurrent = static_cast<unsigned>(iIteratorPrevious + 1);
|
||||||
|
if (iIteratorCurrent >= defined_achievements.size()) return -1;
|
||||||
|
|
||||||
|
std::string name(GetAchievementName(iIteratorCurrent));
|
||||||
|
if (name.empty()) return -1;
|
||||||
|
|
||||||
|
if (pchName && unNameBufLen) {
|
||||||
|
memset(pchName, 0, unNameBufLen);
|
||||||
|
name.copy(pchName, unNameBufLen - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pflPercent) {
|
||||||
|
*pflPercent = (float)(90 * (defined_achievements.size() - iIteratorCurrent) / defined_achievements.size());
|
||||||
|
}
|
||||||
|
if (pbAchieved) {
|
||||||
|
bool achieved = false;
|
||||||
|
GetAchievement(name.c_str(), &achieved);
|
||||||
|
*pbAchieved = achieved;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<int>(iIteratorCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the percentage of users who have achieved the specified achievement.
|
||||||
|
bool Steam_User_Stats::GetAchievementAchievedPercent( const char *pchName, float *pflPercent )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
auto it = defined_achievements_find(pchName);
|
||||||
|
if (defined_achievements.end() == it) return false;
|
||||||
|
|
||||||
|
size_t idx = it - defined_achievements.begin();
|
||||||
|
if (pflPercent) {
|
||||||
|
*pflPercent = (float)(90 * (defined_achievements.size() - idx) / defined_achievements.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For achievements that have related Progress stats, use this to query what the bounds of that progress are.
|
||||||
|
// You may want this info to selectively call IndicateAchievementProgress when appropriate milestones of progress
|
||||||
|
// have been made, to show a progress notification to the user.
|
||||||
|
bool Steam_User_Stats::GetAchievementProgressLimits( const char *pchName, int32 *pnMinProgress, int32 *pnMaxProgress )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
float fMinProgress{};
|
||||||
|
float fMaxProgress{};
|
||||||
|
bool ret = GetAchievementProgressLimits(pchName, &fMinProgress, &fMaxProgress);
|
||||||
|
if (ret) {
|
||||||
|
if (pnMinProgress) *pnMinProgress = static_cast<int32>(fMinProgress);
|
||||||
|
if (pnMaxProgress) *pnMaxProgress = static_cast<int32>(fMaxProgress);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Steam_User_Stats::GetAchievementProgressLimits( const char *pchName, float *pfMinProgress, float *pfMaxProgress )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
|
||||||
|
auto it = defined_achievements.end();
|
||||||
|
try {
|
||||||
|
it = defined_achievements_find(pchName);
|
||||||
|
}
|
||||||
|
catch (...) {}
|
||||||
|
if (defined_achievements.end() == it) return false;
|
||||||
|
|
||||||
|
if (pfMinProgress) *pfMinProgress = 0;
|
||||||
|
if (pfMaxProgress) *pfMaxProgress = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::string pch_name = it->value("name", std::string());
|
||||||
|
auto ach = user_achievements.find(pch_name);
|
||||||
|
if (user_achievements.end() != ach) {
|
||||||
|
auto it_progress = ach->find("progress");
|
||||||
|
auto it_max_progress = ach->find("max_progress");
|
||||||
|
if (ach->end() == it_progress || ach->end() == it_max_progress) return false;
|
||||||
|
|
||||||
|
if (pfMinProgress) {
|
||||||
|
try {
|
||||||
|
if (it_progress->is_number()) {
|
||||||
|
*pfMinProgress = it_progress->get<float>();
|
||||||
|
} else {
|
||||||
|
auto s_ptr = it_progress->get_ptr<std::string*>();
|
||||||
|
if (s_ptr) {
|
||||||
|
*pfMinProgress = std::stof(*s_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
if (pfMaxProgress) {
|
||||||
|
try {
|
||||||
|
if (it_max_progress->is_number()) {
|
||||||
|
*pfMaxProgress = it_max_progress->get<float>();
|
||||||
|
} else {
|
||||||
|
auto s_ptr = it_max_progress->get_ptr<std::string*>();
|
||||||
|
if (s_ptr) {
|
||||||
|
*pfMaxProgress = std::stof(*s_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...) {}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- steam callbacks
|
||||||
|
|
||||||
|
void Steam_User_Stats::load_achievements_icons()
|
||||||
|
{
|
||||||
|
if (achievements_icons_loaded) return;
|
||||||
|
if (settings->lazy_load_achievements_icons) {
|
||||||
|
achievements_icons_loaded = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto & defined_ach : defined_achievements) {
|
||||||
|
load_ach_icon(defined_ach, true);
|
||||||
|
load_ach_icon(defined_ach, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
achievements_icons_loaded = true;
|
||||||
|
}
|
689
dll/steam_user_stats_leaderboard.cpp
Normal file
689
dll/steam_user_stats_leaderboard.cpp
Normal file
@ -0,0 +1,689 @@
|
|||||||
|
/* Copyright (C) 2019 Mr Goldberg
|
||||||
|
This file is part of the Goldberg Emulator
|
||||||
|
|
||||||
|
The Goldberg Emulator is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The Goldberg Emulator is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the Goldberg Emulator; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include "dll/steam_user_stats.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
|
||||||
|
// --- Steam_Leaderboard ---
|
||||||
|
|
||||||
|
Steam_Leaderboard_Entry* Steam_Leaderboard::find_recent_entry(const CSteamID &steamid) const
|
||||||
|
{
|
||||||
|
auto my_it = std::find_if(entries.begin(), entries.end(), [&steamid](const Steam_Leaderboard_Entry &item) {
|
||||||
|
return item.steam_id == steamid;
|
||||||
|
});
|
||||||
|
if (entries.end() == my_it) return nullptr;
|
||||||
|
return const_cast<Steam_Leaderboard_Entry*>(&*my_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_Leaderboard::remove_entries(const CSteamID &steamid)
|
||||||
|
{
|
||||||
|
auto rm_it = std::remove_if(entries.begin(), entries.end(), [&](const Steam_Leaderboard_Entry &item){
|
||||||
|
return item.steam_id == steamid;
|
||||||
|
});
|
||||||
|
if (entries.end() != rm_it) entries.erase(rm_it, entries.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_Leaderboard::remove_duplicate_entries()
|
||||||
|
{
|
||||||
|
if (entries.size() <= 1) return;
|
||||||
|
|
||||||
|
auto rm = std::remove_if(entries.begin(), entries.end(), [&](const Steam_Leaderboard_Entry& item) {
|
||||||
|
auto recent = find_recent_entry(item.steam_id);
|
||||||
|
return &item != recent;
|
||||||
|
});
|
||||||
|
if (entries.end() != rm) entries.erase(rm, entries.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_Leaderboard::sort_entries()
|
||||||
|
{
|
||||||
|
if (sort_method == k_ELeaderboardSortMethodNone) return;
|
||||||
|
if (entries.size() <= 1) return;
|
||||||
|
|
||||||
|
std::sort(entries.begin(), entries.end(), [this](const Steam_Leaderboard_Entry &item1, const Steam_Leaderboard_Entry &item2) {
|
||||||
|
if (sort_method == k_ELeaderboardSortMethodAscending) {
|
||||||
|
return item1.score < item2.score;
|
||||||
|
} else { // k_ELeaderboardSortMethodDescending
|
||||||
|
return item1.score > item2.score;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Steam_Leaderboard ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
layout of each item in the leaderboard file
|
||||||
|
| steamid - lower 32-bits | steamid - higher 32-bits | score (4 bytes) | score details count (4 bytes) | score details array (4 bytes each) ...
|
||||||
|
[0] | [1] | [2] | [3] | [4]
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ main header ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::vector<Steam_Leaderboard_Entry> Steam_User_Stats::load_leaderboard_entries(const std::string &name)
|
||||||
|
{
|
||||||
|
constexpr const static unsigned int MAIN_HEADER_ELEMENTS_COUNT = 4;
|
||||||
|
constexpr const static unsigned int ELEMENT_SIZE = (unsigned int)sizeof(uint32_t);
|
||||||
|
|
||||||
|
std::vector<Steam_Leaderboard_Entry> out{};
|
||||||
|
|
||||||
|
std::string leaderboard_name(common_helpers::ascii_to_lowercase(name));
|
||||||
|
unsigned read_bytes = local_storage->file_size(Local_Storage::leaderboard_storage_folder, leaderboard_name);
|
||||||
|
if ((read_bytes == 0) ||
|
||||||
|
(read_bytes < (ELEMENT_SIZE * MAIN_HEADER_ELEMENTS_COUNT)) ||
|
||||||
|
(read_bytes % ELEMENT_SIZE) != 0) {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> output(read_bytes / ELEMENT_SIZE);
|
||||||
|
if (local_storage->get_data(Local_Storage::leaderboard_storage_folder, leaderboard_name, (char* )output.data(), read_bytes) != read_bytes) return out;
|
||||||
|
|
||||||
|
unsigned int i = 0;
|
||||||
|
while (true) {
|
||||||
|
if ((i + MAIN_HEADER_ELEMENTS_COUNT) > output.size()) break; // invalid main header, or end of buffer
|
||||||
|
|
||||||
|
Steam_Leaderboard_Entry new_entry{};
|
||||||
|
new_entry.steam_id = CSteamID((uint64)output[i] + (((uint64)output[i + 1]) << 32));
|
||||||
|
new_entry.score = (int32)output[i + 2];
|
||||||
|
uint32_t details_count = output[i + 3];
|
||||||
|
i += MAIN_HEADER_ELEMENTS_COUNT; // skip main header
|
||||||
|
|
||||||
|
if ((i + details_count) > output.size()) break; // invalid score details count
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < details_count; ++j) {
|
||||||
|
new_entry.score_details.push_back(output[i]);
|
||||||
|
++i; // move past this score detail
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_DEBUG("'%s': user %llu, score %i, details count = %zu",
|
||||||
|
name.c_str(), new_entry.steam_id.ConvertToUint64(), new_entry.score, new_entry.score_details.size()
|
||||||
|
);
|
||||||
|
out.push_back(new_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_DEBUG("'%s' total entries = %zu", name.c_str(), out.size());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_User_Stats::save_my_leaderboard_entry(const Steam_Leaderboard &leaderboard)
|
||||||
|
{
|
||||||
|
auto my_entry = leaderboard.find_recent_entry(settings->get_local_steam_id());
|
||||||
|
if (!my_entry) return; // we don't have a score entry
|
||||||
|
|
||||||
|
PRINT_DEBUG("saving entries for leaderboard '%s'", leaderboard.name.c_str());
|
||||||
|
|
||||||
|
std::vector<uint32_t> output{};
|
||||||
|
|
||||||
|
uint64_t steam_id = my_entry->steam_id.ConvertToUint64();
|
||||||
|
output.push_back((uint32_t)(steam_id & 0xFFFFFFFF)); // lower 4 bytes
|
||||||
|
output.push_back((uint32_t)(steam_id >> 32)); // higher 4 bytes
|
||||||
|
|
||||||
|
output.push_back(my_entry->score);
|
||||||
|
output.push_back((uint32_t)my_entry->score_details.size());
|
||||||
|
for (const auto &detail : my_entry->score_details) {
|
||||||
|
output.push_back(detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string leaderboard_name(common_helpers::ascii_to_lowercase(leaderboard.name));
|
||||||
|
unsigned int buffer_size = static_cast<unsigned int>(output.size() * sizeof(output[0])); // in bytes
|
||||||
|
local_storage->store_data(Local_Storage::leaderboard_storage_folder, leaderboard_name, (char* )&output[0], buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_Leaderboard_Entry* Steam_User_Stats::update_leaderboard_entry(Steam_Leaderboard &leaderboard, const Steam_Leaderboard_Entry &entry, bool overwrite)
|
||||||
|
{
|
||||||
|
bool added = false;
|
||||||
|
auto user_entry = leaderboard.find_recent_entry(entry.steam_id);
|
||||||
|
if (!user_entry) { // user doesn't have an entry yet, create one
|
||||||
|
added = true;
|
||||||
|
leaderboard.entries.push_back(entry);
|
||||||
|
user_entry = &leaderboard.entries.back();
|
||||||
|
} else if (overwrite) {
|
||||||
|
added = true;
|
||||||
|
*user_entry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (added) { // if we added a new entry then we have to sort and find the target entry again
|
||||||
|
leaderboard.sort_entries();
|
||||||
|
user_entry = leaderboard.find_recent_entry(entry.steam_id);
|
||||||
|
PRINT_DEBUG("added/updated entry for user %llu", entry.steam_id.ConvertToUint64());
|
||||||
|
}
|
||||||
|
|
||||||
|
return user_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int Steam_User_Stats::find_cached_leaderboard(const std::string &name)
|
||||||
|
{
|
||||||
|
unsigned index = 1;
|
||||||
|
for (const auto &leaderboard : cached_leaderboards) {
|
||||||
|
if (common_helpers::str_cmp_insensitive(leaderboard.name, name)) return index;
|
||||||
|
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Steam_User_Stats::cache_leaderboard_ifneeded(const std::string &name, ELeaderboardSortMethod eLeaderboardSortMethod, ELeaderboardDisplayType eLeaderboardDisplayType)
|
||||||
|
{
|
||||||
|
unsigned int board_handle = find_cached_leaderboard(name);
|
||||||
|
if (board_handle) return board_handle;
|
||||||
|
// PRINT_DEBUG("cache miss '%s'", name.c_str());
|
||||||
|
|
||||||
|
// create a new entry in-memory and try reading the entries from disk
|
||||||
|
struct Steam_Leaderboard new_board{};
|
||||||
|
new_board.name = common_helpers::ascii_to_lowercase(name);
|
||||||
|
new_board.sort_method = eLeaderboardSortMethod;
|
||||||
|
new_board.display_type = eLeaderboardDisplayType;
|
||||||
|
new_board.entries = load_leaderboard_entries(name);
|
||||||
|
|
||||||
|
new_board.sort_entries();
|
||||||
|
new_board.remove_duplicate_entries();
|
||||||
|
|
||||||
|
// save it in memory for later
|
||||||
|
cached_leaderboards.push_back(new_board);
|
||||||
|
board_handle = static_cast<unsigned int>(cached_leaderboards.size());
|
||||||
|
|
||||||
|
PRINT_DEBUG("cached a new leaderboard '%s' %i %i",
|
||||||
|
new_board.name.c_str(), (int)eLeaderboardSortMethod, (int)eLeaderboardDisplayType
|
||||||
|
);
|
||||||
|
return board_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_User_Stats::send_my_leaderboard_score(const Steam_Leaderboard &board, const CSteamID *steamid, bool want_scores_back)
|
||||||
|
{
|
||||||
|
if (!settings->share_leaderboards_over_network) return;
|
||||||
|
|
||||||
|
const auto my_entry = board.find_recent_entry(settings->get_local_steam_id());
|
||||||
|
Leaderboards_Messages::UserScoreEntry *score_entry_msg = nullptr;
|
||||||
|
|
||||||
|
if (my_entry) {
|
||||||
|
score_entry_msg = new Leaderboards_Messages::UserScoreEntry();
|
||||||
|
score_entry_msg->set_score(my_entry->score);
|
||||||
|
score_entry_msg->mutable_score_details()->Assign(my_entry->score_details.begin(), my_entry->score_details.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto board_info_msg = new Leaderboards_Messages::LeaderboardInfo();
|
||||||
|
board_info_msg->set_allocated_board_name(new std::string(board.name));
|
||||||
|
board_info_msg->set_sort_method(board.sort_method);
|
||||||
|
board_info_msg->set_display_type(board.display_type);
|
||||||
|
|
||||||
|
auto board_msg = new Leaderboards_Messages();
|
||||||
|
if (want_scores_back) board_msg->set_type(Leaderboards_Messages::UpdateUserScoreMutual);
|
||||||
|
else board_msg->set_type(Leaderboards_Messages::UpdateUserScore);
|
||||||
|
board_msg->set_appid(settings->get_local_game_id().AppID());
|
||||||
|
board_msg->set_allocated_leaderboard_info(board_info_msg);
|
||||||
|
// if we have an entry
|
||||||
|
if (score_entry_msg) board_msg->set_allocated_user_score_entry(score_entry_msg);
|
||||||
|
|
||||||
|
Common_Message common_msg{};
|
||||||
|
common_msg.set_source_id(settings->get_local_steam_id().ConvertToUint64());
|
||||||
|
if (steamid) common_msg.set_dest_id(steamid->ConvertToUint64());
|
||||||
|
common_msg.set_allocated_leaderboards_messages(board_msg);
|
||||||
|
|
||||||
|
if (steamid) network->sendTo(&common_msg, false);
|
||||||
|
else network->sendToAll(&common_msg, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_User_Stats::request_user_leaderboard_entry(const Steam_Leaderboard &board, const CSteamID &steamid)
|
||||||
|
{
|
||||||
|
if (!settings->share_leaderboards_over_network) return;
|
||||||
|
|
||||||
|
auto board_info_msg = new Leaderboards_Messages::LeaderboardInfo();
|
||||||
|
board_info_msg->set_allocated_board_name(new std::string(board.name));
|
||||||
|
board_info_msg->set_sort_method(board.sort_method);
|
||||||
|
board_info_msg->set_display_type(board.display_type);
|
||||||
|
|
||||||
|
auto board_msg = new Leaderboards_Messages();
|
||||||
|
board_msg->set_type(Leaderboards_Messages::RequestUserScore);
|
||||||
|
board_msg->set_appid(settings->get_local_game_id().AppID());
|
||||||
|
board_msg->set_allocated_leaderboard_info(board_info_msg);
|
||||||
|
|
||||||
|
Common_Message common_msg{};
|
||||||
|
common_msg.set_source_id(settings->get_local_steam_id().ConvertToUint64());
|
||||||
|
common_msg.set_dest_id(steamid.ConvertToUint64());
|
||||||
|
common_msg.set_allocated_leaderboards_messages(board_msg);
|
||||||
|
|
||||||
|
network->sendTo(&common_msg, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_User_Stats::steam_user_stats_network_leaderboards(void *object, Common_Message *msg)
|
||||||
|
{
|
||||||
|
// PRINT_DEBUG_ENTRY();
|
||||||
|
|
||||||
|
auto inst = (Steam_User_Stats *)object;
|
||||||
|
inst->network_callback_leaderboards(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Leaderboard functions
|
||||||
|
|
||||||
|
// asks the Steam back-end for a leaderboard by name, and will create it if it's not yet
|
||||||
|
// This call is asynchronous, with the result returned in LeaderboardFindResult_t
|
||||||
|
STEAM_CALL_RESULT(LeaderboardFindResult_t)
|
||||||
|
SteamAPICall_t Steam_User_Stats::FindOrCreateLeaderboard( const char *pchLeaderboardName, ELeaderboardSortMethod eLeaderboardSortMethod, ELeaderboardDisplayType eLeaderboardDisplayType )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchLeaderboardName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (!pchLeaderboardName) {
|
||||||
|
LeaderboardFindResult_t data{};
|
||||||
|
data.m_hSteamLeaderboard = 0;
|
||||||
|
data.m_bLeaderboardFound = 0;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int board_handle = cache_leaderboard_ifneeded(pchLeaderboardName, eLeaderboardSortMethod, eLeaderboardDisplayType);
|
||||||
|
send_my_leaderboard_score(cached_leaderboards[board_handle - 1], nullptr, true);
|
||||||
|
|
||||||
|
LeaderboardFindResult_t data{};
|
||||||
|
data.m_hSteamLeaderboard = board_handle;
|
||||||
|
data.m_bLeaderboardFound = 1;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is the timing ok?
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// as above, but won't create the leaderboard if it's not found
|
||||||
|
// This call is asynchronous, with the result returned in LeaderboardFindResult_t
|
||||||
|
STEAM_CALL_RESULT( LeaderboardFindResult_t )
|
||||||
|
SteamAPICall_t Steam_User_Stats::FindLeaderboard( const char *pchLeaderboardName )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchLeaderboardName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (!pchLeaderboardName) {
|
||||||
|
LeaderboardFindResult_t data{};
|
||||||
|
data.m_hSteamLeaderboard = 0;
|
||||||
|
data.m_bLeaderboardFound = 0;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_lower(common_helpers::ascii_to_lowercase(pchLeaderboardName));
|
||||||
|
const auto &settings_Leaderboards = settings->getLeaderboards();
|
||||||
|
auto it = settings_Leaderboards.begin();
|
||||||
|
for (; settings_Leaderboards.end() != it; ++it) {
|
||||||
|
if (common_helpers::str_cmp_insensitive(it->first, name_lower)) break;
|
||||||
|
}
|
||||||
|
if (settings_Leaderboards.end() != it) {
|
||||||
|
auto &config = it->second;
|
||||||
|
return FindOrCreateLeaderboard(pchLeaderboardName, config.sort_method, config.display_type);
|
||||||
|
} else if (!settings->disable_leaderboards_create_unknown) {
|
||||||
|
return FindOrCreateLeaderboard(pchLeaderboardName, k_ELeaderboardSortMethodDescending, k_ELeaderboardDisplayTypeNumeric);
|
||||||
|
} else {
|
||||||
|
LeaderboardFindResult_t data{};
|
||||||
|
data.m_hSteamLeaderboard = find_cached_leaderboard(name_lower);
|
||||||
|
data.m_bLeaderboardFound = !!data.m_hSteamLeaderboard;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns the name of a leaderboard
|
||||||
|
const char * Steam_User_Stats::GetLeaderboardName( SteamLeaderboard_t hSteamLeaderboard )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu", hSteamLeaderboard);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (hSteamLeaderboard > cached_leaderboards.size() || hSteamLeaderboard <= 0) return "";
|
||||||
|
|
||||||
|
return cached_leaderboards[static_cast<unsigned>(hSteamLeaderboard - 1)].name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns the total number of entries in a leaderboard, as of the last request
|
||||||
|
int Steam_User_Stats::GetLeaderboardEntryCount( SteamLeaderboard_t hSteamLeaderboard )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu", hSteamLeaderboard);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (hSteamLeaderboard > cached_leaderboards.size() || hSteamLeaderboard <= 0) return 0;
|
||||||
|
|
||||||
|
return (int)cached_leaderboards[static_cast<unsigned>(hSteamLeaderboard - 1)].entries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns the sort method of the leaderboard
|
||||||
|
ELeaderboardSortMethod Steam_User_Stats::GetLeaderboardSortMethod( SteamLeaderboard_t hSteamLeaderboard )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu", hSteamLeaderboard);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (hSteamLeaderboard > cached_leaderboards.size() || hSteamLeaderboard <= 0) return k_ELeaderboardSortMethodNone;
|
||||||
|
|
||||||
|
return cached_leaderboards[static_cast<unsigned>(hSteamLeaderboard - 1)].sort_method;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns the display type of the leaderboard
|
||||||
|
ELeaderboardDisplayType Steam_User_Stats::GetLeaderboardDisplayType( SteamLeaderboard_t hSteamLeaderboard )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu", hSteamLeaderboard);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (hSteamLeaderboard > cached_leaderboards.size() || hSteamLeaderboard <= 0) return k_ELeaderboardDisplayTypeNone;
|
||||||
|
|
||||||
|
return cached_leaderboards[static_cast<unsigned>(hSteamLeaderboard - 1)].display_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Asks the Steam back-end for a set of rows in the leaderboard.
|
||||||
|
// This call is asynchronous, with the result returned in LeaderboardScoresDownloaded_t
|
||||||
|
// LeaderboardScoresDownloaded_t will contain a handle to pull the results from GetDownloadedLeaderboardEntries() (below)
|
||||||
|
// You can ask for more entries than exist, and it will return as many as do exist.
|
||||||
|
// k_ELeaderboardDataRequestGlobal requests rows in the leaderboard from the full table, with nRangeStart & nRangeEnd in the range [1, TotalEntries]
|
||||||
|
// k_ELeaderboardDataRequestGlobalAroundUser requests rows around the current user, nRangeStart being negate
|
||||||
|
// e.g. DownloadLeaderboardEntries( hLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -3, 3 ) will return 7 rows, 3 before the user, 3 after
|
||||||
|
// k_ELeaderboardDataRequestFriends requests all the rows for friends of the current user
|
||||||
|
STEAM_CALL_RESULT( LeaderboardScoresDownloaded_t )
|
||||||
|
SteamAPICall_t Steam_User_Stats::DownloadLeaderboardEntries( SteamLeaderboard_t hSteamLeaderboard, ELeaderboardDataRequest eLeaderboardDataRequest, int nRangeStart, int nRangeEnd )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu %i [%i, %i]", hSteamLeaderboard, eLeaderboardDataRequest, nRangeStart, nRangeEnd);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (hSteamLeaderboard > cached_leaderboards.size() || hSteamLeaderboard <= 0) return k_uAPICallInvalid; //might return callresult even if hSteamLeaderboard is invalid
|
||||||
|
|
||||||
|
int entries_count = (int)cached_leaderboards[static_cast<unsigned>(hSteamLeaderboard - 1)].entries.size();
|
||||||
|
// https://partner.steamgames.com/doc/api/ISteamUserStats#ELeaderboardDataRequest
|
||||||
|
if (eLeaderboardDataRequest != k_ELeaderboardDataRequestFriends) {
|
||||||
|
int required_count = nRangeEnd - nRangeStart + 1;
|
||||||
|
if (required_count < 0) required_count = 0;
|
||||||
|
|
||||||
|
if (required_count < entries_count) entries_count = required_count;
|
||||||
|
}
|
||||||
|
LeaderboardScoresDownloaded_t data{};
|
||||||
|
data.m_hSteamLeaderboard = hSteamLeaderboard;
|
||||||
|
data.m_hSteamLeaderboardEntries = hSteamLeaderboard;
|
||||||
|
data.m_cEntryCount = entries_count;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok?
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// as above, but downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is k_ELeaderboardDataRequestUsers
|
||||||
|
// if a user doesn't have a leaderboard entry, they won't be included in the result
|
||||||
|
// a max of 100 users can be downloaded at a time, with only one outstanding call at a time
|
||||||
|
STEAM_METHOD_DESC(Downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is k_ELeaderboardDataRequestUsers)
|
||||||
|
STEAM_CALL_RESULT( LeaderboardScoresDownloaded_t )
|
||||||
|
SteamAPICall_t Steam_User_Stats::DownloadLeaderboardEntriesForUsers( SteamLeaderboard_t hSteamLeaderboard,
|
||||||
|
STEAM_ARRAY_COUNT_D(cUsers, Array of users to retrieve) CSteamID *prgUsers, int cUsers )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%i %llu", cUsers, cUsers > 0 ? prgUsers[0].ConvertToUint64() : 0);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (hSteamLeaderboard > cached_leaderboards.size() || hSteamLeaderboard <= 0) return k_uAPICallInvalid; //might return callresult even if hSteamLeaderboard is invalid
|
||||||
|
|
||||||
|
auto& board = cached_leaderboards[static_cast<unsigned>(hSteamLeaderboard - 1)];
|
||||||
|
bool ok = true;
|
||||||
|
int total_count = 0;
|
||||||
|
if (prgUsers && cUsers > 0) {
|
||||||
|
for (int i = 0; i < cUsers; ++i) {
|
||||||
|
const auto &user_steamid = prgUsers[i];
|
||||||
|
if (!user_steamid.IsValid()) {
|
||||||
|
ok = false;
|
||||||
|
PRINT_DEBUG("bad userid %llu", user_steamid.ConvertToUint64());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (board.find_recent_entry(user_steamid)) ++total_count;
|
||||||
|
|
||||||
|
request_user_leaderboard_entry(board, user_steamid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_DEBUG("total count %i", total_count);
|
||||||
|
// https://partner.steamgames.com/doc/api/ISteamUserStats#DownloadLeaderboardEntriesForUsers
|
||||||
|
if (!ok || total_count > 100) return k_uAPICallInvalid;
|
||||||
|
|
||||||
|
LeaderboardScoresDownloaded_t data{};
|
||||||
|
data.m_hSteamLeaderboard = hSteamLeaderboard;
|
||||||
|
data.m_hSteamLeaderboardEntries = hSteamLeaderboard;
|
||||||
|
data.m_cEntryCount = total_count;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok?
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns data about a single leaderboard entry
|
||||||
|
// use a for loop from 0 to LeaderboardScoresDownloaded_t::m_cEntryCount to get all the downloaded entries
|
||||||
|
// e.g.
|
||||||
|
// void OnLeaderboardScoresDownloaded( LeaderboardScoresDownloaded_t *pLeaderboardScoresDownloaded )
|
||||||
|
// {
|
||||||
|
// for ( int index = 0; index < pLeaderboardScoresDownloaded->m_cEntryCount; index++ )
|
||||||
|
// {
|
||||||
|
// LeaderboardEntry_t leaderboardEntry;
|
||||||
|
// int32 details[3]; // we know this is how many we've stored previously
|
||||||
|
// GetDownloadedLeaderboardEntry( pLeaderboardScoresDownloaded->m_hSteamLeaderboardEntries, index, &leaderboardEntry, details, 3 );
|
||||||
|
// assert( leaderboardEntry.m_cDetails == 3 );
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// once you've accessed all the entries, the data will be free'd, and the SteamLeaderboardEntries_t handle will become invalid
|
||||||
|
bool Steam_User_Stats::GetDownloadedLeaderboardEntry( SteamLeaderboardEntries_t hSteamLeaderboardEntries, int index, LeaderboardEntry_t *pLeaderboardEntry, int32 *pDetails, int cDetailsMax )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("[%i] (%i) %llu %p %p", index, cDetailsMax, hSteamLeaderboardEntries, pLeaderboardEntry, pDetails);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (hSteamLeaderboardEntries > cached_leaderboards.size() || hSteamLeaderboardEntries <= 0) return false;
|
||||||
|
|
||||||
|
const auto &board = cached_leaderboards[static_cast<unsigned>(hSteamLeaderboardEntries - 1)];
|
||||||
|
if (index < 0 || static_cast<size_t>(index) >= board.entries.size()) return false;
|
||||||
|
|
||||||
|
const auto &target_entry = board.entries[index];
|
||||||
|
|
||||||
|
if (pLeaderboardEntry) {
|
||||||
|
LeaderboardEntry_t entry{};
|
||||||
|
entry.m_steamIDUser = target_entry.steam_id;
|
||||||
|
entry.m_nGlobalRank = 1 + (int)(&target_entry - &board.entries[0]);
|
||||||
|
entry.m_nScore = target_entry.score;
|
||||||
|
|
||||||
|
*pLeaderboardEntry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDetails && cDetailsMax > 0) {
|
||||||
|
for (unsigned i = 0; i < target_entry.score_details.size() && i < static_cast<unsigned>(cDetailsMax); ++i) {
|
||||||
|
pDetails[i] = target_entry.score_details[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Uploads a user score to the Steam back-end.
|
||||||
|
// This call is asynchronous, with the result returned in LeaderboardScoreUploaded_t
|
||||||
|
// Details are extra game-defined information regarding how the user got that score
|
||||||
|
// pScoreDetails points to an array of int32's, cScoreDetailsCount is the number of int32's in the list
|
||||||
|
STEAM_CALL_RESULT( LeaderboardScoreUploaded_t )
|
||||||
|
SteamAPICall_t Steam_User_Stats::UploadLeaderboardScore( SteamLeaderboard_t hSteamLeaderboard, ELeaderboardUploadScoreMethod eLeaderboardUploadScoreMethod, int32 nScore, const int32 *pScoreDetails, int cScoreDetailsCount )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu %i", hSteamLeaderboard, nScore);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
if (hSteamLeaderboard > cached_leaderboards.size() || hSteamLeaderboard <= 0) return k_uAPICallInvalid; //TODO: might return callresult even if hSteamLeaderboard is invalid
|
||||||
|
|
||||||
|
auto &board = cached_leaderboards[static_cast<unsigned>(hSteamLeaderboard - 1)];
|
||||||
|
auto my_entry = board.find_recent_entry(settings->get_local_steam_id());
|
||||||
|
int current_rank = my_entry
|
||||||
|
? 1 + (int)(my_entry - &board.entries[0])
|
||||||
|
: 0;
|
||||||
|
int new_rank = current_rank;
|
||||||
|
|
||||||
|
bool score_updated = false;
|
||||||
|
if (my_entry) {
|
||||||
|
switch (eLeaderboardUploadScoreMethod)
|
||||||
|
{
|
||||||
|
case k_ELeaderboardUploadScoreMethodKeepBest: { // keep user's best score
|
||||||
|
if (board.sort_method == k_ELeaderboardSortMethodAscending) { // keep user's lowest score
|
||||||
|
score_updated = nScore < my_entry->score;
|
||||||
|
} else { // keep user's highest score
|
||||||
|
score_updated = nScore > my_entry->score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case k_ELeaderboardUploadScoreMethodForceUpdate: { // always replace score with specified
|
||||||
|
score_updated = my_entry->score != nScore;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
} else { // no entry yet for us
|
||||||
|
score_updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (score_updated || (eLeaderboardUploadScoreMethod == k_ELeaderboardUploadScoreMethodForceUpdate)) {
|
||||||
|
Steam_Leaderboard_Entry new_entry{};
|
||||||
|
new_entry.steam_id = settings->get_local_steam_id();
|
||||||
|
new_entry.score = nScore;
|
||||||
|
if (pScoreDetails && cScoreDetailsCount > 0) {
|
||||||
|
for (int i = 0; i < cScoreDetailsCount; ++i) {
|
||||||
|
new_entry.score_details.push_back(pScoreDetails[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_leaderboard_entry(board, new_entry);
|
||||||
|
new_rank = 1 + (int)(board.find_recent_entry(settings->get_local_steam_id()) - &board.entries[0]);
|
||||||
|
|
||||||
|
// check again in case this was a forced update
|
||||||
|
// avoid disk write if score is the same
|
||||||
|
if (score_updated) save_my_leaderboard_entry(board);
|
||||||
|
send_my_leaderboard_score(board);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaderboardScoreUploaded_t data{};
|
||||||
|
data.m_bSuccess = 1; //needs to be success or DOA6 freezes when uploading score.
|
||||||
|
data.m_hSteamLeaderboard = hSteamLeaderboard;
|
||||||
|
data.m_nScore = nScore;
|
||||||
|
data.m_bScoreChanged = score_updated;
|
||||||
|
data.m_nGlobalRankNew = new_rank;
|
||||||
|
data.m_nGlobalRankPrevious = current_rank;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1); // TODO is this timing ok?
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SteamAPICall_t Steam_User_Stats::UploadLeaderboardScore( SteamLeaderboard_t hSteamLeaderboard, int32 nScore, int32 *pScoreDetails, int cScoreDetailsCount )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("old");
|
||||||
|
return UploadLeaderboardScore(hSteamLeaderboard, k_ELeaderboardUploadScoreMethodKeepBest, nScore, pScoreDetails, cScoreDetailsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Attaches a piece of user generated content the user's entry on a leaderboard.
|
||||||
|
// hContent is a handle to a piece of user generated content that was shared using ISteamUserRemoteStorage::FileShare().
|
||||||
|
// This call is asynchronous, with the result returned in LeaderboardUGCSet_t.
|
||||||
|
STEAM_CALL_RESULT( LeaderboardUGCSet_t )
|
||||||
|
SteamAPICall_t Steam_User_Stats::AttachLeaderboardUGC( SteamLeaderboard_t hSteamLeaderboard, UGCHandle_t hUGC )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_TODO();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
LeaderboardUGCSet_t data{};
|
||||||
|
if (hSteamLeaderboard > cached_leaderboards.size() || hSteamLeaderboard <= 0) {
|
||||||
|
data.m_eResult = k_EResultFail;
|
||||||
|
} else {
|
||||||
|
data.m_eResult = k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.m_hSteamLeaderboard = hSteamLeaderboard;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- networking callbacks
|
||||||
|
// only triggered when we have a message
|
||||||
|
|
||||||
|
// someone updated their score
|
||||||
|
void Steam_User_Stats::network_leaderboard_update_score(Common_Message *msg, Steam_Leaderboard &board, bool send_score_back)
|
||||||
|
{
|
||||||
|
CSteamID sender_steamid((uint64)msg->source_id());
|
||||||
|
PRINT_DEBUG("got score for user %llu on leaderboard '%s' (send our score back=%i)",
|
||||||
|
(uint64)msg->source_id(), board.name.c_str(), (int)send_score_back
|
||||||
|
);
|
||||||
|
|
||||||
|
// when players initally load a board, and they don't have an entry in it,
|
||||||
|
// they send this msg but without their user score entry
|
||||||
|
if (msg->leaderboards_messages().has_user_score_entry()) {
|
||||||
|
const auto &user_score_msg = msg->leaderboards_messages().user_score_entry();
|
||||||
|
|
||||||
|
Steam_Leaderboard_Entry updated_entry{};
|
||||||
|
updated_entry.steam_id = sender_steamid;
|
||||||
|
updated_entry.score = user_score_msg.score();
|
||||||
|
updated_entry.score_details.reserve(user_score_msg.score_details().size());
|
||||||
|
updated_entry.score_details.assign(user_score_msg.score_details().begin(), user_score_msg.score_details().end());
|
||||||
|
update_leaderboard_entry(board, updated_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the sender wants back our score, send it to all, not just them
|
||||||
|
// in case we have 3 or more players and none of them have our data
|
||||||
|
if (send_score_back) send_my_leaderboard_score(board);
|
||||||
|
}
|
||||||
|
|
||||||
|
// someone is requesting our score on a leaderboard
|
||||||
|
void Steam_User_Stats::network_leaderboard_send_my_score(Common_Message *msg, const Steam_Leaderboard &board)
|
||||||
|
{
|
||||||
|
CSteamID sender_steamid((uint64)msg->source_id());
|
||||||
|
PRINT_DEBUG("user %llu requested our score for leaderboard '%s'", (uint64)msg->source_id(), board.name.c_str());
|
||||||
|
|
||||||
|
send_my_leaderboard_score(board, &sender_steamid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_User_Stats::network_callback_leaderboards(Common_Message *msg)
|
||||||
|
{
|
||||||
|
// network->sendToAll() sends to current user also
|
||||||
|
if (msg->source_id() == settings->get_local_steam_id().ConvertToUint64()) return;
|
||||||
|
if (settings->get_local_game_id().AppID() != msg->leaderboards_messages().appid()) return;
|
||||||
|
|
||||||
|
if (!msg->leaderboards_messages().has_leaderboard_info()) {
|
||||||
|
PRINT_DEBUG("error empty leaderboard msg");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &board_info_msg = msg->leaderboards_messages().leaderboard_info();
|
||||||
|
|
||||||
|
PRINT_DEBUG("attempting to cache leaderboard '%s'", board_info_msg.board_name().c_str());
|
||||||
|
unsigned int board_handle = cache_leaderboard_ifneeded(
|
||||||
|
board_info_msg.board_name(),
|
||||||
|
(ELeaderboardSortMethod)board_info_msg.sort_method(),
|
||||||
|
(ELeaderboardDisplayType)board_info_msg.display_type()
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (msg->leaderboards_messages().type()) {
|
||||||
|
// someone updated their score
|
||||||
|
case Leaderboards_Messages::UpdateUserScore:
|
||||||
|
network_leaderboard_update_score(msg, cached_leaderboards[board_handle - 1], false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// someone updated their score and wants us to share back ours
|
||||||
|
case Leaderboards_Messages::UpdateUserScoreMutual:
|
||||||
|
network_leaderboard_update_score(msg, cached_leaderboards[board_handle - 1], true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// someone is requesting our score on a leaderboard
|
||||||
|
case Leaderboards_Messages::RequestUserScore:
|
||||||
|
network_leaderboard_send_my_score(msg, cached_leaderboards[board_handle - 1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
PRINT_DEBUG("unhandled type %i", (int)msg->leaderboards_messages().type());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
846
dll/steam_user_stats_stats.cpp
Normal file
846
dll/steam_user_stats_stats.cpp
Normal file
@ -0,0 +1,846 @@
|
|||||||
|
/* Copyright (C) 2019 Mr Goldberg
|
||||||
|
This file is part of the Goldberg Emulator
|
||||||
|
|
||||||
|
The Goldberg Emulator is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The Goldberg Emulator is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the Goldberg Emulator; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include "dll/steam_user_stats.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// change stats without sending back to server
|
||||||
|
bool Steam_User_Stats::clear_stats_internal()
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_ENTRY();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
bool notify_server = false;
|
||||||
|
|
||||||
|
for (const auto &stat : settings->getStats()) {
|
||||||
|
std::string stat_name(common_helpers::ascii_to_lowercase(stat.first));
|
||||||
|
|
||||||
|
switch (stat.second.type)
|
||||||
|
{
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_INT: {
|
||||||
|
auto data = stat.second.default_value_int;
|
||||||
|
|
||||||
|
bool needs_disk_write = false;
|
||||||
|
auto it_res = stats_cache_int.find(stat_name);
|
||||||
|
if (stats_cache_int.end() == it_res || it_res->second != data) {
|
||||||
|
needs_disk_write = true;
|
||||||
|
notify_server = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats_cache_int[stat_name] = data;
|
||||||
|
|
||||||
|
if (needs_disk_write) local_storage->store_data(Local_Storage::stats_storage_folder, stat_name, (char *)&data, sizeof(data));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_FLOAT:
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_AVGRATE: {
|
||||||
|
auto data = stat.second.default_value_float;
|
||||||
|
|
||||||
|
bool needs_disk_write = false;
|
||||||
|
auto it_res = stats_cache_float.find(stat_name);
|
||||||
|
if (stats_cache_float.end() == it_res || it_res->second != data) {
|
||||||
|
needs_disk_write = true;
|
||||||
|
notify_server = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats_cache_float[stat_name] = data;
|
||||||
|
|
||||||
|
if (needs_disk_write) local_storage->store_data(Local_Storage::stats_storage_folder, stat_name, (char *)&data, sizeof(data));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: PRINT_DEBUG("unhandled type %i", (int)stat.second.type); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return notify_server;
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_User_Stats::InternalSetResult<int32> Steam_User_Stats::set_stat_internal( const char *pchName, int32 nData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("<int32> '%s' = %i", pchName, nData);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
Steam_User_Stats::InternalSetResult<int32> result{};
|
||||||
|
|
||||||
|
if (!pchName) return result;
|
||||||
|
std::string stat_name(common_helpers::ascii_to_lowercase(pchName));
|
||||||
|
|
||||||
|
const auto &stats_config = settings->getStats();
|
||||||
|
auto stats_data = stats_config.find(stat_name);
|
||||||
|
if (stats_config.end() == stats_data && settings->allow_unknown_stats) {
|
||||||
|
Stat_config cfg{};
|
||||||
|
cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_INT;
|
||||||
|
cfg.default_value_int = 0;
|
||||||
|
stats_data = settings->setStatDefiniton(stat_name, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats_config.end() == stats_data) return result;
|
||||||
|
if (stats_data->second.type != GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return result;
|
||||||
|
|
||||||
|
result.internal_name = stat_name;
|
||||||
|
result.current_val = nData;
|
||||||
|
|
||||||
|
auto cached_stat = stats_cache_int.find(stat_name);
|
||||||
|
if (stats_cache_int.end() != cached_stat) {
|
||||||
|
if (cached_stat->second == nData) {
|
||||||
|
result.success = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto stat_trigger = achievement_stat_trigger.find(stat_name);
|
||||||
|
if (stat_trigger != achievement_stat_trigger.end()) {
|
||||||
|
for (auto &t : stat_trigger->second) {
|
||||||
|
if (t.should_unlock_ach(nData)) {
|
||||||
|
set_achievement_internal(t.name.c_str());
|
||||||
|
}
|
||||||
|
if (settings->stat_achievement_progress_functionality && t.should_indicate_progress(nData)) {
|
||||||
|
bool indicate_progress = true;
|
||||||
|
// appid 1482380 needs that otherwise it will spam progress indications while driving
|
||||||
|
if (settings->save_only_higher_stat_achievement_progress) {
|
||||||
|
try {
|
||||||
|
auto user_ach_it = user_achievements.find(t.name);
|
||||||
|
if (user_achievements.end() != user_ach_it) {
|
||||||
|
auto user_progress_it = user_ach_it->find("progress");
|
||||||
|
if (user_ach_it->end() != user_progress_it) {
|
||||||
|
int32 user_progress = *user_progress_it;
|
||||||
|
if (nData <= user_progress) {
|
||||||
|
indicate_progress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(...){}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indicate_progress) {
|
||||||
|
IndicateAchievementProgress(t.name.c_str(), nData, std::stoi(t.max_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local_storage->store_data(Local_Storage::stats_storage_folder, stat_name, (char* )&nData, sizeof(nData)) == sizeof(nData)) {
|
||||||
|
stats_cache_int[stat_name] = nData;
|
||||||
|
result.success = true;
|
||||||
|
result.notify_server = !settings->disable_sharing_stats_with_gameserver;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_User_Stats::InternalSetResult<std::pair<GameServerStats_Messages::StatInfo::Stat_Type, float>> Steam_User_Stats::set_stat_internal( const char *pchName, float fData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("<float> '%s' = %f", pchName, fData);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
Steam_User_Stats::InternalSetResult<std::pair<GameServerStats_Messages::StatInfo::Stat_Type, float>> result{};
|
||||||
|
|
||||||
|
if (!pchName) return result;
|
||||||
|
std::string stat_name(common_helpers::ascii_to_lowercase(pchName));
|
||||||
|
|
||||||
|
const auto &stats_config = settings->getStats();
|
||||||
|
auto stats_data = stats_config.find(stat_name);
|
||||||
|
if (stats_config.end() == stats_data && settings->allow_unknown_stats) {
|
||||||
|
Stat_config cfg{};
|
||||||
|
cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_FLOAT;
|
||||||
|
cfg.default_value_float = 0;
|
||||||
|
stats_data = settings->setStatDefiniton(stat_name, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats_config.end() == stats_data) return result;
|
||||||
|
if (stats_data->second.type == GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return result;
|
||||||
|
|
||||||
|
result.internal_name = stat_name;
|
||||||
|
result.current_val.first = stats_data->second.type;
|
||||||
|
result.current_val.second = fData;
|
||||||
|
|
||||||
|
auto cached_stat = stats_cache_float.find(stat_name);
|
||||||
|
if (stats_cache_float.end() != cached_stat) {
|
||||||
|
if (cached_stat->second == fData) {
|
||||||
|
result.success = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto stat_trigger = achievement_stat_trigger.find(stat_name);
|
||||||
|
if (stat_trigger != achievement_stat_trigger.end()) {
|
||||||
|
for (auto &t : stat_trigger->second) {
|
||||||
|
if (t.should_unlock_ach(fData)) {
|
||||||
|
set_achievement_internal(t.name.c_str());
|
||||||
|
}
|
||||||
|
if (settings->stat_achievement_progress_functionality && t.should_indicate_progress(fData)) {
|
||||||
|
bool indicate_progress = true;
|
||||||
|
// appid 1482380 needs that otherwise it will spam progress indications while driving
|
||||||
|
if (settings->save_only_higher_stat_achievement_progress) {
|
||||||
|
try {
|
||||||
|
auto user_ach_it = user_achievements.find(t.name);
|
||||||
|
if (user_achievements.end() != user_ach_it) {
|
||||||
|
auto user_progress_it = user_ach_it->find("progress");
|
||||||
|
if (user_ach_it->end() != user_progress_it) {
|
||||||
|
float user_progress = *user_progress_it;
|
||||||
|
if (fData <= user_progress) {
|
||||||
|
indicate_progress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(...){}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indicate_progress) {
|
||||||
|
IndicateAchievementProgress(t.name.c_str(), (uint32)fData, (uint32)std::stof(t.max_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local_storage->store_data(Local_Storage::stats_storage_folder, stat_name, (char* )&fData, sizeof(fData)) == sizeof(fData)) {
|
||||||
|
stats_cache_float[stat_name] = fData;
|
||||||
|
result.success = true;
|
||||||
|
result.notify_server = !settings->disable_sharing_stats_with_gameserver;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_User_Stats::InternalSetResult<std::pair<GameServerStats_Messages::StatInfo::Stat_Type, float>> Steam_User_Stats::update_avg_rate_stat_internal( const char *pchName, float flCountThisSession, double dSessionLength )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%s", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
Steam_User_Stats::InternalSetResult<std::pair<GameServerStats_Messages::StatInfo::Stat_Type, float>> result{};
|
||||||
|
|
||||||
|
if (!pchName) return result;
|
||||||
|
std::string stat_name(common_helpers::ascii_to_lowercase(pchName));
|
||||||
|
|
||||||
|
const auto &stats_config = settings->getStats();
|
||||||
|
auto stats_data = stats_config.find(stat_name);
|
||||||
|
if (stats_config.end() == stats_data && settings->allow_unknown_stats) {
|
||||||
|
Stat_config cfg{};
|
||||||
|
cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_AVGRATE;
|
||||||
|
cfg.default_value_float = 0;
|
||||||
|
stats_data = settings->setStatDefiniton(stat_name, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats_config.end() == stats_data) return result;
|
||||||
|
if (stats_data->second.type == GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return result;
|
||||||
|
|
||||||
|
result.internal_name = stat_name;
|
||||||
|
|
||||||
|
char data[sizeof(float) + sizeof(float) + sizeof(double)];
|
||||||
|
int read_data = local_storage->get_data(Local_Storage::stats_storage_folder, stat_name, (char* )data, sizeof(*data));
|
||||||
|
float oldcount = 0;
|
||||||
|
double oldsessionlength = 0;
|
||||||
|
if (read_data == sizeof(data)) {
|
||||||
|
memcpy(&oldcount, data + sizeof(float), sizeof(oldcount));
|
||||||
|
memcpy(&oldsessionlength, data + sizeof(float) + sizeof(float), sizeof(oldsessionlength));
|
||||||
|
}
|
||||||
|
|
||||||
|
oldcount += flCountThisSession;
|
||||||
|
oldsessionlength += dSessionLength;
|
||||||
|
|
||||||
|
float average = static_cast<float>(oldcount / oldsessionlength);
|
||||||
|
memcpy(data, &average, sizeof(average));
|
||||||
|
memcpy(data + sizeof(float), &oldcount, sizeof(oldcount));
|
||||||
|
memcpy(data + sizeof(float) * 2, &oldsessionlength, sizeof(oldsessionlength));
|
||||||
|
|
||||||
|
result.current_val.first = stats_data->second.type;
|
||||||
|
result.current_val.second = average;
|
||||||
|
|
||||||
|
if (local_storage->store_data(Local_Storage::stats_storage_folder, stat_name, data, sizeof(data)) == sizeof(data)) {
|
||||||
|
stats_cache_float[stat_name] = average;
|
||||||
|
result.success = true;
|
||||||
|
result.notify_server = !settings->disable_sharing_stats_with_gameserver;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_User_Stats::steam_user_stats_network_stats(void *object, Common_Message *msg)
|
||||||
|
{
|
||||||
|
// PRINT_DEBUG_ENTRY();
|
||||||
|
|
||||||
|
auto inst = (Steam_User_Stats *)object;
|
||||||
|
inst->network_callback_stats(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Ask the server to send down this user's data and achievements for this game
|
||||||
|
STEAM_CALL_BACK( UserStatsReceived_t )
|
||||||
|
bool Steam_User_Stats::RequestCurrentStats()
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_ENTRY();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
UserStatsReceived_t data{};
|
||||||
|
data.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
data.m_eResult = k_EResultOK;
|
||||||
|
data.m_steamIDUser = settings->get_local_steam_id();
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Data accessors
|
||||||
|
bool Steam_User_Stats::GetStat( const char *pchName, int32 *pData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("<int32> '%s' %p", pchName, pData);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
std::string stat_name = common_helpers::ascii_to_lowercase(pchName);
|
||||||
|
|
||||||
|
const auto &stats_config = settings->getStats();
|
||||||
|
auto stats_data = stats_config.find(stat_name);
|
||||||
|
if (stats_config.end() == stats_data && settings->allow_unknown_stats) {
|
||||||
|
Stat_config cfg{};
|
||||||
|
cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_INT;
|
||||||
|
cfg.default_value_int = 0;
|
||||||
|
stats_data = settings->setStatDefiniton(stat_name, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats_config.end() == stats_data) return false;
|
||||||
|
if (stats_data->second.type != GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return false;
|
||||||
|
|
||||||
|
auto cached_stat = stats_cache_int.find(stat_name);
|
||||||
|
if (cached_stat != stats_cache_int.end()) {
|
||||||
|
if (pData) *pData = cached_stat->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 output = 0;
|
||||||
|
int read_data = local_storage->get_data(Local_Storage::stats_storage_folder, stat_name, (char* )&output, sizeof(output));
|
||||||
|
if (read_data == sizeof(int32)) {
|
||||||
|
stats_cache_int[stat_name] = output;
|
||||||
|
if (pData) *pData = output;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats_cache_int[stat_name] = stats_data->second.default_value_int;
|
||||||
|
if (pData) *pData = stats_data->second.default_value_int;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Steam_User_Stats::GetStat( const char *pchName, float *pData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("<float> '%s' %p", pchName, pData);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
std::string stat_name = common_helpers::ascii_to_lowercase(pchName);
|
||||||
|
|
||||||
|
const auto &stats_config = settings->getStats();
|
||||||
|
auto stats_data = stats_config.find(stat_name);
|
||||||
|
if (stats_config.end() == stats_data && settings->allow_unknown_stats) {
|
||||||
|
Stat_config cfg{};
|
||||||
|
cfg.type = GameServerStats_Messages::StatInfo::STAT_TYPE_FLOAT;
|
||||||
|
cfg.default_value_float = 0;
|
||||||
|
stats_data = settings->setStatDefiniton(stat_name, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats_config.end() == stats_data) return false;
|
||||||
|
if (stats_data->second.type == GameServerStats_Messages::StatInfo::STAT_TYPE_INT) return false;
|
||||||
|
|
||||||
|
auto cached_stat = stats_cache_float.find(stat_name);
|
||||||
|
if (cached_stat != stats_cache_float.end()) {
|
||||||
|
if (pData) *pData = cached_stat->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float output = 0.0;
|
||||||
|
int read_data = local_storage->get_data(Local_Storage::stats_storage_folder, stat_name, (char* )&output, sizeof(output));
|
||||||
|
if (read_data == sizeof(float)) {
|
||||||
|
stats_cache_float[stat_name] = output;
|
||||||
|
if (pData) *pData = output;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats_cache_float[stat_name] = stats_data->second.default_value_float;
|
||||||
|
if (pData) *pData = stats_data->second.default_value_float;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set / update data
|
||||||
|
bool Steam_User_Stats::SetStat( const char *pchName, int32 nData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("<int32> '%s' = %i", pchName, nData);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
auto ret = set_stat_internal(pchName, nData );
|
||||||
|
if (ret.success && ret.notify_server ) {
|
||||||
|
auto &new_stat = (*pending_server_updates.mutable_user_stats())[ret.internal_name];
|
||||||
|
new_stat.set_stat_type(GameServerStats_Messages::StatInfo::STAT_TYPE_INT);
|
||||||
|
new_stat.set_value_int(ret.current_val);
|
||||||
|
|
||||||
|
if (settings->immediate_gameserver_stats) send_updated_stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Steam_User_Stats::SetStat( const char *pchName, float fData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("<float> '%s' = %f", pchName, fData);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
auto ret = set_stat_internal(pchName, fData);
|
||||||
|
if (ret.success && ret.notify_server) {
|
||||||
|
auto &new_stat = (*pending_server_updates.mutable_user_stats())[ret.internal_name];
|
||||||
|
new_stat.set_stat_type(ret.current_val.first);
|
||||||
|
new_stat.set_value_float(ret.current_val.second);
|
||||||
|
|
||||||
|
if (settings->immediate_gameserver_stats) send_updated_stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Steam_User_Stats::UpdateAvgRateStat( const char *pchName, float flCountThisSession, double dSessionLength )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s'", pchName);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
auto ret = update_avg_rate_stat_internal(pchName, flCountThisSession, dSessionLength);
|
||||||
|
if (ret.success && ret.notify_server) {
|
||||||
|
auto &new_stat = (*pending_server_updates.mutable_user_stats())[ret.internal_name];
|
||||||
|
new_stat.set_stat_type(ret.current_val.first);
|
||||||
|
new_stat.set_value_float(ret.current_val.second);
|
||||||
|
|
||||||
|
if (settings->immediate_gameserver_stats) send_updated_stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Store the current data on the server, will get a callback when set
|
||||||
|
// And one callback for every new achievement
|
||||||
|
//
|
||||||
|
// If the callback has a result of k_EResultInvalidParam, one or more stats
|
||||||
|
// uploaded has been rejected, either because they broke constraints
|
||||||
|
// or were out of date. In this case the server sends back updated values.
|
||||||
|
// The stats should be re-iterated to keep in sync.
|
||||||
|
bool Steam_User_Stats::StoreStats()
|
||||||
|
{
|
||||||
|
// no need to exchange data with gameserver, we already do that in run_callback() and on each stat/ach update (immediate mode)
|
||||||
|
PRINT_DEBUG_ENTRY();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
UserStatsStored_t data{};
|
||||||
|
data.m_eResult = k_EResultOK;
|
||||||
|
data.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.01);
|
||||||
|
|
||||||
|
for (auto &kv : store_stats_trigger) {
|
||||||
|
callbacks->addCBResult(kv.second.k_iCallback, &kv.second, sizeof(kv.second));
|
||||||
|
}
|
||||||
|
store_stats_trigger.clear();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Friends stats
|
||||||
|
|
||||||
|
// downloads stats for the user
|
||||||
|
// returns a UserStatsReceived_t received when completed
|
||||||
|
// if the other user has no stats, UserStatsReceived_t.m_eResult will be set to k_EResultFail
|
||||||
|
// these stats won't be auto-updated; you'll need to call RequestUserStats() again to refresh any data
|
||||||
|
STEAM_CALL_RESULT( UserStatsReceived_t )
|
||||||
|
SteamAPICall_t Steam_User_Stats::RequestUserStats( CSteamID steamIDUser )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu", steamIDUser.ConvertToUint64());
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
// Enable this to allow hot reload achievements status
|
||||||
|
//if (steamIDUser == settings->get_local_steam_id()) {
|
||||||
|
// load_achievements();
|
||||||
|
//}
|
||||||
|
|
||||||
|
UserStatsReceived_t data{};
|
||||||
|
data.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
data.m_eResult = k_EResultOK;
|
||||||
|
data.m_steamIDUser = steamIDUser;
|
||||||
|
// appid 756800 expects both: a callback (global event occurring in the Steam environment),
|
||||||
|
// and a callresult (the specific result of this function call)
|
||||||
|
// otherwise it will lock-up and hang at startup
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// requests stat information for a user, usable after a successful call to RequestUserStats()
|
||||||
|
bool Steam_User_Stats::GetUserStat( CSteamID steamIDUser, const char *pchName, int32 *pData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s' %llu", pchName, steamIDUser.ConvertToUint64());
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
|
||||||
|
if (steamIDUser == settings->get_local_steam_id()) {
|
||||||
|
GetStat(pchName, pData);
|
||||||
|
} else {
|
||||||
|
*pData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Steam_User_Stats::GetUserStat( CSteamID steamIDUser, const char *pchName, float *pData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%s %llu", pchName, steamIDUser.ConvertToUint64());
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pchName) return false;
|
||||||
|
|
||||||
|
if (steamIDUser == settings->get_local_steam_id()) {
|
||||||
|
GetStat(pchName, pData);
|
||||||
|
} else {
|
||||||
|
*pData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reset stats
|
||||||
|
bool Steam_User_Stats::ResetAllStats( bool bAchievementsToo )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("bAchievementsToo = %i", (int)bAchievementsToo);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
clear_stats_internal(); // this will save stats to disk if necessary
|
||||||
|
if (!settings->disable_sharing_stats_with_gameserver) {
|
||||||
|
for (const auto &stat : settings->getStats()) {
|
||||||
|
std::string stat_name(common_helpers::ascii_to_lowercase(stat.first));
|
||||||
|
|
||||||
|
auto &new_stat = (*pending_server_updates.mutable_user_stats())[stat_name];
|
||||||
|
new_stat.set_stat_type(stat.second.type);
|
||||||
|
|
||||||
|
switch (stat.second.type)
|
||||||
|
{
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_INT:
|
||||||
|
new_stat.set_value_int(stat.second.default_value_int);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_AVGRATE:
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_FLOAT:
|
||||||
|
new_stat.set_value_float(stat.second.default_value_float);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: PRINT_DEBUG("unhandled type %i", (int)stat.second.type); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bAchievementsToo) {
|
||||||
|
bool needs_disk_write = false;
|
||||||
|
for (auto &kv : user_achievements.items()) {
|
||||||
|
try {
|
||||||
|
auto &name = kv.key();
|
||||||
|
auto &item = kv.value();
|
||||||
|
// assume "earned" is true in case the json obj exists, but the key is absent
|
||||||
|
if (item.value("earned", true) == true) needs_disk_write = true;
|
||||||
|
|
||||||
|
item["earned"] = false;
|
||||||
|
item["earned_time"] = static_cast<uint32>(0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto defined_ach_it = defined_achievements_find(name);
|
||||||
|
if (defined_achievements.end() != defined_ach_it) {
|
||||||
|
auto defined_progress_it = defined_ach_it->find("progress");
|
||||||
|
if (defined_ach_it->end() != defined_progress_it) { // if the schema had "progress"
|
||||||
|
uint32 val = 0;
|
||||||
|
try {
|
||||||
|
auto defined_min_val = defined_progress_it->value("min_val", std::string("0"));
|
||||||
|
val = std::stoul(defined_min_val);
|
||||||
|
} catch(...){}
|
||||||
|
item["progress"] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(...){}
|
||||||
|
|
||||||
|
// this won't actually trigger a notification, just updates the data
|
||||||
|
overlay->AddAchievementNotification(name, item, false);
|
||||||
|
} catch(const std::exception& e) {
|
||||||
|
PRINT_DEBUG("ERROR: %s", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needs_disk_write) save_achievements();
|
||||||
|
|
||||||
|
if (!settings->disable_sharing_stats_with_gameserver) {
|
||||||
|
for (const auto &item : user_achievements.items()) {
|
||||||
|
auto &new_ach = (*pending_server_updates.mutable_user_achievements())[item.key()];
|
||||||
|
new_ach.set_achieved(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!settings->disable_sharing_stats_with_gameserver && settings->immediate_gameserver_stats) send_updated_stats();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Requests global stats data, which is available for stats marked as "aggregated".
|
||||||
|
// This call is asynchronous, with the results returned in GlobalStatsReceived_t.
|
||||||
|
// nHistoryDays specifies how many days of day-by-day history to retrieve in addition
|
||||||
|
// to the overall totals. The limit is 60.
|
||||||
|
STEAM_CALL_RESULT( GlobalStatsReceived_t )
|
||||||
|
SteamAPICall_t Steam_User_Stats::RequestGlobalStats( int nHistoryDays )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%i", nHistoryDays);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
GlobalStatsReceived_t data{};
|
||||||
|
data.m_nGameID = settings->get_local_game_id().ToUint64();
|
||||||
|
data.m_eResult = k_EResultOK;
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Gets the lifetime totals for an aggregated stat
|
||||||
|
bool Steam_User_Stats::GetGlobalStat( const char *pchStatName, int64 *pData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_TODO();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Steam_User_Stats::GetGlobalStat( const char *pchStatName, double *pData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_TODO();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Gets history for an aggregated stat. pData will be filled with daily values, starting with today.
|
||||||
|
// So when called, pData[0] will be today, pData[1] will be yesterday, and pData[2] will be two days ago,
|
||||||
|
// etc. cubData is the size in bytes of the pubData buffer. Returns the number of
|
||||||
|
// elements actually set.
|
||||||
|
int32 Steam_User_Stats::GetGlobalStatHistory( const char *pchStatName, STEAM_ARRAY_COUNT(cubData) int64 *pData, uint32 cubData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_TODO();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 Steam_User_Stats::GetGlobalStatHistory( const char *pchStatName, STEAM_ARRAY_COUNT(cubData) double *pData, uint32 cubData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG_TODO();
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- steam callbacks
|
||||||
|
|
||||||
|
void Steam_User_Stats::send_updated_stats()
|
||||||
|
{
|
||||||
|
if (pending_server_updates.user_stats().empty() && pending_server_updates.user_achievements().empty()) return;
|
||||||
|
if (settings->disable_sharing_stats_with_gameserver) return;
|
||||||
|
|
||||||
|
auto new_updates_msg = new GameServerStats_Messages::AllStats(pending_server_updates);
|
||||||
|
pending_server_updates.clear_user_stats();
|
||||||
|
pending_server_updates.clear_user_achievements();
|
||||||
|
|
||||||
|
auto gameserverstats_msg = new GameServerStats_Messages();
|
||||||
|
gameserverstats_msg->set_type(GameServerStats_Messages::UpdateUserStatsFromUser);
|
||||||
|
gameserverstats_msg->set_allocated_update_user_stats(new_updates_msg);
|
||||||
|
|
||||||
|
Common_Message msg{};
|
||||||
|
// https://protobuf.dev/reference/cpp/cpp-generated/#string
|
||||||
|
// set_allocated_xxx() takes ownership of the allocated object, no need to delete
|
||||||
|
msg.set_allocated_gameserver_stats_messages(gameserverstats_msg);
|
||||||
|
msg.set_source_id(settings->get_local_steam_id().ConvertToUint64());
|
||||||
|
// here we send to all gameservers on the network because we don't know the server steamid
|
||||||
|
network->sendToAllGameservers(&msg, true);
|
||||||
|
|
||||||
|
PRINT_DEBUG("sent updated stats: %zu stats, %zu achievements",
|
||||||
|
new_updates_msg->user_stats().size(), new_updates_msg->user_achievements().size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- networking callbacks
|
||||||
|
// only triggered when we have a message
|
||||||
|
|
||||||
|
// server wants all stats
|
||||||
|
void Steam_User_Stats::network_stats_initial(Common_Message *msg)
|
||||||
|
{
|
||||||
|
if (!msg->gameserver_stats_messages().has_initial_user_stats()) {
|
||||||
|
PRINT_DEBUG("error empty msg");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 server_steamid = msg->source_id();
|
||||||
|
|
||||||
|
auto all_stats_msg = new GameServerStats_Messages::AllStats();
|
||||||
|
|
||||||
|
// get all stats
|
||||||
|
auto &stats_map = *all_stats_msg->mutable_user_stats();
|
||||||
|
const auto ¤t_stats = settings->getStats();
|
||||||
|
for (const auto &stat : current_stats) {
|
||||||
|
auto &this_stat = stats_map[stat.first];
|
||||||
|
this_stat.set_stat_type(stat.second.type);
|
||||||
|
switch (stat.second.type)
|
||||||
|
{
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_INT: {
|
||||||
|
int32 val = 0;
|
||||||
|
GetStat(stat.first.c_str(), &val);
|
||||||
|
this_stat.set_value_int(val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_AVGRATE: // we set the float value also for avg
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_FLOAT: {
|
||||||
|
float val = 0;
|
||||||
|
GetStat(stat.first.c_str(), &val);
|
||||||
|
this_stat.set_value_float(val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
PRINT_DEBUG("Request_AllUserStats unhandled stat type %i", (int)stat.second.type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all achievements
|
||||||
|
auto &achievements_map = *all_stats_msg->mutable_user_achievements();
|
||||||
|
for (const auto &ach : defined_achievements) {
|
||||||
|
const std::string &name = static_cast<const std::string &>( ach.value("name", std::string()) );
|
||||||
|
auto &this_ach = achievements_map[name];
|
||||||
|
|
||||||
|
// achieved or not
|
||||||
|
bool achieved = false;
|
||||||
|
GetAchievement(name.c_str(), &achieved);
|
||||||
|
this_ach.set_achieved(achieved);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto initial_stats_msg = new GameServerStats_Messages::InitialAllStats();
|
||||||
|
// send back same api call id
|
||||||
|
initial_stats_msg->set_steam_api_call(msg->gameserver_stats_messages().initial_user_stats().steam_api_call());
|
||||||
|
initial_stats_msg->set_allocated_all_data(all_stats_msg);
|
||||||
|
|
||||||
|
auto gameserverstats_msg = new GameServerStats_Messages();
|
||||||
|
gameserverstats_msg->set_type(GameServerStats_Messages::Response_AllUserStats);
|
||||||
|
gameserverstats_msg->set_allocated_initial_user_stats(initial_stats_msg);
|
||||||
|
|
||||||
|
Common_Message new_msg{};
|
||||||
|
// https://protobuf.dev/reference/cpp/cpp-generated/#string
|
||||||
|
// set_allocated_xxx() takes ownership of the allocated object, no need to delete
|
||||||
|
new_msg.set_allocated_gameserver_stats_messages(gameserverstats_msg);
|
||||||
|
new_msg.set_source_id(settings->get_local_steam_id().ConvertToUint64());
|
||||||
|
new_msg.set_dest_id(server_steamid);
|
||||||
|
network->sendTo(&new_msg, true);
|
||||||
|
|
||||||
|
PRINT_DEBUG("server requested all stats, sent %zu stats, %zu achievements",
|
||||||
|
initial_stats_msg->all_data().user_stats().size(), initial_stats_msg->all_data().user_achievements().size()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// server has updated/new stats
|
||||||
|
void Steam_User_Stats::network_stats_updated(Common_Message *msg)
|
||||||
|
{
|
||||||
|
if (!msg->gameserver_stats_messages().has_update_user_stats()) {
|
||||||
|
PRINT_DEBUG("error empty msg");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &new_user_data = msg->gameserver_stats_messages().update_user_stats();
|
||||||
|
|
||||||
|
// update our stats
|
||||||
|
for (auto &new_stat : new_user_data.user_stats()) {
|
||||||
|
switch (new_stat.second.stat_type())
|
||||||
|
{
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_INT: {
|
||||||
|
set_stat_internal(new_stat.first.c_str(), new_stat.second.value_int());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_AVGRATE:
|
||||||
|
case GameServerStats_Messages::StatInfo::STAT_TYPE_FLOAT: {
|
||||||
|
set_stat_internal(new_stat.first.c_str(), new_stat.second.value_float());
|
||||||
|
// non-INT values could have avg values
|
||||||
|
if (new_stat.second.has_value_avg()) {
|
||||||
|
auto &avg_val = new_stat.second.value_avg();
|
||||||
|
update_avg_rate_stat_internal(new_stat.first.c_str(), avg_val.count_this_session(), avg_val.session_length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
PRINT_DEBUG("UpdateUserStats unhandled stat type %i", (int)new_stat.second.stat_type());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update achievements
|
||||||
|
for (auto &new_ach : new_user_data.user_achievements()) {
|
||||||
|
if (new_ach.second.achieved()) {
|
||||||
|
set_achievement_internal(new_ach.first.c_str());
|
||||||
|
} else {
|
||||||
|
clear_achievement_internal(new_ach.first.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_DEBUG("server sent updated user stats, %zu stats, %zu achievements",
|
||||||
|
new_user_data.user_stats().size(), new_user_data.user_achievements().size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_User_Stats::network_callback_stats(Common_Message *msg)
|
||||||
|
{
|
||||||
|
// network->sendToAll() sends to current user also
|
||||||
|
if (msg->source_id() == settings->get_local_steam_id().ConvertToUint64()) return;
|
||||||
|
|
||||||
|
uint64 server_steamid = msg->source_id();
|
||||||
|
|
||||||
|
switch (msg->gameserver_stats_messages().type())
|
||||||
|
{
|
||||||
|
// server wants all stats
|
||||||
|
case GameServerStats_Messages::Request_AllUserStats:
|
||||||
|
network_stats_initial(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// server has updated/new stats
|
||||||
|
case GameServerStats_Messages::UpdateUserStatsFromServer:
|
||||||
|
network_stats_updated(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// a user has updated/new stats
|
||||||
|
case GameServerStats_Messages::UpdateUserStatsFromUser:
|
||||||
|
// nothing
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
PRINT_DEBUG("unhandled type %i", (int)msg->gameserver_stats_messages().type());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
@ -81,11 +81,11 @@ bool Steam_Utils::GetImageSize( int iImage, uint32 *pnWidth, uint32 *pnHeight )
|
|||||||
|
|
||||||
if (!iImage || !pnWidth || !pnHeight) return false;
|
if (!iImage || !pnWidth || !pnHeight) return false;
|
||||||
|
|
||||||
auto image = settings->images.find(iImage);
|
auto image_info = settings->get_image(iImage);
|
||||||
if (settings->images.end() == image) return false;
|
if (!image_info) return false;
|
||||||
|
|
||||||
*pnWidth = image->second.width;
|
*pnWidth = image_info->width;
|
||||||
*pnHeight = image->second.height;
|
*pnHeight = image_info->height;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,10 +99,10 @@ bool Steam_Utils::GetImageRGBA( int iImage, uint8 *pubDest, int nDestBufferSize
|
|||||||
|
|
||||||
if (!iImage || !pubDest || nDestBufferSize <= 0) return false;
|
if (!iImage || !pubDest || nDestBufferSize <= 0) return false;
|
||||||
|
|
||||||
auto image = settings->images.find(iImage);
|
auto image_info = settings->get_image(iImage);
|
||||||
if (settings->images.end() == image) return false;
|
if (!image_info) return false;
|
||||||
|
|
||||||
image->second.data.copy((char *)pubDest, nDestBufferSize);
|
image_info->data.copy((char *)pubDest, nDestBufferSize);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
generate_credits.bat
Normal file
26
generate_credits.bat
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
set "CREDITS_FILE=CREDITS.md"
|
||||||
|
|
||||||
|
if exist "%CREDITS_FILE%" (
|
||||||
|
del /f /s /q "%CREDITS_FILE%"
|
||||||
|
)
|
||||||
|
|
||||||
|
set "GLOB=third-party libs tools\steamclient_loader"
|
||||||
|
set "FILTER=SOURCE.txt"
|
||||||
|
|
||||||
|
echo:# Many thanks for these sources>> "%CREDITS_FILE%"
|
||||||
|
|
||||||
|
for %%A in (%GLOB%) do (
|
||||||
|
powershell -Command "Get-ChildItem -LiteralPath \"%%~A\" -Filter \"%FILTER%\" -File -Recurse | foreach { $parent = Split-Path -Path $_.FullName -Parent; $relative = (Resolve-Path -Path $parent -Relative).replace(\".\\\",\"\"); Write-Output \"- ^[$^($relative^)^]^(#$^($relative^)^)\"; }">> "%CREDITS_FILE%"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.>> "%CREDITS_FILE%"
|
||||||
|
|
||||||
|
for %%B in (%GLOB%) do (
|
||||||
|
powershell -Command "Get-ChildItem -LiteralPath \"%%~B\" -Filter \"%FILTER%\" -File -Recurse | foreach { $parent = Split-Path -Path $_.FullName -Parent; $relative = (Resolve-Path -Path $parent -Relative).replace(\".\\\",\"\"); Write-Output \"### $^($relative^)\"; Write-Output \"\"; Get-Content -LiteralPath $_.FullName -Raw -Encoding utf8; }">> "%CREDITS_FILE%"
|
||||||
|
)
|
||||||
|
|
||||||
|
endlocal
|
@ -133,28 +133,6 @@ void common_helpers::write(std::ofstream &file, std::string_view data)
|
|||||||
file << data << std::endl;
|
file << data << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring common_helpers::str_to_w(std::string_view str)
|
|
||||||
{
|
|
||||||
if (str.empty()) return std::wstring();
|
|
||||||
auto cvt_state = std::mbstate_t();
|
|
||||||
const char* src = &str[0];
|
|
||||||
size_t conversion_bytes = std::mbsrtowcs(nullptr, &src, 0, &cvt_state);
|
|
||||||
std::wstring res(conversion_bytes + 1, L'\0');
|
|
||||||
std::mbsrtowcs(&res[0], &src, res.size(), &cvt_state);
|
|
||||||
return res.substr(0, conversion_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string common_helpers::wstr_to_a(std::wstring_view wstr)
|
|
||||||
{
|
|
||||||
if (wstr.empty()) return std::string();
|
|
||||||
auto cvt_state = std::mbstate_t();
|
|
||||||
const wchar_t* src = &wstr[0];
|
|
||||||
size_t conversion_bytes = std::wcsrtombs(nullptr, &src, 0, &cvt_state);
|
|
||||||
std::string res(conversion_bytes + 1, '\0');
|
|
||||||
std::wcsrtombs(&res[0], &src, res.size(), &cvt_state);
|
|
||||||
return res.substr(0, conversion_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool common_helpers::starts_with_i(std::string_view target, std::string_view query)
|
bool common_helpers::starts_with_i(std::string_view target, std::string_view query)
|
||||||
{
|
{
|
||||||
if (target.size() < query.size()) {
|
if (target.size() < query.size()) {
|
||||||
@ -499,3 +477,31 @@ std::string common_helpers::to_str(std::wstring_view wstr)
|
|||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string common_helpers::str_replace_all(std::string_view source, std::string_view substr, std::string_view replace)
|
||||||
|
{
|
||||||
|
if (source.empty() || substr.empty()) return std::string(source);
|
||||||
|
|
||||||
|
std::string out{};
|
||||||
|
out.reserve(source.size() / 4); // out could be bigger or smaller than source, start small
|
||||||
|
|
||||||
|
size_t start_offset = 0;
|
||||||
|
auto f_idx = source.find(substr);
|
||||||
|
while (std::string::npos != f_idx) {
|
||||||
|
// copy the chars before the match
|
||||||
|
auto chars_count_until_match = f_idx - start_offset;
|
||||||
|
out.append(source, start_offset, chars_count_until_match);
|
||||||
|
// copy the replace str
|
||||||
|
out.append(replace);
|
||||||
|
|
||||||
|
// adjust the start offset to point at the char after this match
|
||||||
|
start_offset = f_idx + substr.size();
|
||||||
|
// search for next match
|
||||||
|
f_idx = source.find(substr, start_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy last remaining part
|
||||||
|
out.append(source, start_offset, std::string::npos);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
@ -110,4 +110,6 @@ std::string get_utc_time();
|
|||||||
std::wstring to_wstr(std::string_view str);
|
std::wstring to_wstr(std::string_view str);
|
||||||
std::string to_str(std::wstring_view wstr);
|
std::string to_str(std::wstring_view wstr);
|
||||||
|
|
||||||
|
std::string str_replace_all(std::string_view source, std::string_view substr, std::string_view replace);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
# Copyright (c) Microsoft Corporation
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
# MIT License
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
@ -1,3 +1,9 @@
|
|||||||
|
============================================================================ INFO
|
||||||
|
https://github.com/microsoft/Detours
|
||||||
|
|
||||||
|
VERSION: https://github.com/microsoft/Detours/tree/4b8c659f549b0ab21cf649377c7a84eb708f5e68
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
Copyright (c) Microsoft Corporation.
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
MIT License
|
MIT License
|
@ -1395,6 +1395,12 @@ PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget,
|
|||||||
return pbNewlyAllocated;
|
return pbNewlyAllocated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode,
|
||||||
|
_In_ PBYTE pbAddress)
|
||||||
|
{
|
||||||
|
return detour_is_imported(pbCode, pbAddress);
|
||||||
|
}
|
||||||
|
|
||||||
static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget)
|
static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget)
|
||||||
{
|
{
|
||||||
// We have to place trampolines within +/- 2GB of target.
|
// We have to place trampolines within +/- 2GB of target.
|
||||||
@ -1437,7 +1443,8 @@ static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget)
|
|||||||
// We need to allocate a new region.
|
// We need to allocate a new region.
|
||||||
|
|
||||||
// Round pbTarget down to 64KB block.
|
// Round pbTarget down to 64KB block.
|
||||||
pbTarget = pbTarget - (PtrToUlong(pbTarget) & 0xffff);
|
// /RTCc RuntimeChecks breaks PtrToUlong.
|
||||||
|
pbTarget = pbTarget - (ULONG)((ULONG_PTR)pbTarget & 0xffff);
|
||||||
|
|
||||||
PVOID pbNewlyAllocated =
|
PVOID pbNewlyAllocated =
|
||||||
detour_alloc_trampoline_allocate_new(pbTarget, pLo, pHi);
|
detour_alloc_trampoline_allocate_new(pbTarget, pLo, pHi);
|
||||||
@ -2098,6 +2105,12 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
|
|||||||
delete o;
|
delete o;
|
||||||
o = NULL;
|
o = NULL;
|
||||||
}
|
}
|
||||||
|
if (ppRealDetour != NULL) {
|
||||||
|
*ppRealDetour = NULL;
|
||||||
|
}
|
||||||
|
if (ppRealTarget != NULL) {
|
||||||
|
*ppRealTarget = NULL;
|
||||||
|
}
|
||||||
s_ppPendingError = ppPointer;
|
s_ppPendingError = ppPointer;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#define __try
|
#define __try
|
||||||
#define __except(x) if (0)
|
#define __except(x) if (0)
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
#include <intsafe.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// From winerror.h, as this error isn't found in some SDKs:
|
// From winerror.h, as this error isn't found in some SDKs:
|
||||||
@ -382,6 +383,10 @@ extern const GUID DETOUR_EXE_HELPER_GUID;
|
|||||||
#define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr!
|
#define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr!
|
||||||
typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE;
|
typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE;
|
||||||
|
|
||||||
|
#ifndef DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS
|
||||||
|
#define DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS 32
|
||||||
|
#endif // !DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////// Binary Structures.
|
/////////////////////////////////////////////////////////// Binary Structures.
|
||||||
//
|
//
|
||||||
#pragma pack(push, 8)
|
#pragma pack(push, 8)
|
||||||
@ -453,9 +458,9 @@ typedef struct _DETOUR_EXE_RESTORE
|
|||||||
#endif
|
#endif
|
||||||
#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this
|
#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this
|
||||||
BYTE raw[sizeof(IMAGE_NT_HEADERS64) +
|
BYTE raw[sizeof(IMAGE_NT_HEADERS64) +
|
||||||
sizeof(IMAGE_SECTION_HEADER) * 32];
|
sizeof(IMAGE_SECTION_HEADER) * DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS];
|
||||||
#else
|
#else
|
||||||
BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * 32];
|
BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS];
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
DETOUR_CLR_HEADER clr;
|
DETOUR_CLR_HEADER clr;
|
||||||
@ -590,6 +595,8 @@ BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule,
|
|||||||
_In_ BOOL fLimitReferencesToModule);
|
_In_ BOOL fLimitReferencesToModule);
|
||||||
PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget,
|
PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget,
|
||||||
_Out_ PDWORD pcbAllocatedSize);
|
_Out_ PDWORD pcbAllocatedSize);
|
||||||
|
BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode,
|
||||||
|
_In_ PBYTE pbAddress);
|
||||||
|
|
||||||
///////////////////////////////////////////////////// Loaded Binary Functions.
|
///////////////////////////////////////////////////// Loaded Binary Functions.
|
||||||
//
|
//
|
||||||
@ -951,10 +958,10 @@ typedef DWORD (NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions);
|
|||||||
typedef DWORD (NTAPI *PF_SymGetOptions)(VOID);
|
typedef DWORD (NTAPI *PF_SymGetOptions)(VOID);
|
||||||
typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess,
|
typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess,
|
||||||
_In_opt_ HANDLE hFile,
|
_In_opt_ HANDLE hFile,
|
||||||
_In_ LPSTR ImageName,
|
_In_opt_ LPSTR ImageName,
|
||||||
_In_opt_ LPSTR ModuleName,
|
_In_opt_ LPSTR ModuleName,
|
||||||
_In_ DWORD64 BaseOfDll,
|
_In_ DWORD64 BaseOfDll,
|
||||||
_In_opt_ DWORD SizeOfDll);
|
_In_ DWORD SizeOfDll);
|
||||||
typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess,
|
typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess,
|
||||||
_In_ DWORD64 qwAddr,
|
_In_ DWORD64 qwAddr,
|
||||||
_Out_ PIMAGEHLP_MODULE64 ModuleInfo);
|
_Out_ PIMAGEHLP_MODULE64 ModuleInfo);
|
||||||
|
@ -279,7 +279,7 @@ class CDetourDis
|
|||||||
PBYTE CopyVex2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
|
PBYTE CopyVex2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
|
||||||
PBYTE CopyVex3(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
|
PBYTE CopyVex3(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
|
||||||
PBYTE CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc);
|
PBYTE CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc);
|
||||||
PBYTE CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p);
|
PBYTE CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p, BYTE fp16 = 0);
|
||||||
PBYTE CopyEvex(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
|
PBYTE CopyEvex(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
|
||||||
PBYTE CopyXop(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
|
PBYTE CopyXop(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
|
||||||
|
|
||||||
@ -745,7 +745,7 @@ PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
|
|||||||
return pbOut;
|
return pbOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
PBYTE CDetourDis::CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p)
|
PBYTE CDetourDis::CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p, BYTE fp16)
|
||||||
// m is first instead of last in the hopes of pbDst/pbSrc being
|
// m is first instead of last in the hopes of pbDst/pbSrc being
|
||||||
// passed along efficiently in the registers they were already in.
|
// passed along efficiently in the registers they were already in.
|
||||||
{
|
{
|
||||||
@ -762,10 +762,13 @@ PBYTE CDetourDis::CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p)
|
|||||||
|
|
||||||
REFCOPYENTRY pEntry;
|
REFCOPYENTRY pEntry;
|
||||||
|
|
||||||
switch (m) {
|
// see https://software.intel.com/content/www/us/en/develop/download/intel-avx512-fp16-architecture-specification.html
|
||||||
|
switch (m | fp16) {
|
||||||
default: return Invalid(&ceInvalid, pbDst, pbSrc);
|
default: return Invalid(&ceInvalid, pbDst, pbSrc);
|
||||||
case 1: pEntry = &s_rceCopyTable0F[pbSrc[0]];
|
case 1: pEntry = &s_rceCopyTable0F[pbSrc[0]];
|
||||||
return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
|
return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
|
||||||
|
case 5: // fallthrough
|
||||||
|
case 6: // fallthrough
|
||||||
case 2: return CopyBytes(&ceF38, pbDst, pbSrc);
|
case 2: return CopyBytes(&ceF38, pbDst, pbSrc);
|
||||||
case 3: return CopyBytes(&ceF3A, pbDst, pbSrc);
|
case 3: return CopyBytes(&ceF3A, pbDst, pbSrc);
|
||||||
}
|
}
|
||||||
@ -859,7 +862,9 @@ PBYTE CDetourDis::CopyEvex(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
|
|||||||
|
|
||||||
static const COPYENTRY ceInvalid = /* 62 */ ENTRY_Invalid;
|
static const COPYENTRY ceInvalid = /* 62 */ ENTRY_Invalid;
|
||||||
|
|
||||||
if ((p0 & 0x0C) != 0)
|
// This could also be handled by default in CopyVexEvexCommon
|
||||||
|
// if 4u changed to 4|8.
|
||||||
|
if (p0 & 8u)
|
||||||
return Invalid(&ceInvalid, pbDst, pbSrc);
|
return Invalid(&ceInvalid, pbDst, pbSrc);
|
||||||
|
|
||||||
BYTE const p1 = pbSrc[2];
|
BYTE const p1 = pbSrc[2];
|
||||||
@ -876,7 +881,7 @@ PBYTE CDetourDis::CopyEvex(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
|
|||||||
m_bRaxOverride |= !!(p1 & 0x80); // w
|
m_bRaxOverride |= !!(p1 & 0x80); // w
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return CopyVexEvexCommon(p0 & 3u, pbDst + 4, pbSrc + 4, p1 & 3u);
|
return CopyVexEvexCommon(p0 & 3u, pbDst + 4, pbSrc + 4, p1 & 3u, p0 & 4u);
|
||||||
}
|
}
|
||||||
|
|
||||||
PBYTE CDetourDis::CopyXop(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
|
PBYTE CDetourDis::CopyXop(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
|
||||||
|
27
libs/fifo_map/SOURCE.txt
Normal file
27
libs/fifo_map/SOURCE.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
============================================================================ INFO
|
||||||
|
https://github.com/nlohmann/fifo_map
|
||||||
|
|
||||||
|
VERSION: https://github.com/nlohmann/fifo_map/tree/d732aaf9a315415ae8fd7eb11e3a4c1f80e42a48
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2015-2017 Niels Lohmann
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
26
libs/gamepad/SOURCE.txt
Normal file
26
libs/gamepad/SOURCE.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
============================================================================ INFO
|
||||||
|
https://github.com/mtwilliams/libgamepad
|
||||||
|
|
||||||
|
VERSION: ????
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
|
Copyright (c) 2014 Michael Williams
|
||||||
|
Copyright (c) 2010-2011 Sean Middleditch
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
@ -1,6 +1,12 @@
|
|||||||
MIT License
|
============================================================================ INFO
|
||||||
|
https://github.com/ocornut/imgui
|
||||||
|
|
||||||
Copyright (c) 2015-2017 Niels Lohmann
|
VERSION: ????
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014-2024 Omar Cornut
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
@ -1,3 +1,9 @@
|
|||||||
|
============================================================================ INFO
|
||||||
|
https://github.com/nlohmann/json
|
||||||
|
|
||||||
|
VERSION: https://github.com/nlohmann/json/releases/tag/v3.11.3
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2013-2022 Niels Lohmann
|
Copyright (c) 2013-2022 Niels Lohmann
|
@ -1 +1,7 @@
|
|||||||
|
============================================================================ INFO
|
||||||
https://github.com/vog/sha1
|
https://github.com/vog/sha1
|
||||||
|
|
||||||
|
VERSION: https://github.com/vog/sha1/tree/3f8a4aa032d144309d00dbfe972906a49b3631b9
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
|
PUBLIC DOMAIN
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
============================================================================ INFO
|
||||||
|
https://github.com/brofield/simpleini
|
||||||
|
|
||||||
|
VERSION: https://github.com/brofield/simpleini/releases/tag/v4.22
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2006-2022 Brodie Thiesfield
|
Copyright (c) 2006-2022 Brodie Thiesfield
|
@ -1,3 +1,9 @@
|
|||||||
|
============================================================================ INFO
|
||||||
|
https://github.com/nothings/stb
|
||||||
|
|
||||||
|
VERSION: https://github.com/nothings/stb/tree/f75e8d1cad7d90d72ef7a4661f1b994ef78b4e31
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
This software is available under 2 licenses -- choose whichever you prefer.
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
ALTERNATIVE A - MIT License
|
ALTERNATIVE A - MIT License
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
10572
libs/stb/stb_image_resize2.h
Normal file
10572
libs/stb/stb_image_resize2.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
/* stb_image_write - v1.15 - public domain - http://nothings.org/stb
|
/* stb_image_write - v1.16 - public domain - http://nothings.org/stb
|
||||||
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
|
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
|
||||||
no warranty implied; use at your own risk
|
no warranty implied; use at your own risk
|
||||||
|
|
||||||
@ -140,6 +140,7 @@ CREDITS:
|
|||||||
Ivan Tikhonov
|
Ivan Tikhonov
|
||||||
github:ignotion
|
github:ignotion
|
||||||
Adam Schackart
|
Adam Schackart
|
||||||
|
Andrew Kensler
|
||||||
|
|
||||||
LICENSE
|
LICENSE
|
||||||
|
|
||||||
@ -166,9 +167,9 @@ LICENSE
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations
|
#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations
|
||||||
extern int stbi_write_tga_with_rle;
|
STBIWDEF int stbi_write_tga_with_rle;
|
||||||
extern int stbi_write_png_compression_level;
|
STBIWDEF int stbi_write_png_compression_level;
|
||||||
extern int stbi_write_force_png_filter;
|
STBIWDEF int stbi_write_force_png_filter;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STBI_WRITE_NO_STDIO
|
#ifndef STBI_WRITE_NO_STDIO
|
||||||
@ -178,7 +179,7 @@ STBIWDEF int stbi_write_tga(char const* filename, int w, int h, int comp, const
|
|||||||
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
|
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
|
||||||
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
|
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
|
||||||
|
|
||||||
#ifdef STBI_WINDOWS_UTF8
|
#ifdef STBIW_WINDOWS_UTF8
|
||||||
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
|
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -285,7 +286,7 @@ static void stbi__stdio_write(void* context, void* data, int size)
|
|||||||
fwrite(data,1,size,(FILE*) context);
|
fwrite(data,1,size,(FILE*) context);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
|
#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define STBIW_EXTERN extern "C"
|
#define STBIW_EXTERN extern "C"
|
||||||
#else
|
#else
|
||||||
@ -303,16 +304,16 @@ STBIWDEF int stbiw_convert_wchar_to_utf8(char* buffer, size_t bufferlen, const w
|
|||||||
static FILE *stbiw__fopen(char const *filename, char const *mode)
|
static FILE *stbiw__fopen(char const *filename, char const *mode)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
|
#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
|
||||||
wchar_t wMode[64];
|
wchar_t wMode[64];
|
||||||
wchar_t wFilename[1024];
|
wchar_t wFilename[1024];
|
||||||
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
|
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
|
if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#if _MSC_VER >= 1400
|
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
if (0 != _wfopen_s(&f, wFilename, wMode))
|
if (0 != _wfopen_s(&f, wFilename, wMode))
|
||||||
f = 0;
|
f = 0;
|
||||||
#else
|
#else
|
||||||
@ -397,7 +398,7 @@ static void stbiw__putc(stbi__write_context* s, unsigned char c)
|
|||||||
|
|
||||||
static void stbiw__write1(stbi__write_context *s, unsigned char a)
|
static void stbiw__write1(stbi__write_context *s, unsigned char a)
|
||||||
{
|
{
|
||||||
if (s->buf_used + 1 > sizeof(s->buffer))
|
if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
|
||||||
stbiw__write_flush(s);
|
stbiw__write_flush(s);
|
||||||
s->buffer[s->buf_used++] = a;
|
s->buffer[s->buf_used++] = a;
|
||||||
}
|
}
|
||||||
@ -405,7 +406,7 @@ static void stbiw__write1(stbi__write_context* s, unsigned char a)
|
|||||||
static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
|
static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
if (s->buf_used + 3 > sizeof(s->buffer))
|
if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
|
||||||
stbiw__write_flush(s);
|
stbiw__write_flush(s);
|
||||||
n = s->buf_used;
|
n = s->buf_used;
|
||||||
s->buf_used = n+3;
|
s->buf_used = n+3;
|
||||||
@ -460,8 +461,7 @@ static void stbiw__write_pixels(stbi__write_context* s, int rgb_dir, int vdir, i
|
|||||||
|
|
||||||
if (vdir < 0) {
|
if (vdir < 0) {
|
||||||
j_end = -1; j = y-1;
|
j_end = -1; j = y-1;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
j_end = y; j = 0;
|
j_end = y; j = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,8 +479,7 @@ static int stbiw__outfile(stbi__write_context* s, int rgb_dir, int vdir, int x,
|
|||||||
{
|
{
|
||||||
if (y < 0 || x < 0) {
|
if (y < 0 || x < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
va_list v;
|
va_list v;
|
||||||
va_start(v, fmt);
|
va_start(v, fmt);
|
||||||
stbiw__writefv(s, fmt, v);
|
stbiw__writefv(s, fmt, v);
|
||||||
@ -492,11 +491,22 @@ static int stbiw__outfile(stbi__write_context* s, int rgb_dir, int vdir, int x,
|
|||||||
|
|
||||||
static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
|
static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
|
||||||
{
|
{
|
||||||
|
if (comp != 4) {
|
||||||
|
// write RGB bitmap
|
||||||
int pad = (-x*3) & 3;
|
int pad = (-x*3) & 3;
|
||||||
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
|
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
|
||||||
"11 4 22 4" "4 44 22 444444",
|
"11 4 22 4" "4 44 22 444444",
|
||||||
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
|
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
|
||||||
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
|
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
|
||||||
|
} else {
|
||||||
|
// RGBA bitmaps need a v4 header
|
||||||
|
// use BI_BITFIELDS mode with 32bpp and alpha mask
|
||||||
|
// (straight BI_RGB with alpha mask doesn't work in most readers)
|
||||||
|
return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
|
||||||
|
"11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
|
||||||
|
'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header
|
||||||
|
108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||||
@ -514,8 +524,7 @@ STBIWDEF int stbi_write_bmp(char const* filename, int x, int y, int comp, const
|
|||||||
int r = stbi_write_bmp_core(&s, x, y, comp, data);
|
int r = stbi_write_bmp_core(&s, x, y, comp, data);
|
||||||
stbi__end_write_file(&s);
|
stbi__end_write_file(&s);
|
||||||
return r;
|
return r;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif //!STBI_WRITE_NO_STDIO
|
#endif //!STBI_WRITE_NO_STDIO
|
||||||
@ -532,8 +541,7 @@ static int stbi_write_tga_core(stbi__write_context* s, int x, int y, int comp, v
|
|||||||
if (!stbi_write_tga_with_rle) {
|
if (!stbi_write_tga_with_rle) {
|
||||||
return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
|
return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
|
||||||
"111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
|
"111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
int i,j,k;
|
int i,j,k;
|
||||||
int jend, jdir;
|
int jend, jdir;
|
||||||
|
|
||||||
@ -543,8 +551,7 @@ static int stbi_write_tga_core(stbi__write_context* s, int x, int y, int comp, v
|
|||||||
j = 0;
|
j = 0;
|
||||||
jend = y;
|
jend = y;
|
||||||
jdir = 1;
|
jdir = 1;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
j = y-1;
|
j = y-1;
|
||||||
jend = -1;
|
jend = -1;
|
||||||
jdir = -1;
|
jdir = -1;
|
||||||
@ -567,19 +574,16 @@ static int stbi_write_tga_core(stbi__write_context* s, int x, int y, int comp, v
|
|||||||
if (memcmp(prev, row + k * comp, comp)) {
|
if (memcmp(prev, row + k * comp, comp)) {
|
||||||
prev += comp;
|
prev += comp;
|
||||||
++len;
|
++len;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
--len;
|
--len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for (k = i + 2; k < x && len < 128; ++k) {
|
for (k = i + 2; k < x && len < 128; ++k) {
|
||||||
if (!memcmp(begin, row + k * comp, comp)) {
|
if (!memcmp(begin, row + k * comp, comp)) {
|
||||||
++len;
|
++len;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -592,8 +596,7 @@ static int stbi_write_tga_core(stbi__write_context* s, int x, int y, int comp, v
|
|||||||
for (k = 0; k < len; ++k) {
|
for (k = 0; k < len; ++k) {
|
||||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
|
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
unsigned char header = STBIW_UCHAR(len - 129);
|
unsigned char header = STBIW_UCHAR(len - 129);
|
||||||
stbiw__write1(s, header);
|
stbiw__write1(s, header);
|
||||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
|
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
|
||||||
@ -620,8 +623,7 @@ STBIWDEF int stbi_write_tga(char const* filename, int x, int y, int comp, const
|
|||||||
int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
|
int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
|
||||||
stbi__end_write_file(&s);
|
stbi__end_write_file(&s);
|
||||||
return r;
|
return r;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -632,6 +634,8 @@ STBIWDEF int stbi_write_tga(char const* filename, int x, int y, int comp, const
|
|||||||
|
|
||||||
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
|
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
|
#ifndef STBI_WRITE_NO_STDIO
|
||||||
|
|
||||||
static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
|
static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
|
||||||
{
|
{
|
||||||
int exponent;
|
int exponent;
|
||||||
@ -639,8 +643,7 @@ static void stbiw__linear_to_rgbe(unsigned char* rgbe, float* linear)
|
|||||||
|
|
||||||
if (maxcomp < 1e-32f) {
|
if (maxcomp < 1e-32f) {
|
||||||
rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
|
rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
|
float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
|
||||||
|
|
||||||
rgbe[0] = (unsigned char)(linear[0] * normalize);
|
rgbe[0] = (unsigned char)(linear[0] * normalize);
|
||||||
@ -692,8 +695,7 @@ static void stbiw__write_hdr_scanline(stbi__write_context* s, int width, int nco
|
|||||||
stbiw__linear_to_rgbe(rgbe, linear);
|
stbiw__linear_to_rgbe(rgbe, linear);
|
||||||
s->func(s->context, rgbe, 4);
|
s->func(s->context, rgbe, 4);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
int c,r;
|
int c,r;
|
||||||
/* encode into scratch buffer */
|
/* encode into scratch buffer */
|
||||||
for (x=0; x < width; x++) {
|
for (x=0; x < width; x++) {
|
||||||
@ -768,7 +770,7 @@ static int stbi_write_hdr_core(stbi__write_context* s, int x, int y, int comp, f
|
|||||||
char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
|
char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
|
||||||
s->func(s->context, header, sizeof(header)-1);
|
s->func(s->context, header, sizeof(header)-1);
|
||||||
|
|
||||||
#ifdef __STDC_WANT_SECURE_LIB__
|
#ifdef __STDC_LIB_EXT1__
|
||||||
len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
||||||
#else
|
#else
|
||||||
len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
||||||
@ -789,7 +791,6 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func* func, void* context, int x,
|
|||||||
return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef STBI_WRITE_NO_STDIO
|
|
||||||
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
|
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
|
||||||
{
|
{
|
||||||
stbi__write_context s = { 0 };
|
stbi__write_context s = { 0 };
|
||||||
@ -797,8 +798,7 @@ STBIWDEF int stbi_write_hdr(char const* filename, int x, int y, int comp, const
|
|||||||
int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
||||||
stbi__end_write_file(&s);
|
stbi__end_write_file(&s);
|
||||||
return r;
|
return r;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif // STBI_WRITE_NO_STDIO
|
#endif // STBI_WRITE_NO_STDIO
|
||||||
@ -964,8 +964,7 @@ STBIWDEF unsigned char* stbi_zlib_compress(unsigned char* data, int data_len, in
|
|||||||
stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
|
stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
|
||||||
if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
|
if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
|
||||||
i += best;
|
i += best;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
stbiw__zlib_huffb(data[i]);
|
stbiw__zlib_huffb(data[i]);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@ -982,6 +981,23 @@ STBIWDEF unsigned char* stbi_zlib_compress(unsigned char* data, int data_len, in
|
|||||||
(void) stbiw__sbfree(hash_table[i]);
|
(void) stbiw__sbfree(hash_table[i]);
|
||||||
STBIW_FREE(hash_table);
|
STBIW_FREE(hash_table);
|
||||||
|
|
||||||
|
// store uncompressed instead if compression was worse
|
||||||
|
if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
|
||||||
|
stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1
|
||||||
|
for (j = 0; j < data_len;) {
|
||||||
|
int blocklen = data_len - j;
|
||||||
|
if (blocklen > 32767) blocklen = 32767;
|
||||||
|
stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression
|
||||||
|
stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN
|
||||||
|
stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
|
||||||
|
stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN
|
||||||
|
stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
|
||||||
|
memcpy(out+stbiw__sbn(out), data+j, blocklen);
|
||||||
|
stbiw__sbn(out) += blocklen;
|
||||||
|
j += blocklen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// compute adler32 on input
|
// compute adler32 on input
|
||||||
unsigned int s1=1, s2=0;
|
unsigned int s1=1, s2=0;
|
||||||
@ -1132,8 +1148,7 @@ STBIWDEF unsigned char* stbi_write_png_to_mem(const unsigned char* pixels, int s
|
|||||||
if (force_filter > -1) {
|
if (force_filter > -1) {
|
||||||
filter_type = force_filter;
|
filter_type = force_filter;
|
||||||
stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
|
stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
|
||||||
}
|
} else { // Estimate the best filter by running through all of them:
|
||||||
else { // Estimate the best filter by running through all of them:
|
|
||||||
int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
|
int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
|
||||||
for (filter_type = 0; filter_type < 5; filter_type++) {
|
for (filter_type = 0; filter_type < 5; filter_type++) {
|
||||||
stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
|
stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
|
||||||
@ -1341,8 +1356,7 @@ static int stbiw__jpg_processDU(stbi__write_context* s, int* bitBuf, int* bitCnt
|
|||||||
diff = DU[0] - DC;
|
diff = DU[0] - DC;
|
||||||
if (diff == 0) {
|
if (diff == 0) {
|
||||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
|
stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
unsigned short bits[2];
|
unsigned short bits[2];
|
||||||
stbiw__jpg_calcBits(diff, bits);
|
stbiw__jpg_calcBits(diff, bits);
|
||||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
|
stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
|
||||||
@ -1554,8 +1568,7 @@ static int stbi_write_jpg_core(stbi__write_context* s, int width, int height, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for(y = 0; y < height; y += 8) {
|
for(y = 0; y < height; y += 8) {
|
||||||
for(x = 0; x < width; x += 8) {
|
for(x = 0; x < width; x += 8) {
|
||||||
float Y[64], U[64], V[64];
|
float Y[64], U[64], V[64];
|
||||||
@ -1607,8 +1620,7 @@ STBIWDEF int stbi_write_jpg(char const* filename, int x, int y, int comp, const
|
|||||||
int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
|
int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
|
||||||
stbi__end_write_file(&s);
|
stbi__end_write_file(&s);
|
||||||
return r;
|
return r;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1616,6 +1628,10 @@ STBIWDEF int stbi_write_jpg(char const* filename, int x, int y, int comp, const
|
|||||||
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
|
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
/* Revision history
|
/* Revision history
|
||||||
|
1.16 (2021-07-11)
|
||||||
|
make Deflate code emit uncompressed blocks when it would otherwise expand
|
||||||
|
support writing BMPs with alpha channel
|
||||||
|
1.15 (2020-07-13) unknown
|
||||||
1.14 (2020-02-02) updated JPEG writer to downsample chroma channels
|
1.14 (2020-02-02) updated JPEG writer to downsample chroma channels
|
||||||
1.13
|
1.13
|
||||||
1.12
|
1.12
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
============================================================================ INFO
|
||||||
|
https://github.com/nemtrif/utfcpp
|
||||||
|
|
||||||
|
VERSION: https://github.com/nemtrif/utfcpp/releases/tag/v4.0.5
|
||||||
|
|
||||||
|
============================================================================ LICENSE
|
||||||
Boost Software License - Version 1.0 - August 17th, 2003
|
Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person or organization
|
Permission is hereby granted, free of charge, to any person or organization
|
@ -63,24 +63,16 @@ enum class notification_type
|
|||||||
|
|
||||||
struct Overlay_Achievement
|
struct Overlay_Achievement
|
||||||
{
|
{
|
||||||
// avoids spam loading on failure
|
std::string name{}; // internal schema name
|
||||||
constexpr const static int ICON_LOAD_MAX_TRIALS = 3;
|
std::string title{}; // displayName
|
||||||
|
std::string description{}; // description
|
||||||
std::string name{};
|
|
||||||
std::string title{};
|
|
||||||
std::string description{};
|
|
||||||
std::string icon_name{};
|
|
||||||
std::string icon_gray_name{};
|
|
||||||
uint32 progress{};
|
uint32 progress{};
|
||||||
uint32 max_progress{};
|
uint32 max_progress{};
|
||||||
bool hidden{};
|
bool hidden{};
|
||||||
bool achieved{};
|
bool achieved{};
|
||||||
uint32 unlock_time{};
|
uint32 unlock_time{};
|
||||||
std::weak_ptr<uint64_t> icon{};
|
std::pair< std::weak_ptr<uint64_t>, bool > icon{};
|
||||||
std::weak_ptr<uint64_t> icon_gray{};
|
std::pair< std::weak_ptr<uint64_t>, bool > icon_gray{};
|
||||||
|
|
||||||
uint8_t icon_load_trials = ICON_LOAD_MAX_TRIALS;
|
|
||||||
uint8_t icon_gray_load_trials = ICON_LOAD_MAX_TRIALS;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Notification
|
struct Notification
|
||||||
@ -107,7 +99,6 @@ struct NotificationsCoords
|
|||||||
class Steam_Overlay
|
class Steam_Overlay
|
||||||
{
|
{
|
||||||
constexpr static const char ACH_SOUNDS_FOLDER[] = "sounds";
|
constexpr static const char ACH_SOUNDS_FOLDER[] = "sounds";
|
||||||
constexpr static const char ACH_FALLBACK_DIR[] = "achievement_images";
|
|
||||||
|
|
||||||
constexpr static const int renderer_detector_polling_ms = 100;
|
constexpr static const int renderer_detector_polling_ms = 100;
|
||||||
|
|
||||||
@ -159,7 +150,6 @@ class Steam_Overlay
|
|||||||
|
|
||||||
// some stuff has to be initialized once the renderer hook is ready
|
// some stuff has to be initialized once the renderer hook is ready
|
||||||
std::atomic<bool> late_init_imgui = false;
|
std::atomic<bool> late_init_imgui = false;
|
||||||
bool late_init_ach_icons = false;
|
|
||||||
|
|
||||||
// changed each time a notification is posted or overlay is shown/hidden
|
// changed each time a notification is posted or overlay is shown/hidden
|
||||||
std::atomic_uint32_t renderer_frame_processing_requests = 0;
|
std::atomic_uint32_t renderer_frame_processing_requests = 0;
|
||||||
@ -235,7 +225,6 @@ class Steam_Overlay
|
|||||||
void create_fonts();
|
void create_fonts();
|
||||||
void load_audio();
|
void load_audio();
|
||||||
void load_achievements_data();
|
void load_achievements_data();
|
||||||
void initial_load_achievements_icons();
|
|
||||||
|
|
||||||
void overlay_state_hook(bool ready);
|
void overlay_state_hook(bool ready);
|
||||||
void allow_renderer_frame_processing(bool state, bool cleaning_up_overlay = false);
|
void allow_renderer_frame_processing(bool state, bool cleaning_up_overlay = false);
|
||||||
|
@ -85,7 +85,23 @@ void Steam_Overlay::overlay_run_callback(void* object)
|
|||||||
{
|
{
|
||||||
// PRINT_DEBUG_ENTRY();
|
// PRINT_DEBUG_ENTRY();
|
||||||
Steam_Overlay* _this = reinterpret_cast<Steam_Overlay*>(object);
|
Steam_Overlay* _this = reinterpret_cast<Steam_Overlay*>(object);
|
||||||
|
|
||||||
|
// bail immediately if we can't lock the overlay mutex, deadlock scenario:
|
||||||
|
// 1. ** the background thread locks the global mutex
|
||||||
|
// 2. -- the user opens the overlay
|
||||||
|
// 3. -- the overlay proc is triggered the next frame, locking the overlay mutex
|
||||||
|
// 4. ** the background thread locks the global mutex and runs this callback
|
||||||
|
// 5. ** this callback (already having the global mutex) attempts to lock the overlay mutex (already locked before)
|
||||||
|
// 6. ** this callback, and the background thread, are now blocked, note that the global mutex is still locked
|
||||||
|
// 7. -- in the same frame, some code in the overlay proc attempts to call a steam API which usually locks the global mutex
|
||||||
|
// sice the global mutex is still locked, the overlay proc is also blocked,
|
||||||
|
// and now both the background thread and the overlay proc and locked
|
||||||
|
// even worse, the global mutex is locked forever now
|
||||||
|
if (!_this->overlay_mutex.try_lock()) return;
|
||||||
|
|
||||||
_this->steam_run_callback();
|
_this->steam_run_callback();
|
||||||
|
|
||||||
|
_this->overlay_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Steam_Overlay::overlay_networking_callback(void* object, Common_Message* msg)
|
void Steam_Overlay::overlay_networking_callback(void* object, Common_Message* msg)
|
||||||
@ -356,9 +372,6 @@ void Steam_Overlay::load_achievements_data()
|
|||||||
ach.unlock_time = 0;
|
ach.unlock_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ach.icon_name = steamUserStats->get_achievement_icon_name(ach.name.c_str(), true);
|
|
||||||
ach.icon_gray_name = steamUserStats->get_achievement_icon_name(ach.name.c_str(), false);
|
|
||||||
|
|
||||||
float pnMinProgress = 0, pnMaxProgress = 0;
|
float pnMinProgress = 0, pnMaxProgress = 0;
|
||||||
if (steamUserStats->GetAchievementProgressLimits(ach.name.c_str(), &pnMinProgress, &pnMaxProgress)) {
|
if (steamUserStats->GetAchievementProgressLimits(ach.name.c_str(), &pnMinProgress, &pnMaxProgress)) {
|
||||||
ach.progress = (uint32)pnMinProgress;
|
ach.progress = (uint32)pnMinProgress;
|
||||||
@ -374,40 +387,6 @@ void Steam_Overlay::load_achievements_data()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Steam_Overlay::initial_load_achievements_icons()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
|
||||||
if (late_init_ach_icons) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRINT_DEBUG_ENTRY();
|
|
||||||
for (auto &ach : achievements) {
|
|
||||||
{
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
|
||||||
if (!is_ready || !setup_overlay_called) {
|
|
||||||
PRINT_DEBUG("early exit");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try_load_ach_icon(ach, true);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
|
||||||
if (!is_ready || !setup_overlay_called) {
|
|
||||||
PRINT_DEBUG("early exit");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try_load_ach_icon(ach, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
|
||||||
late_init_ach_icons = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called initially and when window size is updated
|
// called initially and when window size is updated
|
||||||
void Steam_Overlay::overlay_state_hook(bool ready)
|
void Steam_Overlay::overlay_state_hook(bool ready)
|
||||||
{
|
{
|
||||||
@ -662,7 +641,10 @@ void Steam_Overlay::show_test_achievement()
|
|||||||
|
|
||||||
if (achievements.size()) {
|
if (achievements.size()) {
|
||||||
size_t rand_idx = common_helpers::rand_number(achievements.size() - 1);
|
size_t rand_idx = common_helpers::rand_number(achievements.size() - 1);
|
||||||
ach.icon = achievements[rand_idx].icon;
|
auto &rand_ach = achievements[rand_idx];
|
||||||
|
bool achieved = rand_idx < (achievements.size() / 2);
|
||||||
|
try_load_ach_icon(rand_ach, achieved);
|
||||||
|
ach.icon = achieved ? rand_ach.icon : rand_ach.icon_gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool for_progress = false;
|
bool for_progress = false;
|
||||||
@ -1126,13 +1108,16 @@ void Steam_Overlay::build_notifications(float width, float height)
|
|||||||
case notification_type::achievement_progress:
|
case notification_type::achievement_progress:
|
||||||
case notification_type::achievement: {
|
case notification_type::achievement: {
|
||||||
const auto &ach = it->ach.value();
|
const auto &ach = it->ach.value();
|
||||||
if (!ach.icon.expired() && ImGui::BeginTable("imgui_table", 2)) {
|
auto& [icon_rsrc, _] = (notification_type)it->type == notification_type::achievement
|
||||||
|
? ach.icon
|
||||||
|
: ach.icon_gray;
|
||||||
|
if (!icon_rsrc.expired() && ImGui::BeginTable("imgui_table", 2)) {
|
||||||
ImGui::TableSetupColumn("imgui_table_image", ImGuiTableColumnFlags_WidthFixed, settings->overlay_appearance.icon_size);
|
ImGui::TableSetupColumn("imgui_table_image", ImGuiTableColumnFlags_WidthFixed, settings->overlay_appearance.icon_size);
|
||||||
ImGui::TableSetupColumn("imgui_table_text");
|
ImGui::TableSetupColumn("imgui_table_text");
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_None, settings->overlay_appearance.icon_size);
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, settings->overlay_appearance.icon_size);
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::Image((ImTextureID)*ach.icon.lock().get(), ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size));
|
ImGui::Image((ImTextureID)*icon_rsrc.lock().get(), ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size));
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::TextWrapped("%s", it->message.c_str());
|
ImGui::TextWrapped("%s", it->message.c_str());
|
||||||
@ -1259,7 +1244,7 @@ void Steam_Overlay::post_achievement_notification(Overlay_Achievement &ach, bool
|
|||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
||||||
if (!Ready()) return;
|
if (!Ready()) return;
|
||||||
|
|
||||||
try_load_ach_icon(ach, !for_progress);
|
try_load_ach_icon(ach, !for_progress); // for progress notifications we want to load the gray icon
|
||||||
submit_notification(
|
submit_notification(
|
||||||
for_progress ? notification_type::achievement_progress : notification_type::achievement,
|
for_progress ? notification_type::achievement_progress : notification_type::achievement,
|
||||||
ach.title + "\n" + ach.description,
|
ach.title + "\n" + ach.description,
|
||||||
@ -1284,43 +1269,27 @@ bool Steam_Overlay::try_load_ach_icon(Overlay_Achievement &ach, bool achieved)
|
|||||||
{
|
{
|
||||||
if (!_renderer) return false;
|
if (!_renderer) return false;
|
||||||
|
|
||||||
std::weak_ptr<uint64_t> &icon_rsrc = achieved ? ach.icon : ach.icon_gray;
|
auto& [icon_rsrc, attempted] = achieved ? ach.icon : ach.icon_gray;
|
||||||
const std::string &icon_name = achieved ? ach.icon_name : ach.icon_gray_name;
|
if (attempted || !icon_rsrc.expired()) return true;
|
||||||
uint8_t &load_trials = achieved ? ach.icon_load_trials : ach.icon_gray_load_trials;
|
|
||||||
|
|
||||||
if (!icon_rsrc.expired()) return true;
|
|
||||||
|
|
||||||
if (load_trials && icon_name.size()) {
|
|
||||||
--load_trials;
|
|
||||||
std::string file_path(Local_Storage::get_game_settings_path() + icon_name);
|
|
||||||
unsigned int file_size = file_size_(file_path);
|
|
||||||
if (!file_size) {
|
|
||||||
file_path = Local_Storage::get_game_settings_path() + Steam_Overlay::ACH_FALLBACK_DIR + PATH_SEPARATOR + icon_name;
|
|
||||||
file_size = file_size_(file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const int icon_handle = get_steam_client()->steam_user_stats->get_achievement_icon_handle(ach.name, achieved);
|
||||||
|
auto image_info = settings->get_image(icon_handle);
|
||||||
|
if (image_info) {
|
||||||
int icon_size = static_cast<int>(settings->overlay_appearance.icon_size);
|
int icon_size = static_cast<int>(settings->overlay_appearance.icon_size);
|
||||||
if (file_size) {
|
|
||||||
std::string img(Local_Storage::load_image_resized(file_path, "", icon_size));
|
|
||||||
if (img.size()) {
|
|
||||||
icon_rsrc = _renderer->CreateImageResource(
|
icon_rsrc = _renderer->CreateImageResource(
|
||||||
(void*)img.c_str(),
|
(void*)image_info->data.c_str(),
|
||||||
icon_size, icon_size);
|
icon_size, icon_size);
|
||||||
|
|
||||||
if (!icon_rsrc.expired()) load_trials = Overlay_Achievement::ICON_LOAD_MAX_TRIALS;
|
|
||||||
PRINT_DEBUG("'%s' (result=%i)", ach.name.c_str(), (int)!icon_rsrc.expired());
|
PRINT_DEBUG("'%s' (result=%i)", ach.name.c_str(), (int)!icon_rsrc.expired());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
attempted = true;
|
||||||
return !icon_rsrc.expired();
|
return !icon_rsrc.expired();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to make this function as short as possible or it might affect game's fps.
|
// Try to make this function as short as possible or it might affect game's fps.
|
||||||
void Steam_Overlay::overlay_render_proc()
|
void Steam_Overlay::overlay_render_proc()
|
||||||
{
|
{
|
||||||
initial_load_achievements_icons();
|
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
||||||
if (!Ready()) return;
|
if (!Ready()) return;
|
||||||
|
|
||||||
@ -1517,7 +1486,7 @@ void Steam_Overlay::render_main_window()
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
bool could_create_ach_table_entry = false;
|
bool could_create_ach_table_entry = false;
|
||||||
if (!x.icon.expired() || !x.icon_gray.expired()) {
|
if (!x.icon.first.expired() || !x.icon_gray.first.expired()) {
|
||||||
if (ImGui::BeginTable(x.title.c_str(), 2)) {
|
if (ImGui::BeginTable(x.title.c_str(), 2)) {
|
||||||
could_create_ach_table_entry = true;
|
could_create_ach_table_entry = true;
|
||||||
|
|
||||||
@ -1526,21 +1495,13 @@ void Steam_Overlay::render_main_window()
|
|||||||
ImGui::TableNextRow(ImGuiTableRowFlags_None, settings->overlay_appearance.icon_size);
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, settings->overlay_appearance.icon_size);
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
if (achieved) {
|
auto& [icon_rsrc, _] = achieved ? x.icon : x.icon_gray;
|
||||||
if (!x.icon.expired()) {
|
if (!icon_rsrc.expired()) {
|
||||||
ImGui::Image(
|
ImGui::Image(
|
||||||
(ImTextureID)*x.icon.lock().get(),
|
(ImTextureID)*icon_rsrc.lock().get(),
|
||||||
ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size)
|
ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (!x.icon_gray.expired()) {
|
|
||||||
ImGui::Image(
|
|
||||||
(ImTextureID)*x.icon_gray.lock().get(),
|
|
||||||
ImVec2(settings->overlay_appearance.icon_size, settings->overlay_appearance.icon_size)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
// the next column is the achievement text below
|
// the next column is the achievement text below
|
||||||
@ -1680,8 +1641,6 @@ void Steam_Overlay::networking_msg_received(Common_Message *msg)
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
||||||
|
|
||||||
if (!Ready()) return;
|
|
||||||
|
|
||||||
if (msg->has_steam_messages()) {
|
if (msg->has_steam_messages()) {
|
||||||
Friend frd;
|
Friend frd;
|
||||||
frd.set_id(msg->source_id());
|
frd.set_id(msg->source_id());
|
||||||
@ -1702,8 +1661,6 @@ void Steam_Overlay::networking_msg_received(Common_Message *msg)
|
|||||||
|
|
||||||
void Steam_Overlay::steam_run_callback()
|
void Steam_Overlay::steam_run_callback()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
|
|
||||||
|
|
||||||
if (!Ready()) return;
|
if (!Ready()) return;
|
||||||
|
|
||||||
if (overlay_state_changed) {
|
if (overlay_state_changed) {
|
||||||
@ -1881,14 +1838,14 @@ void Steam_Overlay::UnSetupOverlay()
|
|||||||
|
|
||||||
PRINT_DEBUG("releasing any images resources");
|
PRINT_DEBUG("releasing any images resources");
|
||||||
for (auto &ach : achievements) {
|
for (auto &ach : achievements) {
|
||||||
if (!ach.icon.expired()) {
|
if (!ach.icon.first.expired()) {
|
||||||
_renderer->ReleaseImageResource(ach.icon);
|
_renderer->ReleaseImageResource(ach.icon.first);
|
||||||
ach.icon.reset();
|
ach.icon.first.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ach.icon_gray.expired()) {
|
if (!ach.icon_gray.first.expired()) {
|
||||||
_renderer->ReleaseImageResource(ach.icon_gray);
|
_renderer->ReleaseImageResource(ach.icon_gray.first);
|
||||||
ach.icon_gray.reset();
|
ach.icon_gray.first.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1906,7 +1863,7 @@ void Steam_Overlay::UnSetupOverlay()
|
|||||||
|
|
||||||
bool Steam_Overlay::Ready() const
|
bool Steam_Overlay::Ready() const
|
||||||
{
|
{
|
||||||
return !settings->disable_overlay && is_ready && late_init_imgui && late_init_ach_icons;
|
return !settings->disable_overlay && is_ready && late_init_imgui;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Steam_Overlay::NeedPresent() const
|
bool Steam_Overlay::NeedPresent() const
|
||||||
|
@ -1,245 +0,0 @@
|
|||||||
//
|
|
||||||
// File: vk_icd.h
|
|
||||||
//
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015-2016 The Khronos Group Inc.
|
|
||||||
* Copyright (c) 2015-2016 Valve Corporation
|
|
||||||
* Copyright (c) 2015-2016 LunarG, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef VKICD_H
|
|
||||||
#define VKICD_H
|
|
||||||
|
|
||||||
#include "vulkan.h"
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
// Loader-ICD version negotiation API. Versions add the following features:
|
|
||||||
// Version 0 - Initial. Doesn't support vk_icdGetInstanceProcAddr
|
|
||||||
// or vk_icdNegotiateLoaderICDInterfaceVersion.
|
|
||||||
// Version 1 - Add support for vk_icdGetInstanceProcAddr.
|
|
||||||
// Version 2 - Add Loader/ICD Interface version negotiation
|
|
||||||
// via vk_icdNegotiateLoaderICDInterfaceVersion.
|
|
||||||
// Version 3 - Add ICD creation/destruction of KHR_surface objects.
|
|
||||||
// Version 4 - Add unknown physical device extension querying via
|
|
||||||
// vk_icdGetPhysicalDeviceProcAddr.
|
|
||||||
// Version 5 - Tells ICDs that the loader is now paying attention to the
|
|
||||||
// application version of Vulkan passed into the ApplicationInfo
|
|
||||||
// structure during vkCreateInstance. This will tell the ICD
|
|
||||||
// that if the loader is older, it should automatically fail a
|
|
||||||
// call for any API version > 1.0. Otherwise, the loader will
|
|
||||||
// manually determine if it can support the expected version.
|
|
||||||
// Version 6 - Add support for vk_icdEnumerateAdapterPhysicalDevices.
|
|
||||||
#define CURRENT_LOADER_ICD_INTERFACE_VERSION 6
|
|
||||||
#define MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION 0
|
|
||||||
#define MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION 4
|
|
||||||
|
|
||||||
// Old typedefs that don't follow a proper naming convention but are preserved for compatibility
|
|
||||||
typedef VkResult(VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion);
|
|
||||||
// This is defined in vk_layer.h which will be found by the loader, but if an ICD is building against this
|
|
||||||
// file directly, it won't be found.
|
|
||||||
#ifndef PFN_GetPhysicalDeviceProcAddr
|
|
||||||
typedef PFN_vkVoidFunction(VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char *pName);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Typedefs for loader/ICD interface
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vk_icdNegotiateLoaderICDInterfaceVersion)(uint32_t* pVersion);
|
|
||||||
typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vk_icdGetInstanceProcAddr)(VkInstance instance, const char* pName);
|
|
||||||
typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vk_icdGetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName);
|
|
||||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vk_icdEnumerateAdapterPhysicalDevices)(VkInstance instance, LUID adapterLUID,
|
|
||||||
uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Prototypes for loader/ICD interface
|
|
||||||
#if !defined(VK_NO_PROTOTYPES)
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pVersion);
|
|
||||||
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName);
|
|
||||||
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance isntance, const char* pName);
|
|
||||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID,
|
|
||||||
uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
|
|
||||||
#endif
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The ICD must reserve space for a pointer for the loader's dispatch
|
|
||||||
* table, at the start of <each object>.
|
|
||||||
* The ICD must initialize this variable using the SET_LOADER_MAGIC_VALUE macro.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ICD_LOADER_MAGIC 0x01CDC0DE
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
uintptr_t loaderMagic;
|
|
||||||
void *loaderData;
|
|
||||||
} VK_LOADER_DATA;
|
|
||||||
|
|
||||||
static inline void set_loader_magic_value(void *pNewObject) {
|
|
||||||
VK_LOADER_DATA *loader_info = (VK_LOADER_DATA *)pNewObject;
|
|
||||||
loader_info->loaderMagic = ICD_LOADER_MAGIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool valid_loader_magic_value(void *pNewObject) {
|
|
||||||
const VK_LOADER_DATA *loader_info = (VK_LOADER_DATA *)pNewObject;
|
|
||||||
return (loader_info->loaderMagic & 0xffffffff) == ICD_LOADER_MAGIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Windows and Linux ICDs will treat VkSurfaceKHR as a pointer to a struct that
|
|
||||||
* contains the platform-specific connection and surface information.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
VK_ICD_WSI_PLATFORM_MIR,
|
|
||||||
VK_ICD_WSI_PLATFORM_WAYLAND,
|
|
||||||
VK_ICD_WSI_PLATFORM_WIN32,
|
|
||||||
VK_ICD_WSI_PLATFORM_XCB,
|
|
||||||
VK_ICD_WSI_PLATFORM_XLIB,
|
|
||||||
VK_ICD_WSI_PLATFORM_ANDROID,
|
|
||||||
VK_ICD_WSI_PLATFORM_MACOS,
|
|
||||||
VK_ICD_WSI_PLATFORM_IOS,
|
|
||||||
VK_ICD_WSI_PLATFORM_DISPLAY,
|
|
||||||
VK_ICD_WSI_PLATFORM_HEADLESS,
|
|
||||||
VK_ICD_WSI_PLATFORM_METAL,
|
|
||||||
VK_ICD_WSI_PLATFORM_DIRECTFB,
|
|
||||||
VK_ICD_WSI_PLATFORM_VI,
|
|
||||||
VK_ICD_WSI_PLATFORM_GGP,
|
|
||||||
VK_ICD_WSI_PLATFORM_SCREEN,
|
|
||||||
} VkIcdWsiPlatform;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
VkIcdWsiPlatform platform;
|
|
||||||
} VkIcdSurfaceBase;
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_MIR_KHR
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
MirConnection *connection;
|
|
||||||
MirSurface *mirSurface;
|
|
||||||
} VkIcdSurfaceMir;
|
|
||||||
#endif // VK_USE_PLATFORM_MIR_KHR
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
struct wl_display *display;
|
|
||||||
struct wl_surface *surface;
|
|
||||||
} VkIcdSurfaceWayland;
|
|
||||||
#endif // VK_USE_PLATFORM_WAYLAND_KHR
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
HINSTANCE hinstance;
|
|
||||||
HWND hwnd;
|
|
||||||
} VkIcdSurfaceWin32;
|
|
||||||
#endif // VK_USE_PLATFORM_WIN32_KHR
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
xcb_connection_t *connection;
|
|
||||||
xcb_window_t window;
|
|
||||||
} VkIcdSurfaceXcb;
|
|
||||||
#endif // VK_USE_PLATFORM_XCB_KHR
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
Display *dpy;
|
|
||||||
Window window;
|
|
||||||
} VkIcdSurfaceXlib;
|
|
||||||
#endif // VK_USE_PLATFORM_XLIB_KHR
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
IDirectFB *dfb;
|
|
||||||
IDirectFBSurface *surface;
|
|
||||||
} VkIcdSurfaceDirectFB;
|
|
||||||
#endif // VK_USE_PLATFORM_DIRECTFB_EXT
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
struct ANativeWindow *window;
|
|
||||||
} VkIcdSurfaceAndroid;
|
|
||||||
#endif // VK_USE_PLATFORM_ANDROID_KHR
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_MACOS_MVK
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
const void *pView;
|
|
||||||
} VkIcdSurfaceMacOS;
|
|
||||||
#endif // VK_USE_PLATFORM_MACOS_MVK
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_IOS_MVK
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
const void *pView;
|
|
||||||
} VkIcdSurfaceIOS;
|
|
||||||
#endif // VK_USE_PLATFORM_IOS_MVK
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_GGP
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
GgpStreamDescriptor streamDescriptor;
|
|
||||||
} VkIcdSurfaceGgp;
|
|
||||||
#endif // VK_USE_PLATFORM_GGP
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
VkDisplayModeKHR displayMode;
|
|
||||||
uint32_t planeIndex;
|
|
||||||
uint32_t planeStackIndex;
|
|
||||||
VkSurfaceTransformFlagBitsKHR transform;
|
|
||||||
float globalAlpha;
|
|
||||||
VkDisplayPlaneAlphaFlagBitsKHR alphaMode;
|
|
||||||
VkExtent2D imageExtent;
|
|
||||||
} VkIcdSurfaceDisplay;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
} VkIcdSurfaceHeadless;
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_METAL_EXT
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
const CAMetalLayer *pLayer;
|
|
||||||
} VkIcdSurfaceMetal;
|
|
||||||
#endif // VK_USE_PLATFORM_METAL_EXT
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_VI_NN
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
void *window;
|
|
||||||
} VkIcdSurfaceVi;
|
|
||||||
#endif // VK_USE_PLATFORM_VI_NN
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_SCREEN_QNX
|
|
||||||
typedef struct {
|
|
||||||
VkIcdSurfaceBase base;
|
|
||||||
struct _screen_context *context;
|
|
||||||
struct _screen_window *window;
|
|
||||||
} VkIcdSurfaceScreen;
|
|
||||||
#endif // VK_USE_PLATFORM_SCREEN_QNX
|
|
||||||
|
|
||||||
#endif // VKICD_H
|
|
@ -1,210 +0,0 @@
|
|||||||
//
|
|
||||||
// File: vk_layer.h
|
|
||||||
//
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015-2017 The Khronos Group Inc.
|
|
||||||
* Copyright (c) 2015-2017 Valve Corporation
|
|
||||||
* Copyright (c) 2015-2017 LunarG, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Need to define dispatch table
|
|
||||||
* Core struct can then have ptr to dispatch table at the top
|
|
||||||
* Along with object ptrs for current and next OBJ
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "vulkan.h"
|
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
|
||||||
#define VK_LAYER_EXPORT __attribute__((visibility("default")))
|
|
||||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
|
|
||||||
#define VK_LAYER_EXPORT __attribute__((visibility("default")))
|
|
||||||
#else
|
|
||||||
#define VK_LAYER_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_NUM_UNKNOWN_EXTS 250
|
|
||||||
|
|
||||||
// Loader-Layer version negotiation API. Versions add the following features:
|
|
||||||
// Versions 0/1 - Initial. Doesn't support vk_layerGetPhysicalDeviceProcAddr
|
|
||||||
// or vk_icdNegotiateLoaderLayerInterfaceVersion.
|
|
||||||
// Version 2 - Add support for vk_layerGetPhysicalDeviceProcAddr and
|
|
||||||
// vk_icdNegotiateLoaderLayerInterfaceVersion.
|
|
||||||
#define CURRENT_LOADER_LAYER_INTERFACE_VERSION 2
|
|
||||||
#define MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION 1
|
|
||||||
|
|
||||||
#define VK_CURRENT_CHAIN_VERSION 1
|
|
||||||
|
|
||||||
// Typedef for use in the interfaces below
|
|
||||||
typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName);
|
|
||||||
|
|
||||||
// Version negotiation values
|
|
||||||
typedef enum VkNegotiateLayerStructType {
|
|
||||||
LAYER_NEGOTIATE_UNINTIALIZED = 0,
|
|
||||||
LAYER_NEGOTIATE_INTERFACE_STRUCT = 1,
|
|
||||||
} VkNegotiateLayerStructType;
|
|
||||||
|
|
||||||
// Version negotiation structures
|
|
||||||
typedef struct VkNegotiateLayerInterface {
|
|
||||||
VkNegotiateLayerStructType sType;
|
|
||||||
void *pNext;
|
|
||||||
uint32_t loaderLayerInterfaceVersion;
|
|
||||||
PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
|
|
||||||
PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr;
|
|
||||||
PFN_GetPhysicalDeviceProcAddr pfnGetPhysicalDeviceProcAddr;
|
|
||||||
} VkNegotiateLayerInterface;
|
|
||||||
|
|
||||||
// Version negotiation functions
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkNegotiateLoaderLayerInterfaceVersion)(VkNegotiateLayerInterface *pVersionStruct);
|
|
||||||
|
|
||||||
// Function prototype for unknown physical device extension command
|
|
||||||
typedef VkResult(VKAPI_PTR *PFN_PhysDevExt)(VkPhysicalDevice phys_device);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// CreateInstance and CreateDevice support structures
|
|
||||||
|
|
||||||
/* Sub type of structure for instance and device loader ext of CreateInfo.
|
|
||||||
* When sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
|
|
||||||
* or sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
|
|
||||||
* then VkLayerFunction indicates struct type pointed to by pNext
|
|
||||||
*/
|
|
||||||
typedef enum VkLayerFunction_ {
|
|
||||||
VK_LAYER_LINK_INFO = 0,
|
|
||||||
VK_LOADER_DATA_CALLBACK = 1,
|
|
||||||
VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK = 2,
|
|
||||||
VK_LOADER_FEATURES = 3,
|
|
||||||
} VkLayerFunction;
|
|
||||||
|
|
||||||
typedef struct VkLayerInstanceLink_ {
|
|
||||||
struct VkLayerInstanceLink_ *pNext;
|
|
||||||
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
|
|
||||||
PFN_GetPhysicalDeviceProcAddr pfnNextGetPhysicalDeviceProcAddr;
|
|
||||||
} VkLayerInstanceLink;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When creating the device chain the loader needs to pass
|
|
||||||
* down information about it's device structure needed at
|
|
||||||
* the end of the chain. Passing the data via the
|
|
||||||
* VkLayerDeviceInfo avoids issues with finding the
|
|
||||||
* exact instance being used.
|
|
||||||
*/
|
|
||||||
typedef struct VkLayerDeviceInfo_ {
|
|
||||||
void *device_info;
|
|
||||||
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
|
|
||||||
} VkLayerDeviceInfo;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkSetInstanceLoaderData)(VkInstance instance,
|
|
||||||
void *object);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkSetDeviceLoaderData)(VkDevice device,
|
|
||||||
void *object);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkLayerCreateDevice)(VkInstance instance, VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
|
|
||||||
const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, PFN_vkGetInstanceProcAddr layerGIPA, PFN_vkGetDeviceProcAddr *nextGDPA);
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkLayerDestroyDevice)(VkDevice physicalDevice, const VkAllocationCallbacks *pAllocator, PFN_vkDestroyDevice destroyFunction);
|
|
||||||
|
|
||||||
typedef enum VkLoaderFeastureFlagBits {
|
|
||||||
VK_LOADER_FEATURE_PHYSICAL_DEVICE_SORTING = 0x00000001,
|
|
||||||
} VkLoaderFlagBits;
|
|
||||||
typedef VkFlags VkLoaderFeatureFlags;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
|
|
||||||
const void *pNext;
|
|
||||||
VkLayerFunction function;
|
|
||||||
union {
|
|
||||||
VkLayerInstanceLink *pLayerInfo;
|
|
||||||
PFN_vkSetInstanceLoaderData pfnSetInstanceLoaderData;
|
|
||||||
struct {
|
|
||||||
PFN_vkLayerCreateDevice pfnLayerCreateDevice;
|
|
||||||
PFN_vkLayerDestroyDevice pfnLayerDestroyDevice;
|
|
||||||
} layerDevice;
|
|
||||||
VkLoaderFeatureFlags loaderFeatures;
|
|
||||||
} u;
|
|
||||||
} VkLayerInstanceCreateInfo;
|
|
||||||
|
|
||||||
typedef struct VkLayerDeviceLink_ {
|
|
||||||
struct VkLayerDeviceLink_ *pNext;
|
|
||||||
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
|
|
||||||
PFN_vkGetDeviceProcAddr pfnNextGetDeviceProcAddr;
|
|
||||||
} VkLayerDeviceLink;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
|
|
||||||
const void *pNext;
|
|
||||||
VkLayerFunction function;
|
|
||||||
union {
|
|
||||||
VkLayerDeviceLink *pLayerInfo;
|
|
||||||
PFN_vkSetDeviceLoaderData pfnSetDeviceLoaderData;
|
|
||||||
} u;
|
|
||||||
} VkLayerDeviceCreateInfo;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct);
|
|
||||||
|
|
||||||
typedef enum VkChainType {
|
|
||||||
VK_CHAIN_TYPE_UNKNOWN = 0,
|
|
||||||
VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES = 1,
|
|
||||||
VK_CHAIN_TYPE_ENUMERATE_INSTANCE_LAYER_PROPERTIES = 2,
|
|
||||||
VK_CHAIN_TYPE_ENUMERATE_INSTANCE_VERSION = 3,
|
|
||||||
} VkChainType;
|
|
||||||
|
|
||||||
typedef struct VkChainHeader {
|
|
||||||
VkChainType type;
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t size;
|
|
||||||
} VkChainHeader;
|
|
||||||
|
|
||||||
typedef struct VkEnumerateInstanceExtensionPropertiesChain {
|
|
||||||
VkChainHeader header;
|
|
||||||
VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceExtensionPropertiesChain *, const char *, uint32_t *,
|
|
||||||
VkExtensionProperties *);
|
|
||||||
const struct VkEnumerateInstanceExtensionPropertiesChain *pNextLink;
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
inline VkResult CallDown(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) const {
|
|
||||||
return pfnNextLayer(pNextLink, pLayerName, pPropertyCount, pProperties);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} VkEnumerateInstanceExtensionPropertiesChain;
|
|
||||||
|
|
||||||
typedef struct VkEnumerateInstanceLayerPropertiesChain {
|
|
||||||
VkChainHeader header;
|
|
||||||
VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceLayerPropertiesChain *, uint32_t *, VkLayerProperties *);
|
|
||||||
const struct VkEnumerateInstanceLayerPropertiesChain *pNextLink;
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
inline VkResult CallDown(uint32_t *pPropertyCount, VkLayerProperties *pProperties) const {
|
|
||||||
return pfnNextLayer(pNextLink, pPropertyCount, pProperties);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} VkEnumerateInstanceLayerPropertiesChain;
|
|
||||||
|
|
||||||
typedef struct VkEnumerateInstanceVersionChain {
|
|
||||||
VkChainHeader header;
|
|
||||||
VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceVersionChain *, uint32_t *);
|
|
||||||
const struct VkEnumerateInstanceVersionChain *pNextLink;
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
inline VkResult CallDown(uint32_t *pApiVersion) const {
|
|
||||||
return pfnNextLayer(pNextLink, pApiVersion);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} VkEnumerateInstanceVersionChain;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,84 +0,0 @@
|
|||||||
//
|
|
||||||
// File: vk_platform.h
|
|
||||||
//
|
|
||||||
/*
|
|
||||||
** Copyright 2014-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef VK_PLATFORM_H_
|
|
||||||
#define VK_PLATFORM_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
/*
|
|
||||||
***************************************************************************************************
|
|
||||||
* Platform-specific directives and type declarations
|
|
||||||
***************************************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Platform-specific calling convention macros.
|
|
||||||
*
|
|
||||||
* Platforms should define these so that Vulkan clients call Vulkan commands
|
|
||||||
* with the same calling conventions that the Vulkan implementation expects.
|
|
||||||
*
|
|
||||||
* VKAPI_ATTR - Placed before the return type in function declarations.
|
|
||||||
* Useful for C++11 and GCC/Clang-style function attribute syntax.
|
|
||||||
* VKAPI_CALL - Placed after the return type in function declarations.
|
|
||||||
* Useful for MSVC-style calling convention syntax.
|
|
||||||
* VKAPI_PTR - Placed between the '(' and '*' in function pointer types.
|
|
||||||
*
|
|
||||||
* Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void);
|
|
||||||
* Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
|
|
||||||
*/
|
|
||||||
#if defined(_WIN32)
|
|
||||||
// On Windows, Vulkan commands use the stdcall convention
|
|
||||||
#define VKAPI_ATTR
|
|
||||||
#define VKAPI_CALL __stdcall
|
|
||||||
#define VKAPI_PTR VKAPI_CALL
|
|
||||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
|
||||||
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
|
|
||||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
|
|
||||||
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
|
|
||||||
// calling convention, i.e. float parameters are passed in registers. This
|
|
||||||
// is true even if the rest of the application passes floats on the stack,
|
|
||||||
// as it does by default when compiling for the armeabi-v7a NDK ABI.
|
|
||||||
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
|
|
||||||
#define VKAPI_CALL
|
|
||||||
#define VKAPI_PTR VKAPI_ATTR
|
|
||||||
#else
|
|
||||||
// On other platforms, use the default calling convention
|
|
||||||
#define VKAPI_ATTR
|
|
||||||
#define VKAPI_CALL
|
|
||||||
#define VKAPI_PTR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(VK_NO_STDDEF_H)
|
|
||||||
#include <stddef.h>
|
|
||||||
#endif // !defined(VK_NO_STDDEF_H)
|
|
||||||
|
|
||||||
#if !defined(VK_NO_STDINT_H)
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
|
||||||
typedef signed __int8 int8_t;
|
|
||||||
typedef unsigned __int8 uint8_t;
|
|
||||||
typedef signed __int16 int16_t;
|
|
||||||
typedef unsigned __int16 uint16_t;
|
|
||||||
typedef signed __int32 int32_t;
|
|
||||||
typedef unsigned __int32 uint32_t;
|
|
||||||
typedef signed __int64 int64_t;
|
|
||||||
typedef unsigned __int64 uint64_t;
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
#endif // !defined(VK_NO_STDINT_H)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,69 +0,0 @@
|
|||||||
//
|
|
||||||
// File: vk_sdk_platform.h
|
|
||||||
//
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015-2016 The Khronos Group Inc.
|
|
||||||
* Copyright (c) 2015-2016 Valve Corporation
|
|
||||||
* Copyright (c) 2015-2016 LunarG, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef VK_SDK_PLATFORM_H
|
|
||||||
#define VK_SDK_PLATFORM_H
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#define NOMINMAX
|
|
||||||
#ifndef __cplusplus
|
|
||||||
#undef inline
|
|
||||||
#define inline __inline
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
|
|
||||||
// C99:
|
|
||||||
// Microsoft didn't implement C99 in Visual Studio; but started adding it with
|
|
||||||
// VS2013. However, VS2013 still didn't have snprintf(). The following is a
|
|
||||||
// work-around (Note: The _CRT_SECURE_NO_WARNINGS macro must be set in the
|
|
||||||
// "CMakeLists.txt" file).
|
|
||||||
// NOTE: This is fixed in Visual Studio 2015.
|
|
||||||
#define snprintf _snprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define strdup _strdup
|
|
||||||
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
// Check for noexcept support using clang, with fallback to Windows or GCC version numbers
|
|
||||||
#ifndef NOEXCEPT
|
|
||||||
#if defined(__clang__)
|
|
||||||
#if __has_feature(cxx_noexcept)
|
|
||||||
#define HAS_NOEXCEPT
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46
|
|
||||||
#define HAS_NOEXCEPT
|
|
||||||
#else
|
|
||||||
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 && defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS
|
|
||||||
#define HAS_NOEXCEPT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAS_NOEXCEPT
|
|
||||||
#define NOEXCEPT noexcept
|
|
||||||
#else
|
|
||||||
#define NOEXCEPT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // VK_SDK_PLATFORM_H
|
|
@ -1,92 +0,0 @@
|
|||||||
#ifndef VULKAN_H_
|
|
||||||
#define VULKAN_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "vk_platform.h"
|
|
||||||
#include "vulkan_core.h"
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
|
||||||
#include "vulkan_android.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_FUCHSIA
|
|
||||||
#include <zircon/types.h>
|
|
||||||
#include "vulkan_fuchsia.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_IOS_MVK
|
|
||||||
#include "vulkan_ios.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_MACOS_MVK
|
|
||||||
#include "vulkan_macos.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_METAL_EXT
|
|
||||||
#include "vulkan_metal.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_VI_NN
|
|
||||||
#include "vulkan_vi.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
|
||||||
#include <wayland-client.h>
|
|
||||||
#include "vulkan_wayland.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
|
||||||
#include <windows.h>
|
|
||||||
#include "vulkan_win32.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#include "vulkan_xcb.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include "vulkan_xlib.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
|
|
||||||
#include <directfb.h>
|
|
||||||
#include "vulkan_directfb.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/extensions/Xrandr.h>
|
|
||||||
#include "vulkan_xlib_xrandr.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_GGP
|
|
||||||
#include <ggp_c/vulkan_types.h>
|
|
||||||
#include "vulkan_ggp.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_SCREEN_QNX
|
|
||||||
#include <screen/screen.h>
|
|
||||||
#include "vulkan_screen.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VK_ENABLE_BETA_EXTENSIONS
|
|
||||||
#include "vulkan_beta.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // VULKAN_H_
|
|
@ -1,125 +0,0 @@
|
|||||||
#ifndef VULKAN_ANDROID_H_
|
|
||||||
#define VULKAN_ANDROID_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_android_surface 1
|
|
||||||
struct ANativeWindow;
|
|
||||||
#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
|
|
||||||
#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface"
|
|
||||||
typedef VkFlags VkAndroidSurfaceCreateFlagsKHR;
|
|
||||||
typedef struct VkAndroidSurfaceCreateInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkAndroidSurfaceCreateFlagsKHR flags;
|
|
||||||
struct ANativeWindow* window;
|
|
||||||
} VkAndroidSurfaceCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_ANDROID_external_memory_android_hardware_buffer 1
|
|
||||||
struct AHardwareBuffer;
|
|
||||||
#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 4
|
|
||||||
#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer"
|
|
||||||
typedef struct VkAndroidHardwareBufferUsageANDROID {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint64_t androidHardwareBufferUsage;
|
|
||||||
} VkAndroidHardwareBufferUsageANDROID;
|
|
||||||
|
|
||||||
typedef struct VkAndroidHardwareBufferPropertiesANDROID {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkDeviceSize allocationSize;
|
|
||||||
uint32_t memoryTypeBits;
|
|
||||||
} VkAndroidHardwareBufferPropertiesANDROID;
|
|
||||||
|
|
||||||
typedef struct VkAndroidHardwareBufferFormatPropertiesANDROID {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkFormat format;
|
|
||||||
uint64_t externalFormat;
|
|
||||||
VkFormatFeatureFlags formatFeatures;
|
|
||||||
VkComponentMapping samplerYcbcrConversionComponents;
|
|
||||||
VkSamplerYcbcrModelConversion suggestedYcbcrModel;
|
|
||||||
VkSamplerYcbcrRange suggestedYcbcrRange;
|
|
||||||
VkChromaLocation suggestedXChromaOffset;
|
|
||||||
VkChromaLocation suggestedYChromaOffset;
|
|
||||||
} VkAndroidHardwareBufferFormatPropertiesANDROID;
|
|
||||||
|
|
||||||
typedef struct VkImportAndroidHardwareBufferInfoANDROID {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
struct AHardwareBuffer* buffer;
|
|
||||||
} VkImportAndroidHardwareBufferInfoANDROID;
|
|
||||||
|
|
||||||
typedef struct VkMemoryGetAndroidHardwareBufferInfoANDROID {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkDeviceMemory memory;
|
|
||||||
} VkMemoryGetAndroidHardwareBufferInfoANDROID;
|
|
||||||
|
|
||||||
typedef struct VkExternalFormatANDROID {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint64_t externalFormat;
|
|
||||||
} VkExternalFormatANDROID;
|
|
||||||
|
|
||||||
typedef struct VkAndroidHardwareBufferFormatProperties2ANDROID {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkFormat format;
|
|
||||||
uint64_t externalFormat;
|
|
||||||
VkFormatFeatureFlags2KHR formatFeatures;
|
|
||||||
VkComponentMapping samplerYcbcrConversionComponents;
|
|
||||||
VkSamplerYcbcrModelConversion suggestedYcbcrModel;
|
|
||||||
VkSamplerYcbcrRange suggestedYcbcrRange;
|
|
||||||
VkChromaLocation suggestedXChromaOffset;
|
|
||||||
VkChromaLocation suggestedYChromaOffset;
|
|
||||||
} VkAndroidHardwareBufferFormatProperties2ANDROID;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetAndroidHardwareBufferPropertiesANDROID)(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryAndroidHardwareBufferANDROID)(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetAndroidHardwareBufferPropertiesANDROID(
|
|
||||||
VkDevice device,
|
|
||||||
const struct AHardwareBuffer* buffer,
|
|
||||||
VkAndroidHardwareBufferPropertiesANDROID* pProperties);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID(
|
|
||||||
VkDevice device,
|
|
||||||
const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
|
|
||||||
struct AHardwareBuffer** pBuffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,833 +0,0 @@
|
|||||||
#ifndef VULKAN_BETA_H_
|
|
||||||
#define VULKAN_BETA_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_video_queue 1
|
|
||||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionKHR)
|
|
||||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionParametersKHR)
|
|
||||||
#define VK_KHR_VIDEO_QUEUE_SPEC_VERSION 2
|
|
||||||
#define VK_KHR_VIDEO_QUEUE_EXTENSION_NAME "VK_KHR_video_queue"
|
|
||||||
|
|
||||||
typedef enum VkQueryResultStatusKHR {
|
|
||||||
VK_QUERY_RESULT_STATUS_ERROR_KHR = -1,
|
|
||||||
VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0,
|
|
||||||
VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1,
|
|
||||||
VK_QUERY_RESULT_STATUS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkQueryResultStatusKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoCodecOperationFlagBitsKHR {
|
|
||||||
VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR = 0,
|
|
||||||
#ifdef VK_ENABLE_BETA_EXTENSIONS
|
|
||||||
VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT = 0x00010000,
|
|
||||||
#endif
|
|
||||||
#ifdef VK_ENABLE_BETA_EXTENSIONS
|
|
||||||
VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT = 0x00020000,
|
|
||||||
#endif
|
|
||||||
#ifdef VK_ENABLE_BETA_EXTENSIONS
|
|
||||||
VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_EXT = 0x00000001,
|
|
||||||
#endif
|
|
||||||
#ifdef VK_ENABLE_BETA_EXTENSIONS
|
|
||||||
VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_EXT = 0x00000002,
|
|
||||||
#endif
|
|
||||||
VK_VIDEO_CODEC_OPERATION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoCodecOperationFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoCodecOperationFlagsKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoChromaSubsamplingFlagBitsKHR {
|
|
||||||
VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_BIT_KHR = 0,
|
|
||||||
VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0x00000002,
|
|
||||||
VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0x00000004,
|
|
||||||
VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR = 0x00000008,
|
|
||||||
VK_VIDEO_CHROMA_SUBSAMPLING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoChromaSubsamplingFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoChromaSubsamplingFlagsKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoComponentBitDepthFlagBitsKHR {
|
|
||||||
VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR = 0,
|
|
||||||
VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR = 0x00000004,
|
|
||||||
VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR = 0x00000010,
|
|
||||||
VK_VIDEO_COMPONENT_BIT_DEPTH_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoComponentBitDepthFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoComponentBitDepthFlagsKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoCapabilityFlagBitsKHR {
|
|
||||||
VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR = 0x00000002,
|
|
||||||
VK_VIDEO_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoCapabilityFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoCapabilityFlagsKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoSessionCreateFlagBitsKHR {
|
|
||||||
VK_VIDEO_SESSION_CREATE_DEFAULT_KHR = 0,
|
|
||||||
VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_SESSION_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoSessionCreateFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoSessionCreateFlagsKHR;
|
|
||||||
typedef VkFlags VkVideoBeginCodingFlagsKHR;
|
|
||||||
typedef VkFlags VkVideoEndCodingFlagsKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoCodingControlFlagBitsKHR {
|
|
||||||
VK_VIDEO_CODING_CONTROL_DEFAULT_KHR = 0,
|
|
||||||
VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_CODING_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoCodingControlFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoCodingControlFlagsKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoCodingQualityPresetFlagBitsKHR {
|
|
||||||
VK_VIDEO_CODING_QUALITY_PRESET_NORMAL_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_CODING_QUALITY_PRESET_POWER_BIT_KHR = 0x00000002,
|
|
||||||
VK_VIDEO_CODING_QUALITY_PRESET_QUALITY_BIT_KHR = 0x00000004,
|
|
||||||
VK_VIDEO_CODING_QUALITY_PRESET_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoCodingQualityPresetFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoCodingQualityPresetFlagsKHR;
|
|
||||||
typedef struct VkVideoQueueFamilyProperties2KHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkVideoCodecOperationFlagsKHR videoCodecOperations;
|
|
||||||
} VkVideoQueueFamilyProperties2KHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoProfileKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkVideoCodecOperationFlagBitsKHR videoCodecOperation;
|
|
||||||
VkVideoChromaSubsamplingFlagsKHR chromaSubsampling;
|
|
||||||
VkVideoComponentBitDepthFlagsKHR lumaBitDepth;
|
|
||||||
VkVideoComponentBitDepthFlagsKHR chromaBitDepth;
|
|
||||||
} VkVideoProfileKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoProfilesKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint32_t profileCount;
|
|
||||||
const VkVideoProfileKHR* pProfiles;
|
|
||||||
} VkVideoProfilesKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoCapabilitiesKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkVideoCapabilityFlagsKHR capabilityFlags;
|
|
||||||
VkDeviceSize minBitstreamBufferOffsetAlignment;
|
|
||||||
VkDeviceSize minBitstreamBufferSizeAlignment;
|
|
||||||
VkExtent2D videoPictureExtentGranularity;
|
|
||||||
VkExtent2D minExtent;
|
|
||||||
VkExtent2D maxExtent;
|
|
||||||
uint32_t maxReferencePicturesSlotsCount;
|
|
||||||
uint32_t maxReferencePicturesActiveCount;
|
|
||||||
} VkVideoCapabilitiesKHR;
|
|
||||||
|
|
||||||
typedef struct VkPhysicalDeviceVideoFormatInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkImageUsageFlags imageUsage;
|
|
||||||
const VkVideoProfilesKHR* pVideoProfiles;
|
|
||||||
} VkPhysicalDeviceVideoFormatInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoFormatPropertiesKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkFormat format;
|
|
||||||
} VkVideoFormatPropertiesKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoPictureResourceKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkOffset2D codedOffset;
|
|
||||||
VkExtent2D codedExtent;
|
|
||||||
uint32_t baseArrayLayer;
|
|
||||||
VkImageView imageViewBinding;
|
|
||||||
} VkVideoPictureResourceKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoReferenceSlotKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
int8_t slotIndex;
|
|
||||||
const VkVideoPictureResourceKHR* pPictureResource;
|
|
||||||
} VkVideoReferenceSlotKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoGetMemoryPropertiesKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t memoryBindIndex;
|
|
||||||
VkMemoryRequirements2* pMemoryRequirements;
|
|
||||||
} VkVideoGetMemoryPropertiesKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoBindMemoryKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t memoryBindIndex;
|
|
||||||
VkDeviceMemory memory;
|
|
||||||
VkDeviceSize memoryOffset;
|
|
||||||
VkDeviceSize memorySize;
|
|
||||||
} VkVideoBindMemoryKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoSessionCreateInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t queueFamilyIndex;
|
|
||||||
VkVideoSessionCreateFlagsKHR flags;
|
|
||||||
const VkVideoProfileKHR* pVideoProfile;
|
|
||||||
VkFormat pictureFormat;
|
|
||||||
VkExtent2D maxCodedExtent;
|
|
||||||
VkFormat referencePicturesFormat;
|
|
||||||
uint32_t maxReferencePicturesSlotsCount;
|
|
||||||
uint32_t maxReferencePicturesActiveCount;
|
|
||||||
} VkVideoSessionCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoSessionParametersCreateInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoSessionParametersKHR videoSessionParametersTemplate;
|
|
||||||
VkVideoSessionKHR videoSession;
|
|
||||||
} VkVideoSessionParametersCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoSessionParametersUpdateInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t updateSequenceCount;
|
|
||||||
} VkVideoSessionParametersUpdateInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoBeginCodingInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoBeginCodingFlagsKHR flags;
|
|
||||||
VkVideoCodingQualityPresetFlagsKHR codecQualityPreset;
|
|
||||||
VkVideoSessionKHR videoSession;
|
|
||||||
VkVideoSessionParametersKHR videoSessionParameters;
|
|
||||||
uint32_t referenceSlotCount;
|
|
||||||
const VkVideoReferenceSlotKHR* pReferenceSlots;
|
|
||||||
} VkVideoBeginCodingInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoEndCodingInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoEndCodingFlagsKHR flags;
|
|
||||||
} VkVideoEndCodingInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoCodingControlInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoCodingControlFlagsKHR flags;
|
|
||||||
} VkVideoCodingControlInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)(VkPhysicalDevice physicalDevice, const VkVideoProfileKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionKHR)(VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession);
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionKHR)(VkDevice device, VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetVideoSessionMemoryRequirementsKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pVideoSessionMemoryRequirementsCount, VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkBindVideoSessionMemoryKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t videoSessionBindMemoryCount, const VkVideoBindMemoryKHR* pVideoSessionBindMemories);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionParametersKHR)(VkDevice device, const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionParametersKHR* pVideoSessionParameters);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkUpdateVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo);
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkAllocationCallbacks* pAllocator);
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkCmdBeginVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoBeginCodingInfoKHR* pBeginInfo);
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkCmdEndVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoEndCodingInfoKHR* pEndCodingInfo);
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkCmdControlVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoCodingControlInfoKHR* pCodingControlInfo);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoCapabilitiesKHR(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
const VkVideoProfileKHR* pVideoProfile,
|
|
||||||
VkVideoCapabilitiesKHR* pCapabilities);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoFormatPropertiesKHR(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo,
|
|
||||||
uint32_t* pVideoFormatPropertyCount,
|
|
||||||
VkVideoFormatPropertiesKHR* pVideoFormatProperties);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionKHR(
|
|
||||||
VkDevice device,
|
|
||||||
const VkVideoSessionCreateInfoKHR* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkVideoSessionKHR* pVideoSession);
|
|
||||||
|
|
||||||
VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionKHR(
|
|
||||||
VkDevice device,
|
|
||||||
VkVideoSessionKHR videoSession,
|
|
||||||
const VkAllocationCallbacks* pAllocator);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetVideoSessionMemoryRequirementsKHR(
|
|
||||||
VkDevice device,
|
|
||||||
VkVideoSessionKHR videoSession,
|
|
||||||
uint32_t* pVideoSessionMemoryRequirementsCount,
|
|
||||||
VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkBindVideoSessionMemoryKHR(
|
|
||||||
VkDevice device,
|
|
||||||
VkVideoSessionKHR videoSession,
|
|
||||||
uint32_t videoSessionBindMemoryCount,
|
|
||||||
const VkVideoBindMemoryKHR* pVideoSessionBindMemories);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionParametersKHR(
|
|
||||||
VkDevice device,
|
|
||||||
const VkVideoSessionParametersCreateInfoKHR* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkVideoSessionParametersKHR* pVideoSessionParameters);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkUpdateVideoSessionParametersKHR(
|
|
||||||
VkDevice device,
|
|
||||||
VkVideoSessionParametersKHR videoSessionParameters,
|
|
||||||
const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo);
|
|
||||||
|
|
||||||
VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionParametersKHR(
|
|
||||||
VkDevice device,
|
|
||||||
VkVideoSessionParametersKHR videoSessionParameters,
|
|
||||||
const VkAllocationCallbacks* pAllocator);
|
|
||||||
|
|
||||||
VKAPI_ATTR void VKAPI_CALL vkCmdBeginVideoCodingKHR(
|
|
||||||
VkCommandBuffer commandBuffer,
|
|
||||||
const VkVideoBeginCodingInfoKHR* pBeginInfo);
|
|
||||||
|
|
||||||
VKAPI_ATTR void VKAPI_CALL vkCmdEndVideoCodingKHR(
|
|
||||||
VkCommandBuffer commandBuffer,
|
|
||||||
const VkVideoEndCodingInfoKHR* pEndCodingInfo);
|
|
||||||
|
|
||||||
VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR(
|
|
||||||
VkCommandBuffer commandBuffer,
|
|
||||||
const VkVideoCodingControlInfoKHR* pCodingControlInfo);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_video_decode_queue 1
|
|
||||||
#define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 2
|
|
||||||
#define VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME "VK_KHR_video_decode_queue"
|
|
||||||
|
|
||||||
typedef enum VkVideoDecodeFlagBitsKHR {
|
|
||||||
VK_VIDEO_DECODE_DEFAULT_KHR = 0,
|
|
||||||
VK_VIDEO_DECODE_RESERVED_0_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_DECODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoDecodeFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoDecodeFlagsKHR;
|
|
||||||
typedef struct VkVideoDecodeInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoDecodeFlagsKHR flags;
|
|
||||||
VkOffset2D codedOffset;
|
|
||||||
VkExtent2D codedExtent;
|
|
||||||
VkBuffer srcBuffer;
|
|
||||||
VkDeviceSize srcBufferOffset;
|
|
||||||
VkDeviceSize srcBufferRange;
|
|
||||||
VkVideoPictureResourceKHR dstPictureResource;
|
|
||||||
const VkVideoReferenceSlotKHR* pSetupReferenceSlot;
|
|
||||||
uint32_t referenceSlotCount;
|
|
||||||
const VkVideoReferenceSlotKHR* pReferenceSlots;
|
|
||||||
} VkVideoDecodeInfoKHR;
|
|
||||||
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pFrameInfo);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR(
|
|
||||||
VkCommandBuffer commandBuffer,
|
|
||||||
const VkVideoDecodeInfoKHR* pFrameInfo);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_portability_subset 1
|
|
||||||
#define VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION 1
|
|
||||||
#define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset"
|
|
||||||
typedef struct VkPhysicalDevicePortabilitySubsetFeaturesKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkBool32 constantAlphaColorBlendFactors;
|
|
||||||
VkBool32 events;
|
|
||||||
VkBool32 imageViewFormatReinterpretation;
|
|
||||||
VkBool32 imageViewFormatSwizzle;
|
|
||||||
VkBool32 imageView2DOn3DImage;
|
|
||||||
VkBool32 multisampleArrayImage;
|
|
||||||
VkBool32 mutableComparisonSamplers;
|
|
||||||
VkBool32 pointPolygons;
|
|
||||||
VkBool32 samplerMipLodBias;
|
|
||||||
VkBool32 separateStencilMaskRef;
|
|
||||||
VkBool32 shaderSampleRateInterpolationFunctions;
|
|
||||||
VkBool32 tessellationIsolines;
|
|
||||||
VkBool32 tessellationPointMode;
|
|
||||||
VkBool32 triangleFans;
|
|
||||||
VkBool32 vertexAttributeAccessBeyondStride;
|
|
||||||
} VkPhysicalDevicePortabilitySubsetFeaturesKHR;
|
|
||||||
|
|
||||||
typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint32_t minVertexInputBindingStrideAlignment;
|
|
||||||
} VkPhysicalDevicePortabilitySubsetPropertiesKHR;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_video_encode_queue 1
|
|
||||||
#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 3
|
|
||||||
#define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue"
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeFlagBitsKHR {
|
|
||||||
VK_VIDEO_ENCODE_DEFAULT_KHR = 0,
|
|
||||||
VK_VIDEO_ENCODE_RESERVED_0_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoEncodeFlagsKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeRateControlFlagBitsKHR {
|
|
||||||
VK_VIDEO_ENCODE_RATE_CONTROL_DEFAULT_KHR = 0,
|
|
||||||
VK_VIDEO_ENCODE_RATE_CONTROL_RESET_BIT_KHR = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_RATE_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeRateControlFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoEncodeRateControlFlagsKHR;
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeRateControlModeFlagBitsKHR {
|
|
||||||
VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR = 0,
|
|
||||||
VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 1,
|
|
||||||
VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 2,
|
|
||||||
VK_VIDEO_ENCODE_RATE_CONTROL_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeRateControlModeFlagBitsKHR;
|
|
||||||
typedef VkFlags VkVideoEncodeRateControlModeFlagsKHR;
|
|
||||||
typedef struct VkVideoEncodeInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoEncodeFlagsKHR flags;
|
|
||||||
uint32_t qualityLevel;
|
|
||||||
VkExtent2D codedExtent;
|
|
||||||
VkBuffer dstBitstreamBuffer;
|
|
||||||
VkDeviceSize dstBitstreamBufferOffset;
|
|
||||||
VkDeviceSize dstBitstreamBufferMaxRange;
|
|
||||||
VkVideoPictureResourceKHR srcPictureResource;
|
|
||||||
const VkVideoReferenceSlotKHR* pSetupReferenceSlot;
|
|
||||||
uint32_t referenceSlotCount;
|
|
||||||
const VkVideoReferenceSlotKHR* pReferenceSlots;
|
|
||||||
} VkVideoEncodeInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeRateControlInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoEncodeRateControlFlagsKHR flags;
|
|
||||||
VkVideoEncodeRateControlModeFlagBitsKHR rateControlMode;
|
|
||||||
uint32_t averageBitrate;
|
|
||||||
uint16_t peakToAverageBitrateRatio;
|
|
||||||
uint16_t frameRateNumerator;
|
|
||||||
uint16_t frameRateDenominator;
|
|
||||||
uint32_t virtualBufferSizeInMs;
|
|
||||||
} VkVideoEncodeRateControlInfoKHR;
|
|
||||||
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkCmdEncodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR(
|
|
||||||
VkCommandBuffer commandBuffer,
|
|
||||||
const VkVideoEncodeInfoKHR* pEncodeInfo);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_EXT_video_encode_h264 1
|
|
||||||
#include "vk_video/vulkan_video_codec_h264std.h"
|
|
||||||
#include "vk_video/vulkan_video_codec_h264std_encode.h"
|
|
||||||
#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 2
|
|
||||||
#define VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_EXT_video_encode_h264"
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeH264CapabilityFlagBitsEXT {
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT = 0x00000002,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BI_PRED_IMPLICIT_BIT_EXT = 0x00000004,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT = 0x00000008,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT = 0x00000010,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT = 0x00000020,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0x00000040,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0x00000080,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0x00000100,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT = 0x00000200,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_EVENLY_DISTRIBUTED_SLICE_SIZE_BIT_EXT = 0x00000400,
|
|
||||||
VK_VIDEO_ENCODE_H264_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeH264CapabilityFlagBitsEXT;
|
|
||||||
typedef VkFlags VkVideoEncodeH264CapabilityFlagsEXT;
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeH264InputModeFlagBitsEXT {
|
|
||||||
VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT = 0x00000002,
|
|
||||||
VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004,
|
|
||||||
VK_VIDEO_ENCODE_H264_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeH264InputModeFlagBitsEXT;
|
|
||||||
typedef VkFlags VkVideoEncodeH264InputModeFlagsEXT;
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeH264OutputModeFlagBitsEXT {
|
|
||||||
VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002,
|
|
||||||
VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004,
|
|
||||||
VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeH264OutputModeFlagBitsEXT;
|
|
||||||
typedef VkFlags VkVideoEncodeH264OutputModeFlagsEXT;
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeH264CreateFlagBitsEXT {
|
|
||||||
VK_VIDEO_ENCODE_H264_CREATE_DEFAULT_EXT = 0,
|
|
||||||
VK_VIDEO_ENCODE_H264_CREATE_RESERVED_0_BIT_EXT = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_H264_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeH264CreateFlagBitsEXT;
|
|
||||||
typedef VkFlags VkVideoEncodeH264CreateFlagsEXT;
|
|
||||||
typedef struct VkVideoEncodeH264CapabilitiesEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoEncodeH264CapabilityFlagsEXT flags;
|
|
||||||
VkVideoEncodeH264InputModeFlagsEXT inputModeFlags;
|
|
||||||
VkVideoEncodeH264OutputModeFlagsEXT outputModeFlags;
|
|
||||||
VkExtent2D minPictureSizeInMbs;
|
|
||||||
VkExtent2D maxPictureSizeInMbs;
|
|
||||||
VkExtent2D inputImageDataAlignment;
|
|
||||||
uint8_t maxNumL0ReferenceForP;
|
|
||||||
uint8_t maxNumL0ReferenceForB;
|
|
||||||
uint8_t maxNumL1Reference;
|
|
||||||
uint8_t qualityLevelCount;
|
|
||||||
VkExtensionProperties stdExtensionVersion;
|
|
||||||
} VkVideoEncodeH264CapabilitiesEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH264SessionCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoEncodeH264CreateFlagsEXT flags;
|
|
||||||
VkExtent2D maxPictureSizeInMbs;
|
|
||||||
const VkExtensionProperties* pStdExtensionVersion;
|
|
||||||
} VkVideoEncodeH264SessionCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH264SessionParametersAddInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t spsStdCount;
|
|
||||||
const StdVideoH264SequenceParameterSet* pSpsStd;
|
|
||||||
uint32_t ppsStdCount;
|
|
||||||
const StdVideoH264PictureParameterSet* pPpsStd;
|
|
||||||
} VkVideoEncodeH264SessionParametersAddInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH264SessionParametersCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t maxSpsStdCount;
|
|
||||||
uint32_t maxPpsStdCount;
|
|
||||||
const VkVideoEncodeH264SessionParametersAddInfoEXT* pParametersAddInfo;
|
|
||||||
} VkVideoEncodeH264SessionParametersCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH264DpbSlotInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
int8_t slotIndex;
|
|
||||||
const StdVideoEncodeH264PictureInfo* pStdPictureInfo;
|
|
||||||
} VkVideoEncodeH264DpbSlotInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH264NaluSliceEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const StdVideoEncodeH264SliceHeader* pSliceHeaderStd;
|
|
||||||
uint32_t mbCount;
|
|
||||||
uint8_t refFinalList0EntryCount;
|
|
||||||
const VkVideoEncodeH264DpbSlotInfoEXT* pRefFinalList0Entries;
|
|
||||||
uint8_t refFinalList1EntryCount;
|
|
||||||
const VkVideoEncodeH264DpbSlotInfoEXT* pRefFinalList1Entries;
|
|
||||||
uint32_t precedingNaluBytes;
|
|
||||||
uint8_t minQp;
|
|
||||||
uint8_t maxQp;
|
|
||||||
} VkVideoEncodeH264NaluSliceEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH264VclFrameInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint8_t refDefaultFinalList0EntryCount;
|
|
||||||
const VkVideoEncodeH264DpbSlotInfoEXT* pRefDefaultFinalList0Entries;
|
|
||||||
uint8_t refDefaultFinalList1EntryCount;
|
|
||||||
const VkVideoEncodeH264DpbSlotInfoEXT* pRefDefaultFinalList1Entries;
|
|
||||||
uint32_t naluSliceEntryCount;
|
|
||||||
const VkVideoEncodeH264NaluSliceEXT* pNaluSliceEntries;
|
|
||||||
const VkVideoEncodeH264DpbSlotInfoEXT* pCurrentPictureInfo;
|
|
||||||
} VkVideoEncodeH264VclFrameInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH264EmitPictureParametersEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint8_t spsId;
|
|
||||||
VkBool32 emitSpsEnable;
|
|
||||||
uint32_t ppsIdEntryCount;
|
|
||||||
const uint8_t* ppsIdEntries;
|
|
||||||
} VkVideoEncodeH264EmitPictureParametersEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH264ProfileEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
StdVideoH264ProfileIdc stdProfileIdc;
|
|
||||||
} VkVideoEncodeH264ProfileEXT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_EXT_video_encode_h265 1
|
|
||||||
#include "vk_video/vulkan_video_codec_h265std.h"
|
|
||||||
#include "vk_video/vulkan_video_codec_h265std_encode.h"
|
|
||||||
#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 2
|
|
||||||
#define VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_EXT_video_encode_h265"
|
|
||||||
typedef VkFlags VkVideoEncodeH265CapabilityFlagsEXT;
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeH265InputModeFlagBitsEXT {
|
|
||||||
VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_BIT_EXT = 0x00000002,
|
|
||||||
VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004,
|
|
||||||
VK_VIDEO_ENCODE_H265_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeH265InputModeFlagBitsEXT;
|
|
||||||
typedef VkFlags VkVideoEncodeH265InputModeFlagsEXT;
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeH265OutputModeFlagBitsEXT {
|
|
||||||
VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002,
|
|
||||||
VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004,
|
|
||||||
VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeH265OutputModeFlagBitsEXT;
|
|
||||||
typedef VkFlags VkVideoEncodeH265OutputModeFlagsEXT;
|
|
||||||
typedef VkFlags VkVideoEncodeH265CreateFlagsEXT;
|
|
||||||
|
|
||||||
typedef enum VkVideoEncodeH265CtbSizeFlagBitsEXT {
|
|
||||||
VK_VIDEO_ENCODE_H265_CTB_SIZE_8_BIT_EXT = 0x00000001,
|
|
||||||
VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT = 0x00000002,
|
|
||||||
VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT = 0x00000004,
|
|
||||||
VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT = 0x00000008,
|
|
||||||
VK_VIDEO_ENCODE_H265_CTB_SIZE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkVideoEncodeH265CtbSizeFlagBitsEXT;
|
|
||||||
typedef VkFlags VkVideoEncodeH265CtbSizeFlagsEXT;
|
|
||||||
typedef struct VkVideoEncodeH265CapabilitiesEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoEncodeH265CapabilityFlagsEXT flags;
|
|
||||||
VkVideoEncodeH265InputModeFlagsEXT inputModeFlags;
|
|
||||||
VkVideoEncodeH265OutputModeFlagsEXT outputModeFlags;
|
|
||||||
VkVideoEncodeH265CtbSizeFlagsEXT ctbSizes;
|
|
||||||
VkExtent2D inputImageDataAlignment;
|
|
||||||
uint8_t maxNumL0ReferenceForP;
|
|
||||||
uint8_t maxNumL0ReferenceForB;
|
|
||||||
uint8_t maxNumL1Reference;
|
|
||||||
uint8_t maxNumSubLayers;
|
|
||||||
uint8_t qualityLevelCount;
|
|
||||||
VkExtensionProperties stdExtensionVersion;
|
|
||||||
} VkVideoEncodeH265CapabilitiesEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265SessionCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoEncodeH265CreateFlagsEXT flags;
|
|
||||||
const VkExtensionProperties* pStdExtensionVersion;
|
|
||||||
} VkVideoEncodeH265SessionCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265SessionParametersAddInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t vpsStdCount;
|
|
||||||
const StdVideoH265VideoParameterSet* pVpsStd;
|
|
||||||
uint32_t spsStdCount;
|
|
||||||
const StdVideoH265SequenceParameterSet* pSpsStd;
|
|
||||||
uint32_t ppsStdCount;
|
|
||||||
const StdVideoH265PictureParameterSet* pPpsStd;
|
|
||||||
} VkVideoEncodeH265SessionParametersAddInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265SessionParametersCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t maxVpsStdCount;
|
|
||||||
uint32_t maxSpsStdCount;
|
|
||||||
uint32_t maxPpsStdCount;
|
|
||||||
const VkVideoEncodeH265SessionParametersAddInfoEXT* pParametersAddInfo;
|
|
||||||
} VkVideoEncodeH265SessionParametersCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265DpbSlotInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
int8_t slotIndex;
|
|
||||||
const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo;
|
|
||||||
} VkVideoEncodeH265DpbSlotInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265ReferenceListsEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint8_t referenceList0EntryCount;
|
|
||||||
const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList0Entries;
|
|
||||||
uint8_t referenceList1EntryCount;
|
|
||||||
const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList1Entries;
|
|
||||||
const StdVideoEncodeH265ReferenceModifications* pReferenceModifications;
|
|
||||||
} VkVideoEncodeH265ReferenceListsEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265NaluSliceEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t ctbCount;
|
|
||||||
const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists;
|
|
||||||
const StdVideoEncodeH265SliceHeader* pSliceHeaderStd;
|
|
||||||
} VkVideoEncodeH265NaluSliceEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265VclFrameInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists;
|
|
||||||
uint32_t naluSliceEntryCount;
|
|
||||||
const VkVideoEncodeH265NaluSliceEXT* pNaluSliceEntries;
|
|
||||||
const StdVideoEncodeH265PictureInfo* pCurrentPictureInfo;
|
|
||||||
} VkVideoEncodeH265VclFrameInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265EmitPictureParametersEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint8_t vpsId;
|
|
||||||
uint8_t spsId;
|
|
||||||
VkBool32 emitVpsEnable;
|
|
||||||
VkBool32 emitSpsEnable;
|
|
||||||
uint32_t ppsIdEntryCount;
|
|
||||||
const uint8_t* ppsIdEntries;
|
|
||||||
} VkVideoEncodeH265EmitPictureParametersEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoEncodeH265ProfileEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
StdVideoH265ProfileIdc stdProfileIdc;
|
|
||||||
} VkVideoEncodeH265ProfileEXT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_EXT_video_decode_h264 1
|
|
||||||
#include "vk_video/vulkan_video_codec_h264std_decode.h"
|
|
||||||
#define VK_EXT_VIDEO_DECODE_H264_SPEC_VERSION 3
|
|
||||||
#define VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME "VK_EXT_video_decode_h264"
|
|
||||||
|
|
||||||
typedef enum VkVideoDecodeH264PictureLayoutFlagBitsEXT {
|
|
||||||
VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_EXT = 0,
|
|
||||||
VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_EXT = 0x00000001,
|
|
||||||
VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_EXT = 0x00000002,
|
|
||||||
VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkVideoDecodeH264PictureLayoutFlagBitsEXT;
|
|
||||||
typedef VkFlags VkVideoDecodeH264PictureLayoutFlagsEXT;
|
|
||||||
typedef VkFlags VkVideoDecodeH264CreateFlagsEXT;
|
|
||||||
typedef struct VkVideoDecodeH264ProfileEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
StdVideoH264ProfileIdc stdProfileIdc;
|
|
||||||
VkVideoDecodeH264PictureLayoutFlagsEXT pictureLayout;
|
|
||||||
} VkVideoDecodeH264ProfileEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH264CapabilitiesEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint32_t maxLevel;
|
|
||||||
VkOffset2D fieldOffsetGranularity;
|
|
||||||
VkExtensionProperties stdExtensionVersion;
|
|
||||||
} VkVideoDecodeH264CapabilitiesEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH264SessionCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoDecodeH264CreateFlagsEXT flags;
|
|
||||||
const VkExtensionProperties* pStdExtensionVersion;
|
|
||||||
} VkVideoDecodeH264SessionCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH264SessionParametersAddInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t spsStdCount;
|
|
||||||
const StdVideoH264SequenceParameterSet* pSpsStd;
|
|
||||||
uint32_t ppsStdCount;
|
|
||||||
const StdVideoH264PictureParameterSet* pPpsStd;
|
|
||||||
} VkVideoDecodeH264SessionParametersAddInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH264SessionParametersCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t maxSpsStdCount;
|
|
||||||
uint32_t maxPpsStdCount;
|
|
||||||
const VkVideoDecodeH264SessionParametersAddInfoEXT* pParametersAddInfo;
|
|
||||||
} VkVideoDecodeH264SessionParametersCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH264PictureInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const StdVideoDecodeH264PictureInfo* pStdPictureInfo;
|
|
||||||
uint32_t slicesCount;
|
|
||||||
const uint32_t* pSlicesDataOffsets;
|
|
||||||
} VkVideoDecodeH264PictureInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH264MvcEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const StdVideoDecodeH264Mvc* pStdMvc;
|
|
||||||
} VkVideoDecodeH264MvcEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH264DpbSlotInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const StdVideoDecodeH264ReferenceInfo* pStdReferenceInfo;
|
|
||||||
} VkVideoDecodeH264DpbSlotInfoEXT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_EXT_video_decode_h265 1
|
|
||||||
#include "vk_video/vulkan_video_codec_h265std_decode.h"
|
|
||||||
#define VK_EXT_VIDEO_DECODE_H265_SPEC_VERSION 1
|
|
||||||
#define VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME "VK_EXT_video_decode_h265"
|
|
||||||
typedef VkFlags VkVideoDecodeH265CreateFlagsEXT;
|
|
||||||
typedef struct VkVideoDecodeH265ProfileEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
StdVideoH265ProfileIdc stdProfileIdc;
|
|
||||||
} VkVideoDecodeH265ProfileEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH265CapabilitiesEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint32_t maxLevel;
|
|
||||||
VkExtensionProperties stdExtensionVersion;
|
|
||||||
} VkVideoDecodeH265CapabilitiesEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH265SessionCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkVideoDecodeH265CreateFlagsEXT flags;
|
|
||||||
const VkExtensionProperties* pStdExtensionVersion;
|
|
||||||
} VkVideoDecodeH265SessionCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH265SessionParametersAddInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t spsStdCount;
|
|
||||||
const StdVideoH265SequenceParameterSet* pSpsStd;
|
|
||||||
uint32_t ppsStdCount;
|
|
||||||
const StdVideoH265PictureParameterSet* pPpsStd;
|
|
||||||
} VkVideoDecodeH265SessionParametersAddInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH265SessionParametersCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t maxSpsStdCount;
|
|
||||||
uint32_t maxPpsStdCount;
|
|
||||||
const VkVideoDecodeH265SessionParametersAddInfoEXT* pParametersAddInfo;
|
|
||||||
} VkVideoDecodeH265SessionParametersCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH265PictureInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
StdVideoDecodeH265PictureInfo* pStdPictureInfo;
|
|
||||||
uint32_t slicesCount;
|
|
||||||
const uint32_t* pSlicesDataOffsets;
|
|
||||||
} VkVideoDecodeH265PictureInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkVideoDecodeH265DpbSlotInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const StdVideoDecodeH265ReferenceInfo* pStdReferenceInfo;
|
|
||||||
} VkVideoDecodeH265DpbSlotInfoEXT;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@ -1,54 +0,0 @@
|
|||||||
#ifndef VULKAN_DIRECTFB_H_
|
|
||||||
#define VULKAN_DIRECTFB_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_EXT_directfb_surface 1
|
|
||||||
#define VK_EXT_DIRECTFB_SURFACE_SPEC_VERSION 1
|
|
||||||
#define VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME "VK_EXT_directfb_surface"
|
|
||||||
typedef VkFlags VkDirectFBSurfaceCreateFlagsEXT;
|
|
||||||
typedef struct VkDirectFBSurfaceCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkDirectFBSurfaceCreateFlagsEXT flags;
|
|
||||||
IDirectFB* dfb;
|
|
||||||
IDirectFBSurface* surface;
|
|
||||||
} VkDirectFBSurfaceCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateDirectFBSurfaceEXT)(VkInstance instance, const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, IDirectFB* dfb);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDirectFBSurfaceEXT(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceDirectFBPresentationSupportEXT(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
uint32_t queueFamilyIndex,
|
|
||||||
IDirectFB* dfb);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,258 +0,0 @@
|
|||||||
#ifndef VULKAN_FUCHSIA_H_
|
|
||||||
#define VULKAN_FUCHSIA_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_FUCHSIA_imagepipe_surface 1
|
|
||||||
#define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1
|
|
||||||
#define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface"
|
|
||||||
typedef VkFlags VkImagePipeSurfaceCreateFlagsFUCHSIA;
|
|
||||||
typedef struct VkImagePipeSurfaceCreateInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkImagePipeSurfaceCreateFlagsFUCHSIA flags;
|
|
||||||
zx_handle_t imagePipeHandle;
|
|
||||||
} VkImagePipeSurfaceCreateInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateImagePipeSurfaceFUCHSIA)(VkInstance instance, const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_FUCHSIA_external_memory 1
|
|
||||||
#define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1
|
|
||||||
#define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory"
|
|
||||||
typedef struct VkImportMemoryZirconHandleInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkExternalMemoryHandleTypeFlagBits handleType;
|
|
||||||
zx_handle_t handle;
|
|
||||||
} VkImportMemoryZirconHandleInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkMemoryZirconHandlePropertiesFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint32_t memoryTypeBits;
|
|
||||||
} VkMemoryZirconHandlePropertiesFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkMemoryGetZirconHandleInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkDeviceMemory memory;
|
|
||||||
VkExternalMemoryHandleTypeFlagBits handleType;
|
|
||||||
} VkMemoryGetZirconHandleInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryZirconHandleFUCHSIA)(VkDevice device, const VkMemoryGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, zx_handle_t* pZirconHandle);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, zx_handle_t zirconHandle, VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandleFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
const VkMemoryGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo,
|
|
||||||
zx_handle_t* pZirconHandle);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandlePropertiesFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
VkExternalMemoryHandleTypeFlagBits handleType,
|
|
||||||
zx_handle_t zirconHandle,
|
|
||||||
VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_FUCHSIA_external_semaphore 1
|
|
||||||
#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
|
|
||||||
#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_FUCHSIA_external_semaphore"
|
|
||||||
typedef struct VkImportSemaphoreZirconHandleInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkSemaphore semaphore;
|
|
||||||
VkSemaphoreImportFlags flags;
|
|
||||||
VkExternalSemaphoreHandleTypeFlagBits handleType;
|
|
||||||
zx_handle_t zirconHandle;
|
|
||||||
} VkImportSemaphoreZirconHandleInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkSemaphoreGetZirconHandleInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkSemaphore semaphore;
|
|
||||||
VkExternalSemaphoreHandleTypeFlagBits handleType;
|
|
||||||
} VkSemaphoreGetZirconHandleInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreZirconHandleFUCHSIA)(VkDevice device, const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreZirconHandleFUCHSIA)(VkDevice device, const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, zx_handle_t* pZirconHandle);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreZirconHandleFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreZirconHandleFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo,
|
|
||||||
zx_handle_t* pZirconHandle);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_FUCHSIA_buffer_collection 1
|
|
||||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA)
|
|
||||||
#define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 2
|
|
||||||
#define VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME "VK_FUCHSIA_buffer_collection"
|
|
||||||
typedef VkFlags VkImageFormatConstraintsFlagsFUCHSIA;
|
|
||||||
|
|
||||||
typedef enum VkImageConstraintsInfoFlagBitsFUCHSIA {
|
|
||||||
VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA = 0x00000001,
|
|
||||||
VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA = 0x00000002,
|
|
||||||
VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA = 0x00000004,
|
|
||||||
VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA = 0x00000008,
|
|
||||||
VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA = 0x00000010,
|
|
||||||
VK_IMAGE_CONSTRAINTS_INFO_FLAG_BITS_MAX_ENUM_FUCHSIA = 0x7FFFFFFF
|
|
||||||
} VkImageConstraintsInfoFlagBitsFUCHSIA;
|
|
||||||
typedef VkFlags VkImageConstraintsInfoFlagsFUCHSIA;
|
|
||||||
typedef struct VkBufferCollectionCreateInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
zx_handle_t collectionToken;
|
|
||||||
} VkBufferCollectionCreateInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkImportMemoryBufferCollectionFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkBufferCollectionFUCHSIA collection;
|
|
||||||
uint32_t index;
|
|
||||||
} VkImportMemoryBufferCollectionFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkBufferCollectionImageCreateInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkBufferCollectionFUCHSIA collection;
|
|
||||||
uint32_t index;
|
|
||||||
} VkBufferCollectionImageCreateInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkBufferCollectionConstraintsInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t minBufferCount;
|
|
||||||
uint32_t maxBufferCount;
|
|
||||||
uint32_t minBufferCountForCamping;
|
|
||||||
uint32_t minBufferCountForDedicatedSlack;
|
|
||||||
uint32_t minBufferCountForSharedSlack;
|
|
||||||
} VkBufferCollectionConstraintsInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkBufferConstraintsInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkBufferCreateInfo createInfo;
|
|
||||||
VkFormatFeatureFlags requiredFormatFeatures;
|
|
||||||
VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints;
|
|
||||||
} VkBufferConstraintsInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkBufferCollectionBufferCreateInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkBufferCollectionFUCHSIA collection;
|
|
||||||
uint32_t index;
|
|
||||||
} VkBufferCollectionBufferCreateInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkSysmemColorSpaceFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t colorSpace;
|
|
||||||
} VkSysmemColorSpaceFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkBufferCollectionPropertiesFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint32_t memoryTypeBits;
|
|
||||||
uint32_t bufferCount;
|
|
||||||
uint32_t createInfoIndex;
|
|
||||||
uint64_t sysmemPixelFormat;
|
|
||||||
VkFormatFeatureFlags formatFeatures;
|
|
||||||
VkSysmemColorSpaceFUCHSIA sysmemColorSpaceIndex;
|
|
||||||
VkComponentMapping samplerYcbcrConversionComponents;
|
|
||||||
VkSamplerYcbcrModelConversion suggestedYcbcrModel;
|
|
||||||
VkSamplerYcbcrRange suggestedYcbcrRange;
|
|
||||||
VkChromaLocation suggestedXChromaOffset;
|
|
||||||
VkChromaLocation suggestedYChromaOffset;
|
|
||||||
} VkBufferCollectionPropertiesFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkImageFormatConstraintsInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkImageCreateInfo imageCreateInfo;
|
|
||||||
VkFormatFeatureFlags requiredFormatFeatures;
|
|
||||||
VkImageFormatConstraintsFlagsFUCHSIA flags;
|
|
||||||
uint64_t sysmemPixelFormat;
|
|
||||||
uint32_t colorSpaceCount;
|
|
||||||
const VkSysmemColorSpaceFUCHSIA* pColorSpaces;
|
|
||||||
} VkImageFormatConstraintsInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef struct VkImageConstraintsInfoFUCHSIA {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t formatConstraintsCount;
|
|
||||||
const VkImageFormatConstraintsInfoFUCHSIA* pFormatConstraints;
|
|
||||||
VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints;
|
|
||||||
VkImageConstraintsInfoFlagsFUCHSIA flags;
|
|
||||||
} VkImageConstraintsInfoFUCHSIA;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferCollectionFUCHSIA)(VkDevice device, const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferCollectionFUCHSIA* pCollection);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo);
|
|
||||||
typedef void (VKAPI_PTR *PFN_vkDestroyBufferCollectionFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkAllocationCallbacks* pAllocator);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetBufferCollectionPropertiesFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, VkBufferCollectionPropertiesFUCHSIA* pProperties);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferCollectionFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkBufferCollectionFUCHSIA* pCollection);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionImageConstraintsFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
VkBufferCollectionFUCHSIA collection,
|
|
||||||
const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionBufferConstraintsFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
VkBufferCollectionFUCHSIA collection,
|
|
||||||
const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo);
|
|
||||||
|
|
||||||
VKAPI_ATTR void VKAPI_CALL vkDestroyBufferCollectionFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
VkBufferCollectionFUCHSIA collection,
|
|
||||||
const VkAllocationCallbacks* pAllocator);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferCollectionPropertiesFUCHSIA(
|
|
||||||
VkDevice device,
|
|
||||||
VkBufferCollectionFUCHSIA collection,
|
|
||||||
VkBufferCollectionPropertiesFUCHSIA* pProperties);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,58 +0,0 @@
|
|||||||
#ifndef VULKAN_GGP_H_
|
|
||||||
#define VULKAN_GGP_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_GGP_stream_descriptor_surface 1
|
|
||||||
#define VK_GGP_STREAM_DESCRIPTOR_SURFACE_SPEC_VERSION 1
|
|
||||||
#define VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME "VK_GGP_stream_descriptor_surface"
|
|
||||||
typedef VkFlags VkStreamDescriptorSurfaceCreateFlagsGGP;
|
|
||||||
typedef struct VkStreamDescriptorSurfaceCreateInfoGGP {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkStreamDescriptorSurfaceCreateFlagsGGP flags;
|
|
||||||
GgpStreamDescriptor streamDescriptor;
|
|
||||||
} VkStreamDescriptorSurfaceCreateInfoGGP;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateStreamDescriptorSurfaceGGP)(VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateStreamDescriptorSurfaceGGP(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_GGP_frame_token 1
|
|
||||||
#define VK_GGP_FRAME_TOKEN_SPEC_VERSION 1
|
|
||||||
#define VK_GGP_FRAME_TOKEN_EXTENSION_NAME "VK_GGP_frame_token"
|
|
||||||
typedef struct VkPresentFrameTokenGGP {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
GgpFrameToken frameToken;
|
|
||||||
} VkPresentFrameTokenGGP;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,47 +0,0 @@
|
|||||||
#ifndef VULKAN_IOS_H_
|
|
||||||
#define VULKAN_IOS_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_MVK_ios_surface 1
|
|
||||||
#define VK_MVK_IOS_SURFACE_SPEC_VERSION 3
|
|
||||||
#define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
|
|
||||||
typedef VkFlags VkIOSSurfaceCreateFlagsMVK;
|
|
||||||
typedef struct VkIOSSurfaceCreateInfoMVK {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkIOSSurfaceCreateFlagsMVK flags;
|
|
||||||
const void* pView;
|
|
||||||
} VkIOSSurfaceCreateInfoMVK;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,47 +0,0 @@
|
|||||||
#ifndef VULKAN_MACOS_H_
|
|
||||||
#define VULKAN_MACOS_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_MVK_macos_surface 1
|
|
||||||
#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 3
|
|
||||||
#define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface"
|
|
||||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
|
||||||
typedef struct VkMacOSSurfaceCreateInfoMVK {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkMacOSSurfaceCreateFlagsMVK flags;
|
|
||||||
const void* pView;
|
|
||||||
} VkMacOSSurfaceCreateInfoMVK;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,54 +0,0 @@
|
|||||||
#ifndef VULKAN_METAL_H_
|
|
||||||
#define VULKAN_METAL_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_EXT_metal_surface 1
|
|
||||||
|
|
||||||
#ifdef __OBJC__
|
|
||||||
@class CAMetalLayer;
|
|
||||||
#else
|
|
||||||
typedef void CAMetalLayer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define VK_EXT_METAL_SURFACE_SPEC_VERSION 1
|
|
||||||
#define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface"
|
|
||||||
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
|
|
||||||
typedef struct VkMetalSurfaceCreateInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkMetalSurfaceCreateFlagsEXT flags;
|
|
||||||
const CAMetalLayer* pLayer;
|
|
||||||
} VkMetalSurfaceCreateInfoEXT;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateMetalSurfaceEXT)(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,47 +0,0 @@
|
|||||||
#ifndef VULKAN_VI_H_
|
|
||||||
#define VULKAN_VI_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_NN_vi_surface 1
|
|
||||||
#define VK_NN_VI_SURFACE_SPEC_VERSION 1
|
|
||||||
#define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface"
|
|
||||||
typedef VkFlags VkViSurfaceCreateFlagsNN;
|
|
||||||
typedef struct VkViSurfaceCreateInfoNN {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkViSurfaceCreateFlagsNN flags;
|
|
||||||
void* window;
|
|
||||||
} VkViSurfaceCreateInfoNN;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkViSurfaceCreateInfoNN* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,54 +0,0 @@
|
|||||||
#ifndef VULKAN_WAYLAND_H_
|
|
||||||
#define VULKAN_WAYLAND_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_wayland_surface 1
|
|
||||||
#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6
|
|
||||||
#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface"
|
|
||||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
|
||||||
typedef struct VkWaylandSurfaceCreateInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkWaylandSurfaceCreateFlagsKHR flags;
|
|
||||||
struct wl_display* display;
|
|
||||||
struct wl_surface* surface;
|
|
||||||
} VkWaylandSurfaceCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
uint32_t queueFamilyIndex,
|
|
||||||
struct wl_display* display);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,315 +0,0 @@
|
|||||||
#ifndef VULKAN_WIN32_H_
|
|
||||||
#define VULKAN_WIN32_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_win32_surface 1
|
|
||||||
#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6
|
|
||||||
#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface"
|
|
||||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
|
||||||
typedef struct VkWin32SurfaceCreateInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkWin32SurfaceCreateFlagsKHR flags;
|
|
||||||
HINSTANCE hinstance;
|
|
||||||
HWND hwnd;
|
|
||||||
} VkWin32SurfaceCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
uint32_t queueFamilyIndex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_external_memory_win32 1
|
|
||||||
#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
|
|
||||||
#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
|
|
||||||
typedef struct VkImportMemoryWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkExternalMemoryHandleTypeFlagBits handleType;
|
|
||||||
HANDLE handle;
|
|
||||||
LPCWSTR name;
|
|
||||||
} VkImportMemoryWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkExportMemoryWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const SECURITY_ATTRIBUTES* pAttributes;
|
|
||||||
DWORD dwAccess;
|
|
||||||
LPCWSTR name;
|
|
||||||
} VkExportMemoryWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkMemoryWin32HandlePropertiesKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
uint32_t memoryTypeBits;
|
|
||||||
} VkMemoryWin32HandlePropertiesKHR;
|
|
||||||
|
|
||||||
typedef struct VkMemoryGetWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkDeviceMemory memory;
|
|
||||||
VkExternalMemoryHandleTypeFlagBits handleType;
|
|
||||||
} VkMemoryGetWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR(
|
|
||||||
VkDevice device,
|
|
||||||
const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo,
|
|
||||||
HANDLE* pHandle);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR(
|
|
||||||
VkDevice device,
|
|
||||||
VkExternalMemoryHandleTypeFlagBits handleType,
|
|
||||||
HANDLE handle,
|
|
||||||
VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_win32_keyed_mutex 1
|
|
||||||
#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1
|
|
||||||
#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex"
|
|
||||||
typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t acquireCount;
|
|
||||||
const VkDeviceMemory* pAcquireSyncs;
|
|
||||||
const uint64_t* pAcquireKeys;
|
|
||||||
const uint32_t* pAcquireTimeouts;
|
|
||||||
uint32_t releaseCount;
|
|
||||||
const VkDeviceMemory* pReleaseSyncs;
|
|
||||||
const uint64_t* pReleaseKeys;
|
|
||||||
} VkWin32KeyedMutexAcquireReleaseInfoKHR;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_external_semaphore_win32 1
|
|
||||||
#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
|
|
||||||
#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
|
|
||||||
typedef struct VkImportSemaphoreWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkSemaphore semaphore;
|
|
||||||
VkSemaphoreImportFlags flags;
|
|
||||||
VkExternalSemaphoreHandleTypeFlagBits handleType;
|
|
||||||
HANDLE handle;
|
|
||||||
LPCWSTR name;
|
|
||||||
} VkImportSemaphoreWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkExportSemaphoreWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const SECURITY_ATTRIBUTES* pAttributes;
|
|
||||||
DWORD dwAccess;
|
|
||||||
LPCWSTR name;
|
|
||||||
} VkExportSemaphoreWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkD3D12FenceSubmitInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t waitSemaphoreValuesCount;
|
|
||||||
const uint64_t* pWaitSemaphoreValues;
|
|
||||||
uint32_t signalSemaphoreValuesCount;
|
|
||||||
const uint64_t* pSignalSemaphoreValues;
|
|
||||||
} VkD3D12FenceSubmitInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkSemaphoreGetWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkSemaphore semaphore;
|
|
||||||
VkExternalSemaphoreHandleTypeFlagBits handleType;
|
|
||||||
} VkSemaphoreGetWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR(
|
|
||||||
VkDevice device,
|
|
||||||
const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR(
|
|
||||||
VkDevice device,
|
|
||||||
const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo,
|
|
||||||
HANDLE* pHandle);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_external_fence_win32 1
|
|
||||||
#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1
|
|
||||||
#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
|
|
||||||
typedef struct VkImportFenceWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkFence fence;
|
|
||||||
VkFenceImportFlags flags;
|
|
||||||
VkExternalFenceHandleTypeFlagBits handleType;
|
|
||||||
HANDLE handle;
|
|
||||||
LPCWSTR name;
|
|
||||||
} VkImportFenceWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkExportFenceWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const SECURITY_ATTRIBUTES* pAttributes;
|
|
||||||
DWORD dwAccess;
|
|
||||||
LPCWSTR name;
|
|
||||||
} VkExportFenceWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef struct VkFenceGetWin32HandleInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkFence fence;
|
|
||||||
VkExternalFenceHandleTypeFlagBits handleType;
|
|
||||||
} VkFenceGetWin32HandleInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR(
|
|
||||||
VkDevice device,
|
|
||||||
const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR(
|
|
||||||
VkDevice device,
|
|
||||||
const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo,
|
|
||||||
HANDLE* pHandle);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_NV_external_memory_win32 1
|
|
||||||
#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
|
|
||||||
#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32"
|
|
||||||
typedef struct VkImportMemoryWin32HandleInfoNV {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkExternalMemoryHandleTypeFlagsNV handleType;
|
|
||||||
HANDLE handle;
|
|
||||||
} VkImportMemoryWin32HandleInfoNV;
|
|
||||||
|
|
||||||
typedef struct VkExportMemoryWin32HandleInfoNV {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
const SECURITY_ATTRIBUTES* pAttributes;
|
|
||||||
DWORD dwAccess;
|
|
||||||
} VkExportMemoryWin32HandleInfoNV;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV(
|
|
||||||
VkDevice device,
|
|
||||||
VkDeviceMemory memory,
|
|
||||||
VkExternalMemoryHandleTypeFlagsNV handleType,
|
|
||||||
HANDLE* pHandle);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_NV_win32_keyed_mutex 1
|
|
||||||
#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 2
|
|
||||||
#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex"
|
|
||||||
typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
uint32_t acquireCount;
|
|
||||||
const VkDeviceMemory* pAcquireSyncs;
|
|
||||||
const uint64_t* pAcquireKeys;
|
|
||||||
const uint32_t* pAcquireTimeoutMilliseconds;
|
|
||||||
uint32_t releaseCount;
|
|
||||||
const VkDeviceMemory* pReleaseSyncs;
|
|
||||||
const uint64_t* pReleaseKeys;
|
|
||||||
} VkWin32KeyedMutexAcquireReleaseInfoNV;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_EXT_full_screen_exclusive 1
|
|
||||||
#define VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION 4
|
|
||||||
#define VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME "VK_EXT_full_screen_exclusive"
|
|
||||||
|
|
||||||
typedef enum VkFullScreenExclusiveEXT {
|
|
||||||
VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT = 0,
|
|
||||||
VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT = 1,
|
|
||||||
VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT = 2,
|
|
||||||
VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT = 3,
|
|
||||||
VK_FULL_SCREEN_EXCLUSIVE_MAX_ENUM_EXT = 0x7FFFFFFF
|
|
||||||
} VkFullScreenExclusiveEXT;
|
|
||||||
typedef struct VkSurfaceFullScreenExclusiveInfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkFullScreenExclusiveEXT fullScreenExclusive;
|
|
||||||
} VkSurfaceFullScreenExclusiveInfoEXT;
|
|
||||||
|
|
||||||
typedef struct VkSurfaceCapabilitiesFullScreenExclusiveEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
void* pNext;
|
|
||||||
VkBool32 fullScreenExclusiveSupported;
|
|
||||||
} VkSurfaceCapabilitiesFullScreenExclusiveEXT;
|
|
||||||
|
|
||||||
typedef struct VkSurfaceFullScreenExclusiveWin32InfoEXT {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
HMONITOR hmonitor;
|
|
||||||
} VkSurfaceFullScreenExclusiveWin32InfoEXT;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkAcquireFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkReleaseFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModes2EXT)(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModes2EXT(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
|
|
||||||
uint32_t* pPresentModeCount,
|
|
||||||
VkPresentModeKHR* pPresentModes);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkAcquireFullScreenExclusiveModeEXT(
|
|
||||||
VkDevice device,
|
|
||||||
VkSwapchainKHR swapchain);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkReleaseFullScreenExclusiveModeEXT(
|
|
||||||
VkDevice device,
|
|
||||||
VkSwapchainKHR swapchain);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT(
|
|
||||||
VkDevice device,
|
|
||||||
const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
|
|
||||||
VkDeviceGroupPresentModeFlagsKHR* pModes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||||||
#ifndef VULKAN_XCB_H_
|
|
||||||
#define VULKAN_XCB_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_xcb_surface 1
|
|
||||||
#define VK_KHR_XCB_SURFACE_SPEC_VERSION 6
|
|
||||||
#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface"
|
|
||||||
typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
|
|
||||||
typedef struct VkXcbSurfaceCreateInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkXcbSurfaceCreateFlagsKHR flags;
|
|
||||||
xcb_connection_t* connection;
|
|
||||||
xcb_window_t window;
|
|
||||||
} VkXcbSurfaceCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
uint32_t queueFamilyIndex,
|
|
||||||
xcb_connection_t* connection,
|
|
||||||
xcb_visualid_t visual_id);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||||||
#ifndef VULKAN_XLIB_H_
|
|
||||||
#define VULKAN_XLIB_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_KHR_xlib_surface 1
|
|
||||||
#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6
|
|
||||||
#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
|
|
||||||
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
|
|
||||||
typedef struct VkXlibSurfaceCreateInfoKHR {
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkXlibSurfaceCreateFlagsKHR flags;
|
|
||||||
Display* dpy;
|
|
||||||
Window window;
|
|
||||||
} VkXlibSurfaceCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
|
|
||||||
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
|
|
||||||
VkInstance instance,
|
|
||||||
const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
|
|
||||||
const VkAllocationCallbacks* pAllocator,
|
|
||||||
VkSurfaceKHR* pSurface);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
uint32_t queueFamilyIndex,
|
|
||||||
Display* dpy,
|
|
||||||
VisualID visualID);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,45 +0,0 @@
|
|||||||
#ifndef VULKAN_XLIB_XRANDR_H_
|
|
||||||
#define VULKAN_XLIB_XRANDR_H_ 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2015-2021 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This header is generated from the Khronos Vulkan XML API Registry.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VK_EXT_acquire_xlib_display 1
|
|
||||||
#define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1
|
|
||||||
#define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display"
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display);
|
|
||||||
typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay);
|
|
||||||
|
|
||||||
#ifndef VK_NO_PROTOTYPES
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
Display* dpy,
|
|
||||||
VkDisplayKHR display);
|
|
||||||
|
|
||||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetRandROutputDisplayEXT(
|
|
||||||
VkPhysicalDevice physicalDevice,
|
|
||||||
Display* dpy,
|
|
||||||
RROutput rrOutput,
|
|
||||||
VkDisplayKHR* pDisplay);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
143
package_win.bat
143
package_win.bat
@ -1,87 +1,106 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
setlocal
|
set /a "MAX_THREADS=2"
|
||||||
pushd "%~dp0"
|
|
||||||
|
|
||||||
set /a last_code=0
|
|
||||||
|
|
||||||
set "build_base_dir=build\win"
|
|
||||||
set "out_dir=build\package\win"
|
|
||||||
|
|
||||||
set /a MEM_PERCENT=90
|
|
||||||
set /a DICT_SIZE_MB=384
|
|
||||||
set "packager=third-party\deps\win\7za\7za.exe"
|
|
||||||
|
|
||||||
:: use 70%
|
|
||||||
set /a THREAD_COUNT=2
|
|
||||||
if defined NUMBER_OF_PROCESSORS (
|
if defined NUMBER_OF_PROCESSORS (
|
||||||
set /a THREAD_COUNT=NUMBER_OF_PROCESSORS*70/100
|
:: use 70%
|
||||||
|
set /a "MAX_THREADS=%NUMBER_OF_PROCESSORS% * 70 / 100"
|
||||||
|
if %MAX_THREADS% lss 1 (
|
||||||
|
set /a "MAX_THREADS=1"
|
||||||
)
|
)
|
||||||
if %THREAD_COUNT% lss 2 (
|
|
||||||
set /a THREAD_COUNT=2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not exist "%packager%" (
|
set "BUILD_DIR=build\win"
|
||||||
1>&2 echo [X] packager app wasn't found
|
set "OUT_DIR=build\package\win"
|
||||||
set /a last_code=1
|
|
||||||
goto :script_end
|
if "%~1" equ "" (
|
||||||
|
1>&2 echo: missing build target folder arg
|
||||||
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%~1"=="" (
|
set "TARGET_DIR=%BUILD_DIR%\%~1"
|
||||||
1>&2 echo [X] missing build folder
|
if not exist "%TARGET_DIR%\" (
|
||||||
set /a last_code=1
|
1>&2 echo: build target folder wasn't found
|
||||||
goto :script_end
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
set "target_src_dir=%build_base_dir%\%~1"
|
set /a "BUILD_DEBUG=0"
|
||||||
if not exist "%target_src_dir%" (
|
if "%~2" equ "1" (
|
||||||
1>&2 echo [X] build folder wasn't found
|
set /a "BUILD_DEBUG=1"
|
||||||
set /a last_code=1
|
)
|
||||||
goto :script_end
|
|
||||||
|
set /a "PKG_EXE_MEM_PERCENT=90"
|
||||||
|
set /a "PKG_EXE_DICT_SIZE_MB=384"
|
||||||
|
set "PKG_EXE=third-party\deps\win\7za\7za.exe"
|
||||||
|
if not exist "%PKG_EXE%" (
|
||||||
|
1>&2 echo: packager wasn't found
|
||||||
|
goto :end_script_with_err
|
||||||
)
|
)
|
||||||
|
|
||||||
::::::::::::::::::::::::::::::::::::::::::
|
::::::::::::::::::::::::::::::::::::::::::
|
||||||
echo // copying readmes + example files
|
echo: // copying readmes + example files
|
||||||
xcopy /y /s /e /r "post_build\steam_settings.EXAMPLE\" "%target_src_dir%\steam_settings.EXAMPLE\"
|
|
||||||
copy /y "post_build\README.release.md" "%target_src_dir%\"
|
xcopy /y /s /e /r "post_build\steam_settings.EXAMPLE\" "%TARGET_DIR%\steam_settings.EXAMPLE\"
|
||||||
copy /y "CHANGELOG.md" "%target_src_dir%\"
|
|
||||||
copy /y "CREDITS.md" "%target_src_dir%\"
|
copy /y "post_build\README.release.md" "%TARGET_DIR%\"
|
||||||
if "%~2"=="1" (
|
copy /y "CHANGELOG.md" "%TARGET_DIR%\"
|
||||||
copy /y "post_build\README.debug.md" "%target_src_dir%\"
|
copy /y "CREDITS.md" "%TARGET_DIR%\"
|
||||||
|
|
||||||
|
if %BUILD_DEBUG% equ 1 (
|
||||||
|
copy /y "post_build\README.debug.md" "%TARGET_DIR%\"
|
||||||
)
|
)
|
||||||
if exist "%target_src_dir%\experimental\" (
|
|
||||||
copy /y "post_build\README.experimental.md" "%target_src_dir%\experimental\"
|
if exist "%TARGET_DIR%\experimental\" (
|
||||||
|
copy /y "post_build\README.experimental.md" "%TARGET_DIR%\experimental\"
|
||||||
)
|
)
|
||||||
if exist "%target_src_dir%\steamclient_experimental\" (
|
|
||||||
xcopy /y /s /e /r "post_build\win\ColdClientLoader.EXAMPLE\" "%target_src_dir%\steamclient_experimental\dll_injection.EXAMPLE\"
|
if exist "%TARGET_DIR%\steamclient_experimental\" (
|
||||||
copy /y "post_build\README.experimental_steamclient.md" "%target_src_dir%\steamclient_experimental\"
|
xcopy /y /s /e /r "post_build\win\ColdClientLoader.EXAMPLE\" "%TARGET_DIR%\steamclient_experimental\dll_injection.EXAMPLE\"
|
||||||
copy /y "tools\steamclient_loader\win\ColdClientLoader.ini" "%target_src_dir%\steamclient_experimental\"
|
copy /y "post_build\README.experimental_steamclient.md" "%TARGET_DIR%\steamclient_experimental\"
|
||||||
|
copy /y "tools\steamclient_loader\win\ColdClientLoader.ini" "%TARGET_DIR%\steamclient_experimental\"
|
||||||
)
|
)
|
||||||
if exist "%target_src_dir%\tools\generate_interfaces\" (
|
|
||||||
copy /y "post_build\README.generate_interfaces.md" "%target_src_dir%\tools\generate_interfaces\"
|
if exist "%TARGET_DIR%\tools\generate_interfaces\" (
|
||||||
|
copy /y "post_build\README.generate_interfaces.md" "%TARGET_DIR%\tools\generate_interfaces\"
|
||||||
)
|
)
|
||||||
if exist "%target_src_dir%\tools\lobby_connect\" (
|
|
||||||
copy /y "post_build\README.lobby_connect.md" "%target_src_dir%\tools\lobby_connect\"
|
if exist "%TARGET_DIR%\tools\lobby_connect\" (
|
||||||
|
copy /y "post_build\README.lobby_connect.md" "%TARGET_DIR%\tools\lobby_connect\"
|
||||||
)
|
)
|
||||||
::::::::::::::::::::::::::::::::::::::::::
|
::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
|
||||||
set "archive_dir=%out_dir%\%~1"
|
set "ACHIVE_DIR=%OUT_DIR%\%~1"
|
||||||
if exist "%archive_dir%\" (
|
if exist "%ACHIVE_DIR%\" (
|
||||||
rmdir /s /q "%archive_dir%"
|
rmdir /s /q "%ACHIVE_DIR%"
|
||||||
)
|
|
||||||
set "archive_file="
|
|
||||||
for %%A in ("%archive_dir%") do (
|
|
||||||
set "archive_file=%%~dpAemu-win-%%~nxA.7z"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for %%A in ("%archive_dir%") do (
|
for %%A in ("%ACHIVE_DIR%") do (
|
||||||
mkdir "%%~dpA"
|
md "%%~dpA"
|
||||||
)
|
)
|
||||||
"%packager%" a "%archive_file%" ".\%target_src_dir%" -t7z -slp -ssw -mx -myx -mmemuse=p%MEM_PERCENT% -ms=on -mqs=off -mf=on -mhc+ -mhe- -m0=LZMA2:d=%DICT_SIZE_MB%m -mmt=%THREAD_COUNT% -mmtf+ -mtm- -mtc- -mta- -mtr+
|
|
||||||
|
|
||||||
|
set "ACHIVE_FILE="
|
||||||
:script_end
|
for %%A in ("%ACHIVE_DIR%") do (
|
||||||
popd
|
set "ACHIVE_FILE=%%~dpAemu-win-%%~nxA.7z"
|
||||||
endlocal & (
|
|
||||||
exit /b %last_code%
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if exist "%ACHIVE_FILE%" (
|
||||||
|
del /f /s /q "%ACHIVE_FILE%"
|
||||||
|
)
|
||||||
|
|
||||||
|
call "%PKG_EXE%" a "%ACHIVE_FILE%" ".\%TARGET_DIR%" -t7z -xr^^!*.lib -xr^^!*.exp -slp -ssw -mx -myx -mmemuse=p%PKG_EXE_MEM_PERCENT% -ms=on -mqs=off -mf=on -mhc+ -mhe- -m0=LZMA2:d=%PKG_EXE_DICT_SIZE_MB%m -mmt=%MAX_THREADS% -mmtf+ -mtm- -mtc- -mta- -mtr+
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
goto :end_script_with_err
|
||||||
|
)
|
||||||
|
|
||||||
|
goto :end_script
|
||||||
|
|
||||||
|
:: exit without error
|
||||||
|
:end_script
|
||||||
|
endlocal
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:: exit with error
|
||||||
|
:end_script_with_err
|
||||||
|
endlocal
|
||||||
|
exit /b 1
|
||||||
|
@ -1 +1,3 @@
|
|||||||
package_win.bat vs2022\debug
|
@echo off
|
||||||
|
|
||||||
|
call "package_win.bat" vs2022/debug 1
|
||||||
|
@ -1 +1,3 @@
|
|||||||
package_win.bat vs2022\release
|
@echo off
|
||||||
|
|
||||||
|
call "package_win.bat" vs2022/release
|
||||||
|
@ -15,6 +15,26 @@ steam_deck=0
|
|||||||
# 1=enable avatar functionality
|
# 1=enable avatar functionality
|
||||||
# default=0
|
# default=0
|
||||||
enable_account_avatar=0
|
enable_account_avatar=0
|
||||||
|
# 1=synchronize user stats/achievements with game servers as soon as possible instead of caching them until the next call to `Steam_RunCallbacks()`
|
||||||
|
# not recommended to enable this
|
||||||
|
# default=0
|
||||||
|
immediate_gameserver_stats=0
|
||||||
|
# 1=use the proper type of the server list (internet, friends, etc...) when requested by the game
|
||||||
|
# 0=always return the type of the server list as "LAN server"
|
||||||
|
# not recommended to enable this
|
||||||
|
# default=0
|
||||||
|
matchmaking_server_list_actual_type=0
|
||||||
|
# 1=grab the server details for match making using an actual server query
|
||||||
|
# 0=use the info from the local network messages shared between client/server
|
||||||
|
# not recommended to enable this, currently breaks some games
|
||||||
|
# default=0
|
||||||
|
matchmaking_server_details_via_source_query=0
|
||||||
|
# very basic crash logger/printer
|
||||||
|
# this is intended to debug some annoying scenarios, and best used with the debug build of the emu
|
||||||
|
# default=
|
||||||
|
crash_printer_location=./path/relative/to/dll/crashes.txt
|
||||||
|
|
||||||
|
[main::stats]
|
||||||
# 1=prevent 'Steam_User_Stats::FindLeaderboard()' from always succeeding and creating the unknown leaderboard
|
# 1=prevent 'Steam_User_Stats::FindLeaderboard()' from always succeeding and creating the unknown leaderboard
|
||||||
# not recommended to enable this
|
# not recommended to enable this
|
||||||
# default=0
|
# default=0
|
||||||
@ -39,24 +59,12 @@ stat_achievement_progress_functionality=1
|
|||||||
# also has no impact on the functions which directly change stats, achievements, or achievements progress
|
# also has no impact on the functions which directly change stats, achievements, or achievements progress
|
||||||
# default=1
|
# default=1
|
||||||
save_only_higher_stat_achievement_progress=1
|
save_only_higher_stat_achievement_progress=1
|
||||||
# 1=synchronize user stats/achievements with game servers as soon as possible instead of caching them until the next call to 'Steam_RunCallbacks()'
|
# the emulator loads the achievements icons is memory, this is needed for APIs like `ISteamUserStats::GetAchievementIcon()`
|
||||||
# not recommended to enable this
|
# the loaded icon size is controlled by [overlay::appearance] -> Icon_Size, in configs.overlay.ini
|
||||||
# default=0
|
# 1=load icons lazily when they are requested
|
||||||
immediate_gameserver_stats=0
|
# 0=load icons as soon as the interface 'ISteamUserStats' is initialized
|
||||||
# 1=use the proper type of the server list (internet, friends, etc...) when requested by the game
|
# default=1
|
||||||
# 0=always return the type of the server list as 'LAN server'
|
lazy_load_achievements_icons=1
|
||||||
# not recommended to enable this
|
|
||||||
# default=0
|
|
||||||
matchmaking_server_list_actual_type=0
|
|
||||||
# 1=grab the server details for match making using an actual server query
|
|
||||||
# 0=use the info from the local network messages shared between client/server
|
|
||||||
# not recommended to enable this, currently breaks some games
|
|
||||||
# default=0
|
|
||||||
matchmaking_server_details_via_source_query=0
|
|
||||||
# very basic crash logger/printer
|
|
||||||
# this is intended to debug some annoying scenarios, and best used with the debug build of the emu
|
|
||||||
# default=
|
|
||||||
crash_printer_location=./path/relative/to/dll/crashes.txt
|
|
||||||
|
|
||||||
[main::connectivity]
|
[main::connectivity]
|
||||||
# 1=prevent hooking OS networking APIs and allow any external requests
|
# 1=prevent hooking OS networking APIs and allow any external requests
|
||||||
@ -118,3 +126,9 @@ disable_steamoverlaygameid_env_var=0
|
|||||||
# https://developer.valvesoftware.com/wiki/Dedicated_Servers_List
|
# https://developer.valvesoftware.com/wiki/Dedicated_Servers_List
|
||||||
# default=0
|
# default=0
|
||||||
enable_steam_preowned_ids=0
|
enable_steam_preowned_ids=0
|
||||||
|
# some Source-based games use the interface `ISteamGameStats` to report some stats
|
||||||
|
# you can make the emu save this data to a folder
|
||||||
|
# empty value = don't save anything (default)
|
||||||
|
# the emu will create the folders if they are missing but the path specified must be writable
|
||||||
|
# default=
|
||||||
|
steam_game_stats_reports_dir=./path/relative/to/dll/
|
||||||
|
@ -498,23 +498,41 @@ end
|
|||||||
-- https://github.com/Kitware/CMake/blob/a6853135f569f0b040a34374a15a8361bb73901b/Modules/FindZLIB.cmake#L98C4-L98C13
|
-- https://github.com/Kitware/CMake/blob/a6853135f569f0b040a34374a15a8361bb73901b/Modules/FindZLIB.cmake#L98C4-L98C13
|
||||||
|
|
||||||
local zlib_name = ''
|
local zlib_name = ''
|
||||||
|
local mbedtls_name = ''
|
||||||
|
local mbedcrypto_name = ''
|
||||||
|
local mbedx509_name = ''
|
||||||
-- name
|
-- name
|
||||||
if _ACTION and os.target() == 'windows' then
|
if _ACTION and os.target() == 'windows' then
|
||||||
if string.match(_ACTION, 'vs.+') then
|
if string.match(_ACTION, 'vs.+') then
|
||||||
zlib_name = 'zlibstatic'
|
zlib_name = 'zlibstatic'
|
||||||
|
mbedtls_name = 'mbedtls'
|
||||||
|
mbedcrypto_name = 'mbedcrypto'
|
||||||
|
mbedx509_name = 'mbedx509'
|
||||||
elseif string.match(_ACTION, 'gmake.*') then
|
elseif string.match(_ACTION, 'gmake.*') then
|
||||||
zlib_name = 'libzlibstatic'
|
zlib_name = 'libzlibstatic'
|
||||||
|
mbedtls_name = 'libmbedtls'
|
||||||
|
mbedcrypto_name = 'libmbedcrypto'
|
||||||
|
mbedx509_name = 'libmbedx509'
|
||||||
else
|
else
|
||||||
error('unsupported os/action: ' .. os.target() .. ' / ' .. _ACTION)
|
error('unsupported os/action: ' .. os.target() .. ' / ' .. _ACTION)
|
||||||
end
|
end
|
||||||
else -- linux or macos
|
else -- linux or macos
|
||||||
zlib_name = 'libz'
|
zlib_name = 'libz'
|
||||||
|
mbedtls_name = 'libmbedtls'
|
||||||
|
mbedcrypto_name = 'libmbedcrypto'
|
||||||
|
mbedx509_name = 'mbedx509'
|
||||||
end
|
end
|
||||||
-- extension
|
-- extension
|
||||||
if _ACTION and string.match(_ACTION, 'vs.+') then
|
if _ACTION and string.match(_ACTION, 'vs.+') then
|
||||||
zlib_name = zlib_name .. '.lib'
|
zlib_name = zlib_name .. '.lib'
|
||||||
|
mbedtls_name = mbedtls_name .. '.lib'
|
||||||
|
mbedcrypto_name = mbedcrypto_name .. '.lib'
|
||||||
|
mbedx509_name = mbedx509_name .. '.lib'
|
||||||
else
|
else
|
||||||
zlib_name = zlib_name .. '.a'
|
zlib_name = zlib_name .. '.a'
|
||||||
|
mbedtls_name = mbedtls_name .. '.a'
|
||||||
|
mbedcrypto_name = mbedcrypto_name .. '.a'
|
||||||
|
mbedx509_name = mbedx509_name .. '.a'
|
||||||
end
|
end
|
||||||
|
|
||||||
local wild_zlib_path_32 = path.join(deps_dir, 'zlib', 'install32', 'lib', zlib_name)
|
local wild_zlib_path_32 = path.join(deps_dir, 'zlib', 'install32', 'lib', zlib_name)
|
||||||
@ -532,18 +550,55 @@ local wild_zlib_64 = {
|
|||||||
'ZLIB_LIBRARY="' .. wild_zlib_path_64 .. '"',
|
'ZLIB_LIBRARY="' .. wild_zlib_path_64 .. '"',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _OPTIONS["build-mbedtls"] or _OPTIONS["all-build"] then
|
||||||
|
local mbedtls_common_defs = {
|
||||||
|
"USE_STATIC_MBEDTLS_LIBRARY=ON",
|
||||||
|
"USE_SHARED_MBEDTLS_LIBRARY=OFF",
|
||||||
|
"ENABLE_TESTING=OFF",
|
||||||
|
"ENABLE_PROGRAMS=OFF",
|
||||||
|
"MBEDTLS_FATAL_WARNINGS=OFF",
|
||||||
|
}
|
||||||
|
if os.target() == 'windows' and string.match(_ACTION, 'vs.+') then
|
||||||
|
table.insert(mbedtls_common_defs, "MSVC_STATIC_RUNTIME=ON")
|
||||||
|
else -- linux or macos or MinGW on Windows
|
||||||
|
table.insert(mbedtls_common_defs, "LINK_WITH_PTHREAD=ON")
|
||||||
|
end
|
||||||
|
|
||||||
|
local mbedtls_32_bit_fixes = {}
|
||||||
|
if _OPTIONS["32-build"] and string.match(_ACTION, 'gmake.*') then
|
||||||
|
table.insert(mbedtls_32_bit_fixes, '-mpclmul')
|
||||||
|
table.insert(mbedtls_32_bit_fixes, '-msse2')
|
||||||
|
table.insert(mbedtls_32_bit_fixes, '-maes')
|
||||||
|
end
|
||||||
|
|
||||||
|
if _OPTIONS["32-build"] then
|
||||||
|
cmake_build('mbedtls', true, mbedtls_common_defs, mbedtls_32_bit_fixes)
|
||||||
|
end
|
||||||
|
if _OPTIONS["64-build"] then
|
||||||
|
cmake_build('mbedtls', false, mbedtls_common_defs)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if _OPTIONS["build-curl"] or _OPTIONS["all-build"] then
|
if _OPTIONS["build-curl"] or _OPTIONS["all-build"] then
|
||||||
local curl_common_defs = {
|
local curl_common_defs = {
|
||||||
"BUILD_CURL_EXE=OFF",
|
"BUILD_CURL_EXE=OFF",
|
||||||
"BUILD_SHARED_LIBS=OFF",
|
|
||||||
"BUILD_STATIC_CURL=OFF", -- "Build curl executable with static libcurl"
|
"BUILD_STATIC_CURL=OFF", -- "Build curl executable with static libcurl"
|
||||||
|
|
||||||
|
"BUILD_SHARED_LIBS=OFF",
|
||||||
"BUILD_STATIC_LIBS=ON",
|
"BUILD_STATIC_LIBS=ON",
|
||||||
"BUILD_MISC_DOCS=OFF",
|
"BUILD_MISC_DOCS=OFF",
|
||||||
"BUILD_TESTING=OFF",
|
"BUILD_TESTING=OFF",
|
||||||
"BUILD_LIBCURL_DOCS=OFF",
|
"BUILD_LIBCURL_DOCS=OFF",
|
||||||
"ENABLE_CURL_MANUAL=OFF",
|
"ENABLE_CURL_MANUAL=OFF",
|
||||||
|
|
||||||
"CURL_USE_OPENSSL=OFF",
|
"CURL_USE_OPENSSL=OFF",
|
||||||
"CURL_ZLIB=ON",
|
"CURL_ZLIB=ON",
|
||||||
|
|
||||||
|
"CURL_USE_MBEDTLS=ON",
|
||||||
|
-- "CURL_USE_SCHANNEL=ON",
|
||||||
|
"CURL_CA_FALLBACK=ON",
|
||||||
|
|
||||||
|
-- fix building on Arch Linux
|
||||||
"CURL_USE_LIBSSH2=OFF",
|
"CURL_USE_LIBSSH2=OFF",
|
||||||
"CURL_USE_LIBPSL=OFF",
|
"CURL_USE_LIBPSL=OFF",
|
||||||
"USE_LIBIDN2=OFF",
|
"USE_LIBIDN2=OFF",
|
||||||
@ -555,10 +610,20 @@ if _OPTIONS["build-curl"] or _OPTIONS["all-build"] then
|
|||||||
end
|
end
|
||||||
|
|
||||||
if _OPTIONS["32-build"] then
|
if _OPTIONS["32-build"] then
|
||||||
cmake_build('curl', true, merge_list(curl_common_defs, wild_zlib_32))
|
cmake_build('curl', true, merge_list(curl_common_defs, merge_list(wild_zlib_32, {
|
||||||
|
'MBEDTLS_INCLUDE_DIRS="' .. path.join(deps_dir, 'mbedtls', 'install32', 'include') .. '"',
|
||||||
|
'MBEDTLS_LIBRARY="' .. path.join(deps_dir, 'mbedtls', 'install32', 'lib', mbedtls_name) .. '"',
|
||||||
|
'MBEDCRYPTO_LIBRARY="' .. path.join(deps_dir, 'mbedtls', 'install32', 'lib', mbedcrypto_name) .. '"',
|
||||||
|
'MBEDX509_LIBRARY="' .. path.join(deps_dir, 'mbedtls', 'install32', 'lib', mbedx509_name) .. '"',
|
||||||
|
})))
|
||||||
end
|
end
|
||||||
if _OPTIONS["64-build"] then
|
if _OPTIONS["64-build"] then
|
||||||
cmake_build('curl', false, merge_list(curl_common_defs, wild_zlib_64))
|
cmake_build('curl', false, merge_list(curl_common_defs, merge_list(wild_zlib_64, {
|
||||||
|
'MBEDTLS_INCLUDE_DIRS="' .. path.join(deps_dir, 'mbedtls', 'install64', 'include') .. '"',
|
||||||
|
'MBEDTLS_LIBRARY="' .. path.join(deps_dir, 'mbedtls', 'install64', 'lib', mbedtls_name) .. '"',
|
||||||
|
'MBEDCRYPTO_LIBRARY="' .. path.join(deps_dir, 'mbedtls', 'install64', 'lib', mbedcrypto_name) .. '"',
|
||||||
|
'MBEDX509_LIBRARY="' .. path.join(deps_dir, 'mbedtls', 'install64', 'lib', mbedx509_name) .. '"',
|
||||||
|
})))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -588,32 +653,6 @@ if _OPTIONS["build-protobuf"] or _OPTIONS["all-build"] then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if _OPTIONS["build-mbedtls"] or _OPTIONS["all-build"] then
|
|
||||||
local mbedtls_common_defs = {
|
|
||||||
"USE_STATIC_MBEDTLS_LIBRARY=ON",
|
|
||||||
"USE_SHARED_MBEDTLS_LIBRARY=OFF",
|
|
||||||
"ENABLE_TESTING=OFF",
|
|
||||||
"ENABLE_PROGRAMS=OFF",
|
|
||||||
"MBEDTLS_FATAL_WARNINGS=OFF",
|
|
||||||
}
|
|
||||||
if os.target() == 'windows' and string.match(_ACTION, 'vs.+') then
|
|
||||||
table.insert(mbedtls_common_defs, "MSVC_STATIC_RUNTIME=ON")
|
|
||||||
else -- linux or macos or MinGW on Windows
|
|
||||||
table.insert(mbedtls_common_defs, "LINK_WITH_PTHREAD=ON")
|
|
||||||
end
|
|
||||||
|
|
||||||
if _OPTIONS["32-build"] then
|
|
||||||
cmake_build('mbedtls', true, mbedtls_common_defs, {
|
|
||||||
'-mpclmul',
|
|
||||||
'-msse2',
|
|
||||||
'-maes',
|
|
||||||
})
|
|
||||||
end
|
|
||||||
if _OPTIONS["64-build"] then
|
|
||||||
cmake_build('mbedtls', false, mbedtls_common_defs)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if _OPTIONS["build-ingame_overlay"] or _OPTIONS["all-build"] then
|
if _OPTIONS["build-ingame_overlay"] or _OPTIONS["all-build"] then
|
||||||
-- fixes 32-bit compilation of DX12
|
-- fixes 32-bit compilation of DX12
|
||||||
local overaly_imgui_cfg_file = path.join(deps_dir, 'ingame_overlay', 'imconfig.imcfg')
|
local overaly_imgui_cfg_file = path.join(deps_dir, 'ingame_overlay', 'imconfig.imcfg')
|
||||||
|
@ -273,6 +273,8 @@ local deps_link = {
|
|||||||
zlib_archive_name .. static_postfix,
|
zlib_archive_name .. static_postfix,
|
||||||
lib_prefix .. "curl" .. static_postfix,
|
lib_prefix .. "curl" .. static_postfix,
|
||||||
"mbedcrypto" .. static_postfix,
|
"mbedcrypto" .. static_postfix,
|
||||||
|
"mbedtls" .. static_postfix,
|
||||||
|
"mbedx509" .. static_postfix,
|
||||||
}
|
}
|
||||||
-- add protobuf libs
|
-- add protobuf libs
|
||||||
table_append(deps_link, {
|
table_append(deps_link, {
|
||||||
|
804
sdk/steam/isteamnetworkingsockets010.h
Normal file
804
sdk/steam/isteamnetworkingsockets010.h
Normal file
@ -0,0 +1,804 @@
|
|||||||
|
|
||||||
|
#ifndef ISTEAMNETWORKINGSOCKETS010
|
||||||
|
#define ISTEAMNETWORKINGSOCKETS010
|
||||||
|
|
||||||
|
// this interface version is not found in public SDK archives, it is based on reversing the returned vftable from steamclient64.dll
|
||||||
|
|
||||||
|
class ISteamNetworkingSockets010
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Creates a "server" socket that listens for clients to connect to by
|
||||||
|
/// calling ConnectByIPAddress, over ordinary UDP (IPv4 or IPv6)
|
||||||
|
///
|
||||||
|
/// You must select a specific local port to listen on and set it
|
||||||
|
/// the port field of the local address.
|
||||||
|
///
|
||||||
|
/// Usually you will set the IP portion of the address to zero (SteamNetworkingIPAddr::Clear()).
|
||||||
|
/// This means that you will not bind to any particular local interface (i.e. the same
|
||||||
|
/// as INADDR_ANY in plain socket code). Furthermore, if possible the socket will be bound
|
||||||
|
/// in "dual stack" mode, which means that it can accept both IPv4 and IPv6 client connections.
|
||||||
|
/// If you really do wish to bind a particular interface, then set the local address to the
|
||||||
|
/// appropriate IPv4 or IPv6 IP.
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
///
|
||||||
|
/// When a client attempts to connect, a SteamNetConnectionStatusChangedCallback_t
|
||||||
|
/// will be posted. The connection will be in the connecting state.
|
||||||
|
virtual HSteamListenSocket CreateListenSocketIP( const SteamNetworkingIPAddr &localAddress, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Creates a connection and begins talking to a "server" over UDP at the
|
||||||
|
/// given IPv4 or IPv6 address. The remote host must be listening with a
|
||||||
|
/// matching call to CreateListenSocketIP on the specified port.
|
||||||
|
///
|
||||||
|
/// A SteamNetConnectionStatusChangedCallback_t callback will be triggered when we start
|
||||||
|
/// connecting, and then another one on either timeout or successful connection.
|
||||||
|
///
|
||||||
|
/// If the server does not have any identity configured, then their network address
|
||||||
|
/// will be the only identity in use. Or, the network host may provide a platform-specific
|
||||||
|
/// identity with or without a valid certificate to authenticate that identity. (These
|
||||||
|
/// details will be contained in the SteamNetConnectionStatusChangedCallback_t.) It's
|
||||||
|
/// up to your application to decide whether to allow the connection.
|
||||||
|
///
|
||||||
|
/// By default, all connections will get basic encryption sufficient to prevent
|
||||||
|
/// casual eavesdropping. But note that without certificates (or a shared secret
|
||||||
|
/// distributed through some other out-of-band mechanism), you don't have any
|
||||||
|
/// way of knowing who is actually on the other end, and thus are vulnerable to
|
||||||
|
/// man-in-the-middle attacks.
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
virtual HSteamNetConnection ConnectByIPAddress( const SteamNetworkingIPAddr &address, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Like CreateListenSocketIP, but clients will connect using ConnectP2P.
|
||||||
|
///
|
||||||
|
/// nLocalVirtualPort specifies how clients can connect to this socket using
|
||||||
|
/// ConnectP2P. It's very common for applications to only have one listening socket;
|
||||||
|
/// in that case, use zero. If you need to open multiple listen sockets and have clients
|
||||||
|
/// be able to connect to one or the other, then nLocalVirtualPort should be a small
|
||||||
|
/// integer (<1000) unique to each listen socket you create.
|
||||||
|
///
|
||||||
|
/// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
|
||||||
|
/// when your app initializes.
|
||||||
|
///
|
||||||
|
/// If you are listening on a dedicated servers in known data center,
|
||||||
|
/// then you can listen using this function instead of CreateHostedDedicatedServerListenSocket,
|
||||||
|
/// to allow clients to connect without a ticket. Any user that owns
|
||||||
|
/// the app and is signed into Steam will be able to attempt to connect to
|
||||||
|
/// your server. Also, a connection attempt may require the client to
|
||||||
|
/// be connected to Steam, which is one more moving part that may fail. When
|
||||||
|
/// tickets are used, then once a ticket is obtained, a client can connect to
|
||||||
|
/// your server even if they got disconnected from Steam or Steam is offline.
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
virtual HSteamListenSocket CreateListenSocketP2P( int nLocalVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Begin connecting to a peer that is identified using a platform-specific identifier.
|
||||||
|
/// This uses the default rendezvous service, which depends on the platform and library
|
||||||
|
/// configuration. (E.g. on Steam, it goes through the steam backend.)
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
///
|
||||||
|
/// To use your own signaling service, see:
|
||||||
|
/// - ConnectP2PCustomSignaling
|
||||||
|
/// - k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling
|
||||||
|
virtual HSteamNetConnection ConnectP2P( const SteamNetworkingIdentity &identityRemote, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Accept an incoming connection that has been received on a listen socket.
|
||||||
|
///
|
||||||
|
/// When a connection attempt is received (perhaps after a few basic handshake
|
||||||
|
/// packets have been exchanged to prevent trivial spoofing), a connection interface
|
||||||
|
/// object is created in the k_ESteamNetworkingConnectionState_Connecting state
|
||||||
|
/// and a SteamNetConnectionStatusChangedCallback_t is posted. At this point, your
|
||||||
|
/// application MUST either accept or close the connection. (It may not ignore it.)
|
||||||
|
/// Accepting the connection will transition it either into the connected state,
|
||||||
|
/// or the finding route state, depending on the connection type.
|
||||||
|
///
|
||||||
|
/// You should take action within a second or two, because accepting the connection is
|
||||||
|
/// what actually sends the reply notifying the client that they are connected. If you
|
||||||
|
/// delay taking action, from the client's perspective it is the same as the network
|
||||||
|
/// being unresponsive, and the client may timeout the connection attempt. In other
|
||||||
|
/// words, the client cannot distinguish between a delay caused by network problems
|
||||||
|
/// and a delay caused by the application.
|
||||||
|
///
|
||||||
|
/// This means that if your application goes for more than a few seconds without
|
||||||
|
/// processing callbacks (for example, while loading a map), then there is a chance
|
||||||
|
/// that a client may attempt to connect in that interval and fail due to timeout.
|
||||||
|
///
|
||||||
|
/// If the application does not respond to the connection attempt in a timely manner,
|
||||||
|
/// and we stop receiving communication from the client, the connection attempt will
|
||||||
|
/// be timed out locally, transitioning the connection to the
|
||||||
|
/// k_ESteamNetworkingConnectionState_ProblemDetectedLocally state. The client may also
|
||||||
|
/// close the connection before it is accepted, and a transition to the
|
||||||
|
/// k_ESteamNetworkingConnectionState_ClosedByPeer is also possible depending the exact
|
||||||
|
/// sequence of events.
|
||||||
|
///
|
||||||
|
/// Returns k_EResultInvalidParam if the handle is invalid.
|
||||||
|
/// Returns k_EResultInvalidState if the connection is not in the appropriate state.
|
||||||
|
/// (Remember that the connection state could change in between the time that the
|
||||||
|
/// notification being posted to the queue and when it is received by the application.)
|
||||||
|
///
|
||||||
|
/// A note about connection configuration options. If you need to set any configuration
|
||||||
|
/// options that are common to all connections accepted through a particular listen
|
||||||
|
/// socket, consider setting the options on the listen socket, since such options are
|
||||||
|
/// inherited automatically. If you really do need to set options that are connection
|
||||||
|
/// specific, it is safe to set them on the connection before accepting the connection.
|
||||||
|
virtual EResult AcceptConnection( HSteamNetConnection hConn ) = 0;
|
||||||
|
|
||||||
|
/// Disconnects from the remote host and invalidates the connection handle.
|
||||||
|
/// Any unread data on the connection is discarded.
|
||||||
|
///
|
||||||
|
/// nReason is an application defined code that will be received on the other
|
||||||
|
/// end and recorded (when possible) in backend analytics. The value should
|
||||||
|
/// come from a restricted range. (See ESteamNetConnectionEnd.) If you don't need
|
||||||
|
/// to communicate any information to the remote host, and do not want analytics to
|
||||||
|
/// be able to distinguish "normal" connection terminations from "exceptional" ones,
|
||||||
|
/// You may pass zero, in which case the generic value of
|
||||||
|
/// k_ESteamNetConnectionEnd_App_Generic will be used.
|
||||||
|
///
|
||||||
|
/// pszDebug is an optional human-readable diagnostic string that will be received
|
||||||
|
/// by the remote host and recorded (when possible) in backend analytics.
|
||||||
|
///
|
||||||
|
/// If you wish to put the socket into a "linger" state, where an attempt is made to
|
||||||
|
/// flush any remaining sent data, use bEnableLinger=true. Otherwise reliable data
|
||||||
|
/// is not flushed.
|
||||||
|
///
|
||||||
|
/// If the connection has already ended and you are just freeing up the
|
||||||
|
/// connection interface, the reason code, debug string, and linger flag are
|
||||||
|
/// ignored.
|
||||||
|
virtual bool CloseConnection( HSteamNetConnection hPeer, int nReason, const char *pszDebug, bool bEnableLinger ) = 0;
|
||||||
|
|
||||||
|
/// Destroy a listen socket. All the connections that were accepting on the listen
|
||||||
|
/// socket are closed ungracefully.
|
||||||
|
virtual bool CloseListenSocket( HSteamListenSocket hSocket ) = 0;
|
||||||
|
|
||||||
|
/// Set connection user data. the data is returned in the following places
|
||||||
|
/// - You can query it using GetConnectionUserData.
|
||||||
|
/// - The SteamNetworkingmessage_t structure.
|
||||||
|
/// - The SteamNetConnectionInfo_t structure.
|
||||||
|
/// (Which is a member of SteamNetConnectionStatusChangedCallback_t -- but see WARNINGS below!!!!)
|
||||||
|
///
|
||||||
|
/// Do you need to set this atomically when the connection is created?
|
||||||
|
/// See k_ESteamNetworkingConfig_ConnectionUserData.
|
||||||
|
///
|
||||||
|
/// WARNING: Be *very careful* when using the value provided in callbacks structs.
|
||||||
|
/// Callbacks are queued, and the value that you will receive in your
|
||||||
|
/// callback is the userdata that was effective at the time the callback
|
||||||
|
/// was queued. There are subtle race conditions that can happen if you
|
||||||
|
/// don't understand this!
|
||||||
|
///
|
||||||
|
/// If any incoming messages for this connection are queued, the userdata
|
||||||
|
/// field is updated, so that when when you receive messages (e.g. with
|
||||||
|
/// ReceiveMessagesOnConnection), they will always have the very latest
|
||||||
|
/// userdata. So the tricky race conditions that can happen with callbacks
|
||||||
|
/// do not apply to retrieving messages.
|
||||||
|
///
|
||||||
|
/// Returns false if the handle is invalid.
|
||||||
|
virtual bool SetConnectionUserData( HSteamNetConnection hPeer, int64 nUserData ) = 0;
|
||||||
|
|
||||||
|
/// Fetch connection user data. Returns -1 if handle is invalid
|
||||||
|
/// or if you haven't set any userdata on the connection.
|
||||||
|
virtual int64 GetConnectionUserData( HSteamNetConnection hPeer ) = 0;
|
||||||
|
|
||||||
|
/// Set a name for the connection, used mostly for debugging
|
||||||
|
virtual void SetConnectionName( HSteamNetConnection hPeer, const char *pszName ) = 0;
|
||||||
|
|
||||||
|
/// Fetch connection name. Returns false if handle is invalid
|
||||||
|
virtual bool GetConnectionName( HSteamNetConnection hPeer, char *pszName, int nMaxLen ) = 0;
|
||||||
|
|
||||||
|
/// Send a message to the remote host on the specified connection.
|
||||||
|
///
|
||||||
|
/// nSendFlags determines the delivery guarantees that will be provided,
|
||||||
|
/// when data should be buffered, etc. E.g. k_nSteamNetworkingSend_Unreliable
|
||||||
|
///
|
||||||
|
/// Note that the semantics we use for messages are not precisely
|
||||||
|
/// the same as the semantics of a standard "stream" socket.
|
||||||
|
/// (SOCK_STREAM) For an ordinary stream socket, the boundaries
|
||||||
|
/// between chunks are not considered relevant, and the sizes of
|
||||||
|
/// the chunks of data written will not necessarily match up to
|
||||||
|
/// the sizes of the chunks that are returned by the reads on
|
||||||
|
/// the other end. The remote host might read a partial chunk,
|
||||||
|
/// or chunks might be coalesced. For the message semantics
|
||||||
|
/// used here, however, the sizes WILL match. Each send call
|
||||||
|
/// will match a successful read call on the remote host
|
||||||
|
/// one-for-one. If you are porting existing stream-oriented
|
||||||
|
/// code to the semantics of reliable messages, your code should
|
||||||
|
/// work the same, since reliable message semantics are more
|
||||||
|
/// strict than stream semantics. The only caveat is related to
|
||||||
|
/// performance: there is per-message overhead to retain the
|
||||||
|
/// message sizes, and so if your code sends many small chunks
|
||||||
|
/// of data, performance will suffer. Any code based on stream
|
||||||
|
/// sockets that does not write excessively small chunks will
|
||||||
|
/// work without any changes.
|
||||||
|
///
|
||||||
|
/// The pOutMessageNumber is an optional pointer to receive the
|
||||||
|
/// message number assigned to the message, if sending was successful.
|
||||||
|
///
|
||||||
|
/// Returns:
|
||||||
|
/// - k_EResultInvalidParam: invalid connection handle, or the individual message is too big.
|
||||||
|
/// (See k_cbMaxSteamNetworkingSocketsMessageSizeSend)
|
||||||
|
/// - k_EResultInvalidState: connection is in an invalid state
|
||||||
|
/// - k_EResultNoConnection: connection has ended
|
||||||
|
/// - k_EResultIgnored: You used k_nSteamNetworkingSend_NoDelay, and the message was dropped because
|
||||||
|
/// we were not ready to send it.
|
||||||
|
/// - k_EResultLimitExceeded: there was already too much data queued to be sent.
|
||||||
|
/// (See k_ESteamNetworkingConfig_SendBufferSize)
|
||||||
|
virtual EResult SendMessageToConnection( HSteamNetConnection hConn, const void *pData, uint32 cbData, int nSendFlags, int64 *pOutMessageNumber ) = 0;
|
||||||
|
|
||||||
|
/// Send one or more messages without copying the message payload.
|
||||||
|
/// This is the most efficient way to send messages. To use this
|
||||||
|
/// function, you must first allocate a message object using
|
||||||
|
/// ISteamNetworkingUtils::AllocateMessage. (Do not declare one
|
||||||
|
/// on the stack or allocate your own.)
|
||||||
|
///
|
||||||
|
/// You should fill in the message payload. You can either let
|
||||||
|
/// it allocate the buffer for you and then fill in the payload,
|
||||||
|
/// or if you already have a buffer allocated, you can just point
|
||||||
|
/// m_pData at your buffer and set the callback to the appropriate function
|
||||||
|
/// to free it. Note that if you use your own buffer, it MUST remain valid
|
||||||
|
/// until the callback is executed. And also note that your callback can be
|
||||||
|
/// invoked at any time from any thread (perhaps even before SendMessages
|
||||||
|
/// returns!), so it MUST be fast and threadsafe.
|
||||||
|
///
|
||||||
|
/// You MUST also fill in:
|
||||||
|
/// - m_conn - the handle of the connection to send the message to
|
||||||
|
/// - m_nFlags - bitmask of k_nSteamNetworkingSend_xxx flags.
|
||||||
|
///
|
||||||
|
/// All other fields are currently reserved and should not be modified.
|
||||||
|
///
|
||||||
|
/// The library will take ownership of the message structures. They may
|
||||||
|
/// be modified or become invalid at any time, so you must not read them
|
||||||
|
/// after passing them to this function.
|
||||||
|
///
|
||||||
|
/// pOutMessageNumberOrResult is an optional array that will receive,
|
||||||
|
/// for each message, the message number that was assigned to the message
|
||||||
|
/// if sending was successful. If sending failed, then a negative EResult
|
||||||
|
/// value is placed into the array. For example, the array will hold
|
||||||
|
/// -k_EResultInvalidState if the connection was in an invalid state.
|
||||||
|
/// See ISteamNetworkingSockets::SendMessageToConnection for possible
|
||||||
|
/// failure codes.
|
||||||
|
virtual void SendMessages( int nMessages, SteamNetworkingMessage_t *const *pMessages, int64 *pOutMessageNumberOrResult ) = 0;
|
||||||
|
|
||||||
|
/// Flush any messages waiting on the Nagle timer and send them
|
||||||
|
/// at the next transmission opportunity (often that means right now).
|
||||||
|
///
|
||||||
|
/// If Nagle is enabled (it's on by default) then when calling
|
||||||
|
/// SendMessageToConnection the message will be buffered, up to the Nagle time
|
||||||
|
/// before being sent, to merge small messages into the same packet.
|
||||||
|
/// (See k_ESteamNetworkingConfig_NagleTime)
|
||||||
|
///
|
||||||
|
/// Returns:
|
||||||
|
/// k_EResultInvalidParam: invalid connection handle
|
||||||
|
/// k_EResultInvalidState: connection is in an invalid state
|
||||||
|
/// k_EResultNoConnection: connection has ended
|
||||||
|
/// k_EResultIgnored: We weren't (yet) connected, so this operation has no effect.
|
||||||
|
virtual EResult FlushMessagesOnConnection( HSteamNetConnection hConn ) = 0;
|
||||||
|
|
||||||
|
/// Fetch the next available message(s) from the connection, if any.
|
||||||
|
/// Returns the number of messages returned into your array, up to nMaxMessages.
|
||||||
|
/// If the connection handle is invalid, -1 is returned.
|
||||||
|
///
|
||||||
|
/// The order of the messages returned in the array is relevant.
|
||||||
|
/// Reliable messages will be received in the order they were sent (and with the
|
||||||
|
/// same sizes --- see SendMessageToConnection for on this subtle difference from a stream socket).
|
||||||
|
///
|
||||||
|
/// Unreliable messages may be dropped, or delivered out of order with respect to
|
||||||
|
/// each other or with respect to reliable messages. The same unreliable message
|
||||||
|
/// may be received multiple times.
|
||||||
|
///
|
||||||
|
/// If any messages are returned, you MUST call SteamNetworkingMessage_t::Release() on each
|
||||||
|
/// of them free up resources after you are done. It is safe to keep the object alive for
|
||||||
|
/// a little while (put it into some queue, etc), and you may call Release() from any thread.
|
||||||
|
virtual int ReceiveMessagesOnConnection( HSteamNetConnection hConn, SteamNetworkingMessage_t **ppOutMessages, int nMaxMessages ) = 0;
|
||||||
|
|
||||||
|
/// Returns basic information about the high-level state of the connection.
|
||||||
|
virtual bool GetConnectionInfo( HSteamNetConnection hConn, SteamNetConnectionInfo_t *pInfo ) = 0;
|
||||||
|
|
||||||
|
// based on reversing the vftable returned from original steamclient64.dll
|
||||||
|
virtual bool GetConnectionRealTimeStatus_old( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus ) = 0;
|
||||||
|
|
||||||
|
/// Returns detailed connection stats in text format. Useful
|
||||||
|
/// for dumping to a log, etc.
|
||||||
|
///
|
||||||
|
/// Returns:
|
||||||
|
/// -1 failure (bad connection handle)
|
||||||
|
/// 0 OK, your buffer was filled in and '\0'-terminated
|
||||||
|
/// >0 Your buffer was either nullptr, or it was too small and the text got truncated.
|
||||||
|
/// Try again with a buffer of at least N bytes.
|
||||||
|
virtual int GetDetailedConnectionStatus( HSteamNetConnection hConn, char *pszBuf, int cbBuf ) = 0;
|
||||||
|
|
||||||
|
/// Returns local IP and port that a listen socket created using CreateListenSocketIP is bound to.
|
||||||
|
///
|
||||||
|
/// An IPv6 address of ::0 means "any IPv4 or IPv6"
|
||||||
|
/// An IPv6 address of ::ffff:0000:0000 means "any IPv4"
|
||||||
|
virtual bool GetListenSocketAddress( HSteamListenSocket hSocket, SteamNetworkingIPAddr *address ) = 0;
|
||||||
|
|
||||||
|
/// Create a pair of connections that are talking to each other, e.g. a loopback connection.
|
||||||
|
/// This is very useful for testing, or so that your client/server code can work the same
|
||||||
|
/// even when you are running a local "server".
|
||||||
|
///
|
||||||
|
/// The two connections will immediately be placed into the connected state, and no callbacks
|
||||||
|
/// will be posted immediately. After this, if you close either connection, the other connection
|
||||||
|
/// will receive a callback, exactly as if they were communicating over the network. You must
|
||||||
|
/// close *both* sides in order to fully clean up the resources!
|
||||||
|
///
|
||||||
|
/// By default, internal buffers are used, completely bypassing the network, the chopping up of
|
||||||
|
/// messages into packets, encryption, copying the payload, etc. This means that loopback
|
||||||
|
/// packets, by default, will not simulate lag or loss. Passing true for bUseNetworkLoopback will
|
||||||
|
/// cause the socket pair to send packets through the local network loopback device (127.0.0.1)
|
||||||
|
/// on ephemeral ports. Fake lag and loss are supported in this case, and CPU time is expended
|
||||||
|
/// to encrypt and decrypt.
|
||||||
|
///
|
||||||
|
/// If you wish to assign a specific identity to either connection, you may pass a particular
|
||||||
|
/// identity. Otherwise, if you pass nullptr, the respective connection will assume a generic
|
||||||
|
/// "localhost" identity. If you use real network loopback, this might be translated to the
|
||||||
|
/// actual bound loopback port. Otherwise, the port will be zero.
|
||||||
|
virtual bool CreateSocketPair( HSteamNetConnection *pOutConnection1, HSteamNetConnection *pOutConnection2, bool bUseNetworkLoopback, const SteamNetworkingIdentity *pIdentity1, const SteamNetworkingIdentity *pIdentity2 ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Identity and authentication
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Get the identity assigned to this interface.
|
||||||
|
/// E.g. on Steam, this is the user's SteamID, or for the gameserver interface, the SteamID assigned
|
||||||
|
/// to the gameserver. Returns false and sets the result to an invalid identity if we don't know
|
||||||
|
/// our identity yet. (E.g. GameServer has not logged in. On Steam, the user will know their SteamID
|
||||||
|
/// even if they are not signed into Steam.)
|
||||||
|
virtual bool GetIdentity( SteamNetworkingIdentity *pIdentity ) = 0;
|
||||||
|
|
||||||
|
/// Indicate our desire to be ready participate in authenticated communications.
|
||||||
|
/// If we are currently not ready, then steps will be taken to obtain the necessary
|
||||||
|
/// certificates. (This includes a certificate for us, as well as any CA certificates
|
||||||
|
/// needed to authenticate peers.)
|
||||||
|
///
|
||||||
|
/// You can call this at program init time if you know that you are going to
|
||||||
|
/// be making authenticated connections, so that we will be ready immediately when
|
||||||
|
/// those connections are attempted. (Note that essentially all connections require
|
||||||
|
/// authentication, with the exception of ordinary UDP connections with authentication
|
||||||
|
/// disabled using k_ESteamNetworkingConfig_IP_AllowWithoutAuth.) If you don't call
|
||||||
|
/// this function, we will wait until a feature is utilized that that necessitates
|
||||||
|
/// these resources.
|
||||||
|
///
|
||||||
|
/// You can also call this function to force a retry, if failure has occurred.
|
||||||
|
/// Once we make an attempt and fail, we will not automatically retry.
|
||||||
|
/// In this respect, the behavior of the system after trying and failing is the same
|
||||||
|
/// as before the first attempt: attempting authenticated communication or calling
|
||||||
|
/// this function will call the system to attempt to acquire the necessary resources.
|
||||||
|
///
|
||||||
|
/// You can use GetAuthenticationStatus or listen for SteamNetAuthenticationStatus_t
|
||||||
|
/// to monitor the status.
|
||||||
|
///
|
||||||
|
/// Returns the current value that would be returned from GetAuthenticationStatus.
|
||||||
|
virtual ESteamNetworkingAvailability InitAuthentication() = 0;
|
||||||
|
|
||||||
|
/// Query our readiness to participate in authenticated communications. A
|
||||||
|
/// SteamNetAuthenticationStatus_t callback is posted any time this status changes,
|
||||||
|
/// but you can use this function to query it at any time.
|
||||||
|
///
|
||||||
|
/// The value of SteamNetAuthenticationStatus_t::m_eAvail is returned. If you only
|
||||||
|
/// want this high level status, you can pass NULL for pDetails. If you want further
|
||||||
|
/// details, pass non-NULL to receive them.
|
||||||
|
virtual ESteamNetworkingAvailability GetAuthenticationStatus( SteamNetAuthenticationStatus_t *pDetails ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Poll groups. A poll group is a set of connections that can be polled efficiently.
|
||||||
|
// (In our API, to "poll" a connection means to retrieve all pending messages. We
|
||||||
|
// actually don't have an API to "poll" the connection *state*, like BSD sockets.)
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Create a new poll group.
|
||||||
|
///
|
||||||
|
/// You should destroy the poll group when you are done using DestroyPollGroup
|
||||||
|
virtual HSteamNetPollGroup CreatePollGroup() = 0;
|
||||||
|
|
||||||
|
/// Destroy a poll group created with CreatePollGroup().
|
||||||
|
///
|
||||||
|
/// If there are any connections in the poll group, they are removed from the group,
|
||||||
|
/// and left in a state where they are not part of any poll group.
|
||||||
|
/// Returns false if passed an invalid poll group handle.
|
||||||
|
virtual bool DestroyPollGroup( HSteamNetPollGroup hPollGroup ) = 0;
|
||||||
|
|
||||||
|
/// Assign a connection to a poll group. Note that a connection may only belong to a
|
||||||
|
/// single poll group. Adding a connection to a poll group implicitly removes it from
|
||||||
|
/// any other poll group it is in.
|
||||||
|
///
|
||||||
|
/// You can pass k_HSteamNetPollGroup_Invalid to remove a connection from its current
|
||||||
|
/// poll group without adding it to a new poll group.
|
||||||
|
///
|
||||||
|
/// If there are received messages currently pending on the connection, an attempt
|
||||||
|
/// is made to add them to the queue of messages for the poll group in approximately
|
||||||
|
/// the order that would have applied if the connection was already part of the poll
|
||||||
|
/// group at the time that the messages were received.
|
||||||
|
///
|
||||||
|
/// Returns false if the connection handle is invalid, or if the poll group handle
|
||||||
|
/// is invalid (and not k_HSteamNetPollGroup_Invalid).
|
||||||
|
virtual bool SetConnectionPollGroup( HSteamNetConnection hConn, HSteamNetPollGroup hPollGroup ) = 0;
|
||||||
|
|
||||||
|
/// Same as ReceiveMessagesOnConnection, but will return the next messages available
|
||||||
|
/// on any connection in the poll group. Examine SteamNetworkingMessage_t::m_conn
|
||||||
|
/// to know which connection. (SteamNetworkingMessage_t::m_nConnUserData might also
|
||||||
|
/// be useful.)
|
||||||
|
///
|
||||||
|
/// Delivery order of messages among different connections will usually match the
|
||||||
|
/// order that the last packet was received which completed the message. But this
|
||||||
|
/// is not a strong guarantee, especially for packets received right as a connection
|
||||||
|
/// is being assigned to poll group.
|
||||||
|
///
|
||||||
|
/// Delivery order of messages on the same connection is well defined and the
|
||||||
|
/// same guarantees are present as mentioned in ReceiveMessagesOnConnection.
|
||||||
|
/// (But the messages are not grouped by connection, so they will not necessarily
|
||||||
|
/// appear consecutively in the list; they may be interleaved with messages for
|
||||||
|
/// other connections.)
|
||||||
|
virtual int ReceiveMessagesOnPollGroup( HSteamNetPollGroup hPollGroup, SteamNetworkingMessage_t **ppOutMessages, int nMaxMessages ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Clients connecting to dedicated servers hosted in a data center,
|
||||||
|
// using tickets issued by your game coordinator. If you are not
|
||||||
|
// issuing your own tickets to restrict who can attempt to connect
|
||||||
|
// to your server, then you won't use these functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Call this when you receive a ticket from your backend / matchmaking system. Puts the
|
||||||
|
/// ticket into a persistent cache, and optionally returns the parsed ticket.
|
||||||
|
///
|
||||||
|
/// See stamdatagram_ticketgen.h for more details.
|
||||||
|
virtual bool ReceivedRelayAuthTicket( const void *pvTicket, int cbTicket, SteamDatagramRelayAuthTicket *pOutParsedTicket ) = 0;
|
||||||
|
|
||||||
|
/// Search cache for a ticket to talk to the server on the specified virtual port.
|
||||||
|
/// If found, returns the number of seconds until the ticket expires, and optionally
|
||||||
|
/// the complete cracked ticket. Returns 0 if we don't have a ticket.
|
||||||
|
///
|
||||||
|
/// Typically this is useful just to confirm that you have a ticket, before you
|
||||||
|
/// call ConnectToHostedDedicatedServer to connect to the server.
|
||||||
|
virtual int FindRelayAuthTicketForServer( const SteamNetworkingIdentity &identityGameServer, int nRemoteVirtualPort, SteamDatagramRelayAuthTicket *pOutParsedTicket ) = 0;
|
||||||
|
|
||||||
|
/// Client call to connect to a server hosted in a Valve data center, on the specified virtual
|
||||||
|
/// port. You must have placed a ticket for this server into the cache, or else this connect
|
||||||
|
/// attempt will fail! If you are not issuing your own tickets, then to connect to a dedicated
|
||||||
|
/// server via SDR in auto-ticket mode, use ConnectP2P. (The server must be configured to allow
|
||||||
|
/// this type of connection by listening using CreateListenSocketP2P.)
|
||||||
|
///
|
||||||
|
/// You may wonder why tickets are stored in a cache, instead of simply being passed as an argument
|
||||||
|
/// here. The reason is to make reconnection to a gameserver robust, even if the client computer loses
|
||||||
|
/// connection to Steam or the central backend, or the app is restarted or crashes, etc.
|
||||||
|
///
|
||||||
|
/// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
|
||||||
|
/// when your app initializes
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
virtual HSteamNetConnection ConnectToHostedDedicatedServer( const SteamNetworkingIdentity &identityTarget, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Servers hosted in data centers known to the Valve relay network
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Returns the value of the SDR_LISTEN_PORT environment variable. This
|
||||||
|
/// is the UDP server your server will be listening on. This will
|
||||||
|
/// configured automatically for you in production environments.
|
||||||
|
///
|
||||||
|
/// In development, you'll need to set it yourself. See
|
||||||
|
/// https://partner.steamgames.com/doc/api/ISteamNetworkingSockets
|
||||||
|
/// for more information on how to configure dev environments.
|
||||||
|
virtual uint16 GetHostedDedicatedServerPort() = 0;
|
||||||
|
|
||||||
|
/// Returns 0 if SDR_LISTEN_PORT is not set. Otherwise, returns the data center the server
|
||||||
|
/// is running in. This will be k_SteamDatagramPOPID_dev in non-production environment.
|
||||||
|
virtual SteamNetworkingPOPID GetHostedDedicatedServerPOPID() = 0;
|
||||||
|
|
||||||
|
/// Return info about the hosted server. This contains the PoPID of the server,
|
||||||
|
/// and opaque routing information that can be used by the relays to send traffic
|
||||||
|
/// to your server.
|
||||||
|
///
|
||||||
|
/// You will need to send this information to your backend, and put it in tickets,
|
||||||
|
/// so that the relays will know how to forward traffic from
|
||||||
|
/// clients to your server. See SteamDatagramRelayAuthTicket for more info.
|
||||||
|
///
|
||||||
|
/// Also, note that the routing information is contained in SteamDatagramGameCoordinatorServerLogin,
|
||||||
|
/// so if possible, it's preferred to use GetGameCoordinatorServerLogin to send this info
|
||||||
|
/// to your game coordinator service, and also login securely at the same time.
|
||||||
|
///
|
||||||
|
/// On a successful exit, k_EResultOK is returned
|
||||||
|
///
|
||||||
|
/// Unsuccessful exit:
|
||||||
|
/// - Something other than k_EResultOK is returned.
|
||||||
|
/// - k_EResultInvalidState: We are not configured to listen for SDR (SDR_LISTEN_SOCKET
|
||||||
|
/// is not set.)
|
||||||
|
/// - k_EResultPending: we do not (yet) have the authentication information needed.
|
||||||
|
/// (See GetAuthenticationStatus.) If you use environment variables to pre-fetch
|
||||||
|
/// the network config, this data should always be available immediately.
|
||||||
|
/// - A non-localized diagnostic debug message will be placed in m_data that describes
|
||||||
|
/// the cause of the failure.
|
||||||
|
///
|
||||||
|
/// NOTE: The returned blob is not encrypted. Send it to your backend, but don't
|
||||||
|
/// directly share it with clients.
|
||||||
|
virtual EResult GetHostedDedicatedServerAddress( SteamDatagramHostedAddress *pRouting ) = 0;
|
||||||
|
|
||||||
|
/// Create a listen socket on the specified virtual port. The physical UDP port to use
|
||||||
|
/// will be determined by the SDR_LISTEN_PORT environment variable. If a UDP port is not
|
||||||
|
/// configured, this call will fail.
|
||||||
|
///
|
||||||
|
/// This call MUST be made through the SteamGameServerNetworkingSockets() interface.
|
||||||
|
///
|
||||||
|
/// This function should be used when you are using the ticket generator library
|
||||||
|
/// to issue your own tickets. Clients connecting to the server on this virtual
|
||||||
|
/// port will need a ticket, and they must connect using ConnectToHostedDedicatedServer.
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
virtual HSteamListenSocket CreateHostedDedicatedServerListenSocket( int nLocalVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Generate an authentication blob that can be used to securely login with
|
||||||
|
/// your backend, using SteamDatagram_ParseHostedServerLogin. (See
|
||||||
|
/// steamdatagram_gamecoordinator.h)
|
||||||
|
///
|
||||||
|
/// Before calling the function:
|
||||||
|
/// - Populate the app data in pLoginInfo (m_cbAppData and m_appData). You can leave
|
||||||
|
/// all other fields uninitialized.
|
||||||
|
/// - *pcbSignedBlob contains the size of the buffer at pBlob. (It should be
|
||||||
|
/// at least k_cbMaxSteamDatagramGameCoordinatorServerLoginSerialized.)
|
||||||
|
///
|
||||||
|
/// On a successful exit:
|
||||||
|
/// - k_EResultOK is returned
|
||||||
|
/// - All of the remaining fields of pLoginInfo will be filled out.
|
||||||
|
/// - *pcbSignedBlob contains the size of the serialized blob that has been
|
||||||
|
/// placed into pBlob.
|
||||||
|
///
|
||||||
|
/// Unsuccessful exit:
|
||||||
|
/// - Something other than k_EResultOK is returned.
|
||||||
|
/// - k_EResultNotLoggedOn: you are not logged in (yet)
|
||||||
|
/// - See GetHostedDedicatedServerAddress for more potential failure return values.
|
||||||
|
/// - A non-localized diagnostic debug message will be placed in pBlob that describes
|
||||||
|
/// the cause of the failure.
|
||||||
|
///
|
||||||
|
/// This works by signing the contents of the SteamDatagramGameCoordinatorServerLogin
|
||||||
|
/// with the cert that is issued to this server. In dev environments, it's OK if you do
|
||||||
|
/// not have a cert. (You will need to enable insecure dev login in SteamDatagram_ParseHostedServerLogin.)
|
||||||
|
/// Otherwise, you will need a signed cert.
|
||||||
|
///
|
||||||
|
/// NOTE: The routing blob returned here is not encrypted. Send it to your backend
|
||||||
|
/// and don't share it directly with clients.
|
||||||
|
virtual EResult GetGameCoordinatorServerLogin( SteamDatagramGameCoordinatorServerLogin *pLoginInfo, int *pcbSignedBlob, void *pBlob ) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Relayed connections using custom signaling protocol
|
||||||
|
//
|
||||||
|
// This is used if you have your own method of sending out-of-band
|
||||||
|
// signaling / rendezvous messages through a mutually trusted channel.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Create a P2P "client" connection that does signaling over a custom
|
||||||
|
/// rendezvous/signaling channel.
|
||||||
|
///
|
||||||
|
/// pSignaling points to a new object that you create just for this connection.
|
||||||
|
/// It must stay valid until Release() is called. Once you pass the
|
||||||
|
/// object to this function, it assumes ownership. Release() will be called
|
||||||
|
/// from within the function call if the call fails. Furthermore, until Release()
|
||||||
|
/// is called, you should be prepared for methods to be invoked on your
|
||||||
|
/// object from any thread! You need to make sure your object is threadsafe!
|
||||||
|
/// Furthermore, you should make sure that dispatching the methods is done
|
||||||
|
/// as quickly as possible.
|
||||||
|
///
|
||||||
|
/// This function will immediately construct a connection in the "connecting"
|
||||||
|
/// state. Soon after (perhaps before this function returns, perhaps in another thread),
|
||||||
|
/// the connection will begin sending signaling messages by calling
|
||||||
|
/// ISteamNetworkingConnectionSignaling::SendSignal.
|
||||||
|
///
|
||||||
|
/// When the remote peer accepts the connection (See
|
||||||
|
/// ISteamNetworkingSignalingRecvContext::OnConnectRequest),
|
||||||
|
/// it will begin sending signaling messages. When these messages are received,
|
||||||
|
/// you can pass them to the connection using ReceivedP2PCustomSignal.
|
||||||
|
///
|
||||||
|
/// If you know the identity of the peer that you expect to be on the other end,
|
||||||
|
/// you can pass their identity to improve debug output or just detect bugs.
|
||||||
|
/// If you don't know their identity yet, you can pass NULL, and their
|
||||||
|
/// identity will be established in the connection handshake.
|
||||||
|
///
|
||||||
|
/// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
|
||||||
|
/// when your app initializes
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
//virtual HSteamNetConnection ConnectP2PCustomSignaling( ISteamNetworkingConnectionCustomSignaling *pSignaling, const SteamNetworkingIdentity *pPeerIdentity, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
virtual HSteamNetConnection ConnectP2PCustomSignaling( ISteamNetworkingConnectionSignaling *pSignaling, const SteamNetworkingIdentity *pPeerIdentity, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Called when custom signaling has received a message. When your
|
||||||
|
/// signaling channel receives a message, it should save off whatever
|
||||||
|
/// routing information was in the envelope into the context object,
|
||||||
|
/// and then pass the payload to this function.
|
||||||
|
///
|
||||||
|
/// A few different things can happen next, depending on the message:
|
||||||
|
///
|
||||||
|
/// - If the signal is associated with existing connection, it is dealt
|
||||||
|
/// with immediately. If any replies need to be sent, they will be
|
||||||
|
/// dispatched using the ISteamNetworkingConnectionSignaling
|
||||||
|
/// associated with the connection.
|
||||||
|
/// - If the message represents a connection request (and the request
|
||||||
|
/// is not redundant for an existing connection), a new connection
|
||||||
|
/// will be created, and ReceivedConnectRequest will be called on your
|
||||||
|
/// context object to determine how to proceed.
|
||||||
|
/// - Otherwise, the message is for a connection that does not
|
||||||
|
/// exist (anymore). In this case, we *may* call SendRejectionReply
|
||||||
|
/// on your context object.
|
||||||
|
///
|
||||||
|
/// In any case, we will not save off pContext or access it after this
|
||||||
|
/// function returns.
|
||||||
|
///
|
||||||
|
/// Returns true if the message was parsed and dispatched without anything
|
||||||
|
/// unusual or suspicious happening. Returns false if there was some problem
|
||||||
|
/// with the message that prevented ordinary handling. (Debug output will
|
||||||
|
/// usually have more information.)
|
||||||
|
///
|
||||||
|
/// If you expect to be using relayed connections, then you probably want
|
||||||
|
/// to call ISteamNetworkingUtils::InitRelayNetworkAccess() when your app initializes
|
||||||
|
//virtual bool ReceivedP2PCustomSignal( const void *pMsg, int cbMsg, ISteamNetworkingCustomSignalingRecvContext *pContext ) = 0;
|
||||||
|
virtual bool ReceivedP2PCustomSignal( const void *pMsg, int cbMsg, ISteamNetworkingSignalingRecvContext *pContext ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Certificate provision by the application. On Steam, we normally handle all this automatically
|
||||||
|
// and you will not need to use these advanced functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Get blob that describes a certificate request. You can send this to your game coordinator.
|
||||||
|
/// Upon entry, *pcbBlob should contain the size of the buffer. On successful exit, it will
|
||||||
|
/// return the number of bytes that were populated. You can pass pBlob=NULL to query for the required
|
||||||
|
/// size. (512 bytes is a conservative estimate.)
|
||||||
|
///
|
||||||
|
/// Pass this blob to your game coordinator and call SteamDatagram_CreateCert.
|
||||||
|
virtual bool GetCertificateRequest( int *pcbBlob, void *pBlob, SteamNetworkingErrMsg &errMsg ) = 0;
|
||||||
|
|
||||||
|
/// Set the certificate. The certificate blob should be the output of
|
||||||
|
/// SteamDatagram_CreateCert.
|
||||||
|
virtual bool SetCertificate( const void *pCertificate, int cbCertificate, SteamNetworkingErrMsg &errMsg ) = 0;
|
||||||
|
|
||||||
|
/// Reset the identity associated with this instance.
|
||||||
|
/// Any open connections are closed. Any previous certificates, etc are discarded.
|
||||||
|
/// You can pass a specific identity that you want to use, or you can pass NULL,
|
||||||
|
/// in which case the identity will be invalid until you set it using SetCertificate
|
||||||
|
///
|
||||||
|
/// NOTE: This function is not actually supported on Steam! It is included
|
||||||
|
/// for use on other platforms where the active user can sign out and
|
||||||
|
/// a new user can sign in.
|
||||||
|
virtual void ResetIdentity( const SteamNetworkingIdentity *pIdentity ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Misc
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Invoke all callback functions queued for this interface.
|
||||||
|
/// See k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, etc
|
||||||
|
///
|
||||||
|
/// You don't need to call this if you are using Steam's callback dispatch
|
||||||
|
/// mechanism (SteamAPI_RunCallbacks and SteamGameserver_RunCallbacks).
|
||||||
|
virtual void RunCallbacks() = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// "FakeIP" system.
|
||||||
|
//
|
||||||
|
// A FakeIP is essentially a temporary, arbitrary identifier that
|
||||||
|
// happens to be a valid IPv4 address. The purpose of this system is to make it
|
||||||
|
// easy to integrate with existing code that identifies hosts using IPv4 addresses.
|
||||||
|
// The FakeIP address will never actually be used to send or receive any packets
|
||||||
|
// on the Internet, it is strictly an identifier.
|
||||||
|
//
|
||||||
|
// FakeIP addresses are designed to (hopefully) pass through existing code as
|
||||||
|
// transparently as possible, while conflicting with "real" addresses that might
|
||||||
|
// be in use on networks (both the Internet and LANs) in the same code as little
|
||||||
|
// as possible. At the time this comment is being written, they come from the
|
||||||
|
// 169.254.0.0/16 range, and the port number will always be >1024. HOWEVER,
|
||||||
|
// this is subject to change! Do not make assumptions about these addresses,
|
||||||
|
// or your code might break in the future. In particular, you should use
|
||||||
|
// functions such as ISteamNetworkingUtils::IsFakeIP to determine if an IP
|
||||||
|
// address is a "fake" one used by this system.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Begin asynchronous process of allocating a fake IPv4 address that other
|
||||||
|
/// peers can use to contact us via P2P. IP addresses returned by this
|
||||||
|
/// function are globally unique for a given appid.
|
||||||
|
///
|
||||||
|
/// nNumPorts is the numbers of ports you wish to reserve. This is useful
|
||||||
|
/// for the same reason that listening on multiple UDP ports is useful for
|
||||||
|
/// different types of traffic. Because these allocations come from a global
|
||||||
|
/// namespace, there is a relatively strict limit on the maximum number of
|
||||||
|
/// ports you may request. (At the time of this writing, the limit is 4.)
|
||||||
|
/// The port assignments are *not* guaranteed to have any particular order
|
||||||
|
/// or relationship! Do *not* assume they are contiguous, even though that
|
||||||
|
/// may often occur in practice.
|
||||||
|
///
|
||||||
|
/// Returns false if a request was already in progress, true if a new request
|
||||||
|
/// was started. A SteamNetworkingFakeIPResult_t will be posted when the request
|
||||||
|
/// completes.
|
||||||
|
///
|
||||||
|
/// For gameservers, you *must* call this after initializing the SDK but before
|
||||||
|
/// beginning login. Steam needs to know in advance that FakeIP will be used.
|
||||||
|
/// Everywhere your public IP would normally appear (such as the server browser) will be
|
||||||
|
/// replaced by the FakeIP, and the fake port at index 0. The request is actually queued
|
||||||
|
/// until the logon completes, so you must not wait until the allocation completes
|
||||||
|
/// before logging in. Except for trivial failures that can be detected locally
|
||||||
|
/// (e.g. invalid parameter), a SteamNetworkingFakeIPResult_t callback (whether success or
|
||||||
|
/// failure) will not be posted until after we have logged in. Furthermore, it is assumed
|
||||||
|
/// that FakeIP allocation is essential for your application to function, and so failure
|
||||||
|
/// will not be reported until *several* retries have been attempted. This process may
|
||||||
|
/// last several minutes. It is *highly* recommended to treat failure as fatal.
|
||||||
|
///
|
||||||
|
/// To communicate using a connection-oriented (TCP-style) API:
|
||||||
|
/// - Server creates a listen socket using CreateListenSocketP2PFakeIP
|
||||||
|
/// - Client connects using ConnectByIPAddress, passing in the FakeIP address.
|
||||||
|
/// - The connection will behave mostly like a P2P connection. The identities
|
||||||
|
/// that appear in SteamNetConnectionInfo_t will be the FakeIP identity until
|
||||||
|
/// we know the real identity. Then it will be the real identity. If the
|
||||||
|
/// SteamNetConnectionInfo_t::m_addrRemote is valid, it will be a real IPv4
|
||||||
|
/// address of a NAT-punched connection. Otherwise, it will not be valid.
|
||||||
|
///
|
||||||
|
/// To communicate using an ad-hoc sendto/recv from (UDP-style) API,
|
||||||
|
/// use CreateFakeUDPPort.
|
||||||
|
virtual bool BeginAsyncRequestFakeIP( int nNumPorts ) = 0;
|
||||||
|
|
||||||
|
/// Return info about the FakeIP and port(s) that we have been assigned,
|
||||||
|
/// if any. idxFirstPort is currently reserved and must be zero.
|
||||||
|
/// Make sure and check SteamNetworkingFakeIPResult_t::m_eResult
|
||||||
|
virtual void GetFakeIP( int idxFirstPort, SteamNetworkingFakeIPResult_t *pInfo ) = 0;
|
||||||
|
|
||||||
|
/// Create a listen socket that will listen for P2P connections sent
|
||||||
|
/// to our FakeIP. A peer can initiate connections to this listen
|
||||||
|
/// socket by calling ConnectByIPAddress.
|
||||||
|
///
|
||||||
|
/// idxFakePort refers to the *index* of the fake port requested,
|
||||||
|
/// not the actual port number. For example, pass 0 to refer to the
|
||||||
|
/// first port in the reservation. You must call this only after calling
|
||||||
|
/// BeginAsyncRequestFakeIP. However, you do not need to wait for the
|
||||||
|
/// request to complete before creating the listen socket.
|
||||||
|
virtual HSteamListenSocket CreateListenSocketP2PFakeIP( int idxFakePort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// If the connection was initiated using the "FakeIP" system, then we
|
||||||
|
/// we can get an IP address for the remote host. If the remote host had
|
||||||
|
/// a global FakeIP at the time the connection was established, this
|
||||||
|
/// function will return that global IP. Otherwise, a FakeIP that is
|
||||||
|
/// unique locally will be allocated from the local FakeIP address space,
|
||||||
|
/// and that will be returned.
|
||||||
|
///
|
||||||
|
/// The allocation of local FakeIPs attempts to assign addresses in
|
||||||
|
/// a consistent manner. If multiple connections are made to the
|
||||||
|
/// same remote host, they *probably* will return the same FakeIP.
|
||||||
|
/// However, since the namespace is limited, this cannot be guaranteed.
|
||||||
|
///
|
||||||
|
/// On failure, returns:
|
||||||
|
/// - k_EResultInvalidParam: invalid connection handle
|
||||||
|
/// - k_EResultIPNotFound: This connection wasn't made using FakeIP system
|
||||||
|
virtual EResult GetRemoteFakeIPForConnection( HSteamNetConnection hConn, SteamNetworkingIPAddr *pOutAddr ) = 0;
|
||||||
|
|
||||||
|
/// Get an interface that can be used like a UDP port to send/receive
|
||||||
|
/// datagrams to a FakeIP address. This is intended to make it easy
|
||||||
|
/// to port existing UDP-based code to take advantage of SDR.
|
||||||
|
///
|
||||||
|
/// idxFakeServerPort refers to the *index* of the port allocated using
|
||||||
|
/// BeginAsyncRequestFakeIP and is used to create "server" ports. You may
|
||||||
|
/// call this before the allocation has completed. However, any attempts
|
||||||
|
/// to send packets will fail until the allocation has succeeded. When
|
||||||
|
/// the peer receives packets sent from this interface, the from address
|
||||||
|
/// of the packet will be the globally-unique FakeIP. If you call this
|
||||||
|
/// function multiple times and pass the same (nonnegative) fake port index,
|
||||||
|
/// the same object will be returned, and this object is not reference counted.
|
||||||
|
///
|
||||||
|
/// To create a "client" port (e.g. the equivalent of an ephemeral UDP port)
|
||||||
|
/// pass -1. In this case, a distinct object will be returned for each call.
|
||||||
|
/// When the peer receives packets sent from this interface, the peer will
|
||||||
|
/// assign a FakeIP from its own locally-controlled namespace.
|
||||||
|
virtual ISteamNetworkingFakeUDPPort *CreateFakeUDPPort( int idxFakeServerPort ) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// ~ISteamNetworkingSockets(); // Silence some warnings
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ISTEAMNETWORKINGSOCKETS010
|
804
sdk/steam/isteamnetworkingsockets011.h
Normal file
804
sdk/steam/isteamnetworkingsockets011.h
Normal file
@ -0,0 +1,804 @@
|
|||||||
|
|
||||||
|
#ifndef ISTEAMNETWORKINGSOCKETS011
|
||||||
|
#define ISTEAMNETWORKINGSOCKETS011
|
||||||
|
|
||||||
|
// this interface version is not found in public SDK archives, it is based on reversing the returned vftable from steamclient64.dll
|
||||||
|
|
||||||
|
class ISteamNetworkingSockets011
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Creates a "server" socket that listens for clients to connect to by
|
||||||
|
/// calling ConnectByIPAddress, over ordinary UDP (IPv4 or IPv6)
|
||||||
|
///
|
||||||
|
/// You must select a specific local port to listen on and set it
|
||||||
|
/// the port field of the local address.
|
||||||
|
///
|
||||||
|
/// Usually you will set the IP portion of the address to zero (SteamNetworkingIPAddr::Clear()).
|
||||||
|
/// This means that you will not bind to any particular local interface (i.e. the same
|
||||||
|
/// as INADDR_ANY in plain socket code). Furthermore, if possible the socket will be bound
|
||||||
|
/// in "dual stack" mode, which means that it can accept both IPv4 and IPv6 client connections.
|
||||||
|
/// If you really do wish to bind a particular interface, then set the local address to the
|
||||||
|
/// appropriate IPv4 or IPv6 IP.
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
///
|
||||||
|
/// When a client attempts to connect, a SteamNetConnectionStatusChangedCallback_t
|
||||||
|
/// will be posted. The connection will be in the connecting state.
|
||||||
|
virtual HSteamListenSocket CreateListenSocketIP( const SteamNetworkingIPAddr &localAddress, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Creates a connection and begins talking to a "server" over UDP at the
|
||||||
|
/// given IPv4 or IPv6 address. The remote host must be listening with a
|
||||||
|
/// matching call to CreateListenSocketIP on the specified port.
|
||||||
|
///
|
||||||
|
/// A SteamNetConnectionStatusChangedCallback_t callback will be triggered when we start
|
||||||
|
/// connecting, and then another one on either timeout or successful connection.
|
||||||
|
///
|
||||||
|
/// If the server does not have any identity configured, then their network address
|
||||||
|
/// will be the only identity in use. Or, the network host may provide a platform-specific
|
||||||
|
/// identity with or without a valid certificate to authenticate that identity. (These
|
||||||
|
/// details will be contained in the SteamNetConnectionStatusChangedCallback_t.) It's
|
||||||
|
/// up to your application to decide whether to allow the connection.
|
||||||
|
///
|
||||||
|
/// By default, all connections will get basic encryption sufficient to prevent
|
||||||
|
/// casual eavesdropping. But note that without certificates (or a shared secret
|
||||||
|
/// distributed through some other out-of-band mechanism), you don't have any
|
||||||
|
/// way of knowing who is actually on the other end, and thus are vulnerable to
|
||||||
|
/// man-in-the-middle attacks.
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
virtual HSteamNetConnection ConnectByIPAddress( const SteamNetworkingIPAddr &address, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Like CreateListenSocketIP, but clients will connect using ConnectP2P.
|
||||||
|
///
|
||||||
|
/// nLocalVirtualPort specifies how clients can connect to this socket using
|
||||||
|
/// ConnectP2P. It's very common for applications to only have one listening socket;
|
||||||
|
/// in that case, use zero. If you need to open multiple listen sockets and have clients
|
||||||
|
/// be able to connect to one or the other, then nLocalVirtualPort should be a small
|
||||||
|
/// integer (<1000) unique to each listen socket you create.
|
||||||
|
///
|
||||||
|
/// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
|
||||||
|
/// when your app initializes.
|
||||||
|
///
|
||||||
|
/// If you are listening on a dedicated servers in known data center,
|
||||||
|
/// then you can listen using this function instead of CreateHostedDedicatedServerListenSocket,
|
||||||
|
/// to allow clients to connect without a ticket. Any user that owns
|
||||||
|
/// the app and is signed into Steam will be able to attempt to connect to
|
||||||
|
/// your server. Also, a connection attempt may require the client to
|
||||||
|
/// be connected to Steam, which is one more moving part that may fail. When
|
||||||
|
/// tickets are used, then once a ticket is obtained, a client can connect to
|
||||||
|
/// your server even if they got disconnected from Steam or Steam is offline.
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
virtual HSteamListenSocket CreateListenSocketP2P( int nLocalVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Begin connecting to a peer that is identified using a platform-specific identifier.
|
||||||
|
/// This uses the default rendezvous service, which depends on the platform and library
|
||||||
|
/// configuration. (E.g. on Steam, it goes through the steam backend.)
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
///
|
||||||
|
/// To use your own signaling service, see:
|
||||||
|
/// - ConnectP2PCustomSignaling
|
||||||
|
/// - k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling
|
||||||
|
virtual HSteamNetConnection ConnectP2P( const SteamNetworkingIdentity &identityRemote, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Accept an incoming connection that has been received on a listen socket.
|
||||||
|
///
|
||||||
|
/// When a connection attempt is received (perhaps after a few basic handshake
|
||||||
|
/// packets have been exchanged to prevent trivial spoofing), a connection interface
|
||||||
|
/// object is created in the k_ESteamNetworkingConnectionState_Connecting state
|
||||||
|
/// and a SteamNetConnectionStatusChangedCallback_t is posted. At this point, your
|
||||||
|
/// application MUST either accept or close the connection. (It may not ignore it.)
|
||||||
|
/// Accepting the connection will transition it either into the connected state,
|
||||||
|
/// or the finding route state, depending on the connection type.
|
||||||
|
///
|
||||||
|
/// You should take action within a second or two, because accepting the connection is
|
||||||
|
/// what actually sends the reply notifying the client that they are connected. If you
|
||||||
|
/// delay taking action, from the client's perspective it is the same as the network
|
||||||
|
/// being unresponsive, and the client may timeout the connection attempt. In other
|
||||||
|
/// words, the client cannot distinguish between a delay caused by network problems
|
||||||
|
/// and a delay caused by the application.
|
||||||
|
///
|
||||||
|
/// This means that if your application goes for more than a few seconds without
|
||||||
|
/// processing callbacks (for example, while loading a map), then there is a chance
|
||||||
|
/// that a client may attempt to connect in that interval and fail due to timeout.
|
||||||
|
///
|
||||||
|
/// If the application does not respond to the connection attempt in a timely manner,
|
||||||
|
/// and we stop receiving communication from the client, the connection attempt will
|
||||||
|
/// be timed out locally, transitioning the connection to the
|
||||||
|
/// k_ESteamNetworkingConnectionState_ProblemDetectedLocally state. The client may also
|
||||||
|
/// close the connection before it is accepted, and a transition to the
|
||||||
|
/// k_ESteamNetworkingConnectionState_ClosedByPeer is also possible depending the exact
|
||||||
|
/// sequence of events.
|
||||||
|
///
|
||||||
|
/// Returns k_EResultInvalidParam if the handle is invalid.
|
||||||
|
/// Returns k_EResultInvalidState if the connection is not in the appropriate state.
|
||||||
|
/// (Remember that the connection state could change in between the time that the
|
||||||
|
/// notification being posted to the queue and when it is received by the application.)
|
||||||
|
///
|
||||||
|
/// A note about connection configuration options. If you need to set any configuration
|
||||||
|
/// options that are common to all connections accepted through a particular listen
|
||||||
|
/// socket, consider setting the options on the listen socket, since such options are
|
||||||
|
/// inherited automatically. If you really do need to set options that are connection
|
||||||
|
/// specific, it is safe to set them on the connection before accepting the connection.
|
||||||
|
virtual EResult AcceptConnection( HSteamNetConnection hConn ) = 0;
|
||||||
|
|
||||||
|
/// Disconnects from the remote host and invalidates the connection handle.
|
||||||
|
/// Any unread data on the connection is discarded.
|
||||||
|
///
|
||||||
|
/// nReason is an application defined code that will be received on the other
|
||||||
|
/// end and recorded (when possible) in backend analytics. The value should
|
||||||
|
/// come from a restricted range. (See ESteamNetConnectionEnd.) If you don't need
|
||||||
|
/// to communicate any information to the remote host, and do not want analytics to
|
||||||
|
/// be able to distinguish "normal" connection terminations from "exceptional" ones,
|
||||||
|
/// You may pass zero, in which case the generic value of
|
||||||
|
/// k_ESteamNetConnectionEnd_App_Generic will be used.
|
||||||
|
///
|
||||||
|
/// pszDebug is an optional human-readable diagnostic string that will be received
|
||||||
|
/// by the remote host and recorded (when possible) in backend analytics.
|
||||||
|
///
|
||||||
|
/// If you wish to put the socket into a "linger" state, where an attempt is made to
|
||||||
|
/// flush any remaining sent data, use bEnableLinger=true. Otherwise reliable data
|
||||||
|
/// is not flushed.
|
||||||
|
///
|
||||||
|
/// If the connection has already ended and you are just freeing up the
|
||||||
|
/// connection interface, the reason code, debug string, and linger flag are
|
||||||
|
/// ignored.
|
||||||
|
virtual bool CloseConnection( HSteamNetConnection hPeer, int nReason, const char *pszDebug, bool bEnableLinger ) = 0;
|
||||||
|
|
||||||
|
/// Destroy a listen socket. All the connections that were accepting on the listen
|
||||||
|
/// socket are closed ungracefully.
|
||||||
|
virtual bool CloseListenSocket( HSteamListenSocket hSocket ) = 0;
|
||||||
|
|
||||||
|
/// Set connection user data. the data is returned in the following places
|
||||||
|
/// - You can query it using GetConnectionUserData.
|
||||||
|
/// - The SteamNetworkingmessage_t structure.
|
||||||
|
/// - The SteamNetConnectionInfo_t structure.
|
||||||
|
/// (Which is a member of SteamNetConnectionStatusChangedCallback_t -- but see WARNINGS below!!!!)
|
||||||
|
///
|
||||||
|
/// Do you need to set this atomically when the connection is created?
|
||||||
|
/// See k_ESteamNetworkingConfig_ConnectionUserData.
|
||||||
|
///
|
||||||
|
/// WARNING: Be *very careful* when using the value provided in callbacks structs.
|
||||||
|
/// Callbacks are queued, and the value that you will receive in your
|
||||||
|
/// callback is the userdata that was effective at the time the callback
|
||||||
|
/// was queued. There are subtle race conditions that can happen if you
|
||||||
|
/// don't understand this!
|
||||||
|
///
|
||||||
|
/// If any incoming messages for this connection are queued, the userdata
|
||||||
|
/// field is updated, so that when when you receive messages (e.g. with
|
||||||
|
/// ReceiveMessagesOnConnection), they will always have the very latest
|
||||||
|
/// userdata. So the tricky race conditions that can happen with callbacks
|
||||||
|
/// do not apply to retrieving messages.
|
||||||
|
///
|
||||||
|
/// Returns false if the handle is invalid.
|
||||||
|
virtual bool SetConnectionUserData( HSteamNetConnection hPeer, int64 nUserData ) = 0;
|
||||||
|
|
||||||
|
/// Fetch connection user data. Returns -1 if handle is invalid
|
||||||
|
/// or if you haven't set any userdata on the connection.
|
||||||
|
virtual int64 GetConnectionUserData( HSteamNetConnection hPeer ) = 0;
|
||||||
|
|
||||||
|
/// Set a name for the connection, used mostly for debugging
|
||||||
|
virtual void SetConnectionName( HSteamNetConnection hPeer, const char *pszName ) = 0;
|
||||||
|
|
||||||
|
/// Fetch connection name. Returns false if handle is invalid
|
||||||
|
virtual bool GetConnectionName( HSteamNetConnection hPeer, char *pszName, int nMaxLen ) = 0;
|
||||||
|
|
||||||
|
/// Send a message to the remote host on the specified connection.
|
||||||
|
///
|
||||||
|
/// nSendFlags determines the delivery guarantees that will be provided,
|
||||||
|
/// when data should be buffered, etc. E.g. k_nSteamNetworkingSend_Unreliable
|
||||||
|
///
|
||||||
|
/// Note that the semantics we use for messages are not precisely
|
||||||
|
/// the same as the semantics of a standard "stream" socket.
|
||||||
|
/// (SOCK_STREAM) For an ordinary stream socket, the boundaries
|
||||||
|
/// between chunks are not considered relevant, and the sizes of
|
||||||
|
/// the chunks of data written will not necessarily match up to
|
||||||
|
/// the sizes of the chunks that are returned by the reads on
|
||||||
|
/// the other end. The remote host might read a partial chunk,
|
||||||
|
/// or chunks might be coalesced. For the message semantics
|
||||||
|
/// used here, however, the sizes WILL match. Each send call
|
||||||
|
/// will match a successful read call on the remote host
|
||||||
|
/// one-for-one. If you are porting existing stream-oriented
|
||||||
|
/// code to the semantics of reliable messages, your code should
|
||||||
|
/// work the same, since reliable message semantics are more
|
||||||
|
/// strict than stream semantics. The only caveat is related to
|
||||||
|
/// performance: there is per-message overhead to retain the
|
||||||
|
/// message sizes, and so if your code sends many small chunks
|
||||||
|
/// of data, performance will suffer. Any code based on stream
|
||||||
|
/// sockets that does not write excessively small chunks will
|
||||||
|
/// work without any changes.
|
||||||
|
///
|
||||||
|
/// The pOutMessageNumber is an optional pointer to receive the
|
||||||
|
/// message number assigned to the message, if sending was successful.
|
||||||
|
///
|
||||||
|
/// Returns:
|
||||||
|
/// - k_EResultInvalidParam: invalid connection handle, or the individual message is too big.
|
||||||
|
/// (See k_cbMaxSteamNetworkingSocketsMessageSizeSend)
|
||||||
|
/// - k_EResultInvalidState: connection is in an invalid state
|
||||||
|
/// - k_EResultNoConnection: connection has ended
|
||||||
|
/// - k_EResultIgnored: You used k_nSteamNetworkingSend_NoDelay, and the message was dropped because
|
||||||
|
/// we were not ready to send it.
|
||||||
|
/// - k_EResultLimitExceeded: there was already too much data queued to be sent.
|
||||||
|
/// (See k_ESteamNetworkingConfig_SendBufferSize)
|
||||||
|
virtual EResult SendMessageToConnection( HSteamNetConnection hConn, const void *pData, uint32 cbData, int nSendFlags, int64 *pOutMessageNumber ) = 0;
|
||||||
|
|
||||||
|
/// Send one or more messages without copying the message payload.
|
||||||
|
/// This is the most efficient way to send messages. To use this
|
||||||
|
/// function, you must first allocate a message object using
|
||||||
|
/// ISteamNetworkingUtils::AllocateMessage. (Do not declare one
|
||||||
|
/// on the stack or allocate your own.)
|
||||||
|
///
|
||||||
|
/// You should fill in the message payload. You can either let
|
||||||
|
/// it allocate the buffer for you and then fill in the payload,
|
||||||
|
/// or if you already have a buffer allocated, you can just point
|
||||||
|
/// m_pData at your buffer and set the callback to the appropriate function
|
||||||
|
/// to free it. Note that if you use your own buffer, it MUST remain valid
|
||||||
|
/// until the callback is executed. And also note that your callback can be
|
||||||
|
/// invoked at any time from any thread (perhaps even before SendMessages
|
||||||
|
/// returns!), so it MUST be fast and threadsafe.
|
||||||
|
///
|
||||||
|
/// You MUST also fill in:
|
||||||
|
/// - m_conn - the handle of the connection to send the message to
|
||||||
|
/// - m_nFlags - bitmask of k_nSteamNetworkingSend_xxx flags.
|
||||||
|
///
|
||||||
|
/// All other fields are currently reserved and should not be modified.
|
||||||
|
///
|
||||||
|
/// The library will take ownership of the message structures. They may
|
||||||
|
/// be modified or become invalid at any time, so you must not read them
|
||||||
|
/// after passing them to this function.
|
||||||
|
///
|
||||||
|
/// pOutMessageNumberOrResult is an optional array that will receive,
|
||||||
|
/// for each message, the message number that was assigned to the message
|
||||||
|
/// if sending was successful. If sending failed, then a negative EResult
|
||||||
|
/// value is placed into the array. For example, the array will hold
|
||||||
|
/// -k_EResultInvalidState if the connection was in an invalid state.
|
||||||
|
/// See ISteamNetworkingSockets::SendMessageToConnection for possible
|
||||||
|
/// failure codes.
|
||||||
|
virtual void SendMessages( int nMessages, SteamNetworkingMessage_t *const *pMessages, int64 *pOutMessageNumberOrResult ) = 0;
|
||||||
|
|
||||||
|
/// Flush any messages waiting on the Nagle timer and send them
|
||||||
|
/// at the next transmission opportunity (often that means right now).
|
||||||
|
///
|
||||||
|
/// If Nagle is enabled (it's on by default) then when calling
|
||||||
|
/// SendMessageToConnection the message will be buffered, up to the Nagle time
|
||||||
|
/// before being sent, to merge small messages into the same packet.
|
||||||
|
/// (See k_ESteamNetworkingConfig_NagleTime)
|
||||||
|
///
|
||||||
|
/// Returns:
|
||||||
|
/// k_EResultInvalidParam: invalid connection handle
|
||||||
|
/// k_EResultInvalidState: connection is in an invalid state
|
||||||
|
/// k_EResultNoConnection: connection has ended
|
||||||
|
/// k_EResultIgnored: We weren't (yet) connected, so this operation has no effect.
|
||||||
|
virtual EResult FlushMessagesOnConnection( HSteamNetConnection hConn ) = 0;
|
||||||
|
|
||||||
|
/// Fetch the next available message(s) from the connection, if any.
|
||||||
|
/// Returns the number of messages returned into your array, up to nMaxMessages.
|
||||||
|
/// If the connection handle is invalid, -1 is returned.
|
||||||
|
///
|
||||||
|
/// The order of the messages returned in the array is relevant.
|
||||||
|
/// Reliable messages will be received in the order they were sent (and with the
|
||||||
|
/// same sizes --- see SendMessageToConnection for on this subtle difference from a stream socket).
|
||||||
|
///
|
||||||
|
/// Unreliable messages may be dropped, or delivered out of order with respect to
|
||||||
|
/// each other or with respect to reliable messages. The same unreliable message
|
||||||
|
/// may be received multiple times.
|
||||||
|
///
|
||||||
|
/// If any messages are returned, you MUST call SteamNetworkingMessage_t::Release() on each
|
||||||
|
/// of them free up resources after you are done. It is safe to keep the object alive for
|
||||||
|
/// a little while (put it into some queue, etc), and you may call Release() from any thread.
|
||||||
|
virtual int ReceiveMessagesOnConnection( HSteamNetConnection hConn, SteamNetworkingMessage_t **ppOutMessages, int nMaxMessages ) = 0;
|
||||||
|
|
||||||
|
/// Returns basic information about the high-level state of the connection.
|
||||||
|
virtual bool GetConnectionInfo( HSteamNetConnection hConn, SteamNetConnectionInfo_t *pInfo ) = 0;
|
||||||
|
|
||||||
|
// based on reversing the vftable returned from original steamclient64.dll
|
||||||
|
virtual bool GetConnectionRealTimeStatus_old( HSteamNetConnection hConn, SteamNetConnectionRealTimeStatus_t *pStatus ) = 0;
|
||||||
|
|
||||||
|
/// Returns detailed connection stats in text format. Useful
|
||||||
|
/// for dumping to a log, etc.
|
||||||
|
///
|
||||||
|
/// Returns:
|
||||||
|
/// -1 failure (bad connection handle)
|
||||||
|
/// 0 OK, your buffer was filled in and '\0'-terminated
|
||||||
|
/// >0 Your buffer was either nullptr, or it was too small and the text got truncated.
|
||||||
|
/// Try again with a buffer of at least N bytes.
|
||||||
|
virtual int GetDetailedConnectionStatus( HSteamNetConnection hConn, char *pszBuf, int cbBuf ) = 0;
|
||||||
|
|
||||||
|
/// Returns local IP and port that a listen socket created using CreateListenSocketIP is bound to.
|
||||||
|
///
|
||||||
|
/// An IPv6 address of ::0 means "any IPv4 or IPv6"
|
||||||
|
/// An IPv6 address of ::ffff:0000:0000 means "any IPv4"
|
||||||
|
virtual bool GetListenSocketAddress( HSteamListenSocket hSocket, SteamNetworkingIPAddr *address ) = 0;
|
||||||
|
|
||||||
|
/// Create a pair of connections that are talking to each other, e.g. a loopback connection.
|
||||||
|
/// This is very useful for testing, or so that your client/server code can work the same
|
||||||
|
/// even when you are running a local "server".
|
||||||
|
///
|
||||||
|
/// The two connections will immediately be placed into the connected state, and no callbacks
|
||||||
|
/// will be posted immediately. After this, if you close either connection, the other connection
|
||||||
|
/// will receive a callback, exactly as if they were communicating over the network. You must
|
||||||
|
/// close *both* sides in order to fully clean up the resources!
|
||||||
|
///
|
||||||
|
/// By default, internal buffers are used, completely bypassing the network, the chopping up of
|
||||||
|
/// messages into packets, encryption, copying the payload, etc. This means that loopback
|
||||||
|
/// packets, by default, will not simulate lag or loss. Passing true for bUseNetworkLoopback will
|
||||||
|
/// cause the socket pair to send packets through the local network loopback device (127.0.0.1)
|
||||||
|
/// on ephemeral ports. Fake lag and loss are supported in this case, and CPU time is expended
|
||||||
|
/// to encrypt and decrypt.
|
||||||
|
///
|
||||||
|
/// If you wish to assign a specific identity to either connection, you may pass a particular
|
||||||
|
/// identity. Otherwise, if you pass nullptr, the respective connection will assume a generic
|
||||||
|
/// "localhost" identity. If you use real network loopback, this might be translated to the
|
||||||
|
/// actual bound loopback port. Otherwise, the port will be zero.
|
||||||
|
virtual bool CreateSocketPair( HSteamNetConnection *pOutConnection1, HSteamNetConnection *pOutConnection2, bool bUseNetworkLoopback, const SteamNetworkingIdentity *pIdentity1, const SteamNetworkingIdentity *pIdentity2 ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Identity and authentication
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Get the identity assigned to this interface.
|
||||||
|
/// E.g. on Steam, this is the user's SteamID, or for the gameserver interface, the SteamID assigned
|
||||||
|
/// to the gameserver. Returns false and sets the result to an invalid identity if we don't know
|
||||||
|
/// our identity yet. (E.g. GameServer has not logged in. On Steam, the user will know their SteamID
|
||||||
|
/// even if they are not signed into Steam.)
|
||||||
|
virtual bool GetIdentity( SteamNetworkingIdentity *pIdentity ) = 0;
|
||||||
|
|
||||||
|
/// Indicate our desire to be ready participate in authenticated communications.
|
||||||
|
/// If we are currently not ready, then steps will be taken to obtain the necessary
|
||||||
|
/// certificates. (This includes a certificate for us, as well as any CA certificates
|
||||||
|
/// needed to authenticate peers.)
|
||||||
|
///
|
||||||
|
/// You can call this at program init time if you know that you are going to
|
||||||
|
/// be making authenticated connections, so that we will be ready immediately when
|
||||||
|
/// those connections are attempted. (Note that essentially all connections require
|
||||||
|
/// authentication, with the exception of ordinary UDP connections with authentication
|
||||||
|
/// disabled using k_ESteamNetworkingConfig_IP_AllowWithoutAuth.) If you don't call
|
||||||
|
/// this function, we will wait until a feature is utilized that that necessitates
|
||||||
|
/// these resources.
|
||||||
|
///
|
||||||
|
/// You can also call this function to force a retry, if failure has occurred.
|
||||||
|
/// Once we make an attempt and fail, we will not automatically retry.
|
||||||
|
/// In this respect, the behavior of the system after trying and failing is the same
|
||||||
|
/// as before the first attempt: attempting authenticated communication or calling
|
||||||
|
/// this function will call the system to attempt to acquire the necessary resources.
|
||||||
|
///
|
||||||
|
/// You can use GetAuthenticationStatus or listen for SteamNetAuthenticationStatus_t
|
||||||
|
/// to monitor the status.
|
||||||
|
///
|
||||||
|
/// Returns the current value that would be returned from GetAuthenticationStatus.
|
||||||
|
virtual ESteamNetworkingAvailability InitAuthentication() = 0;
|
||||||
|
|
||||||
|
/// Query our readiness to participate in authenticated communications. A
|
||||||
|
/// SteamNetAuthenticationStatus_t callback is posted any time this status changes,
|
||||||
|
/// but you can use this function to query it at any time.
|
||||||
|
///
|
||||||
|
/// The value of SteamNetAuthenticationStatus_t::m_eAvail is returned. If you only
|
||||||
|
/// want this high level status, you can pass NULL for pDetails. If you want further
|
||||||
|
/// details, pass non-NULL to receive them.
|
||||||
|
virtual ESteamNetworkingAvailability GetAuthenticationStatus( SteamNetAuthenticationStatus_t *pDetails ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Poll groups. A poll group is a set of connections that can be polled efficiently.
|
||||||
|
// (In our API, to "poll" a connection means to retrieve all pending messages. We
|
||||||
|
// actually don't have an API to "poll" the connection *state*, like BSD sockets.)
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Create a new poll group.
|
||||||
|
///
|
||||||
|
/// You should destroy the poll group when you are done using DestroyPollGroup
|
||||||
|
virtual HSteamNetPollGroup CreatePollGroup() = 0;
|
||||||
|
|
||||||
|
/// Destroy a poll group created with CreatePollGroup().
|
||||||
|
///
|
||||||
|
/// If there are any connections in the poll group, they are removed from the group,
|
||||||
|
/// and left in a state where they are not part of any poll group.
|
||||||
|
/// Returns false if passed an invalid poll group handle.
|
||||||
|
virtual bool DestroyPollGroup( HSteamNetPollGroup hPollGroup ) = 0;
|
||||||
|
|
||||||
|
/// Assign a connection to a poll group. Note that a connection may only belong to a
|
||||||
|
/// single poll group. Adding a connection to a poll group implicitly removes it from
|
||||||
|
/// any other poll group it is in.
|
||||||
|
///
|
||||||
|
/// You can pass k_HSteamNetPollGroup_Invalid to remove a connection from its current
|
||||||
|
/// poll group without adding it to a new poll group.
|
||||||
|
///
|
||||||
|
/// If there are received messages currently pending on the connection, an attempt
|
||||||
|
/// is made to add them to the queue of messages for the poll group in approximately
|
||||||
|
/// the order that would have applied if the connection was already part of the poll
|
||||||
|
/// group at the time that the messages were received.
|
||||||
|
///
|
||||||
|
/// Returns false if the connection handle is invalid, or if the poll group handle
|
||||||
|
/// is invalid (and not k_HSteamNetPollGroup_Invalid).
|
||||||
|
virtual bool SetConnectionPollGroup( HSteamNetConnection hConn, HSteamNetPollGroup hPollGroup ) = 0;
|
||||||
|
|
||||||
|
/// Same as ReceiveMessagesOnConnection, but will return the next messages available
|
||||||
|
/// on any connection in the poll group. Examine SteamNetworkingMessage_t::m_conn
|
||||||
|
/// to know which connection. (SteamNetworkingMessage_t::m_nConnUserData might also
|
||||||
|
/// be useful.)
|
||||||
|
///
|
||||||
|
/// Delivery order of messages among different connections will usually match the
|
||||||
|
/// order that the last packet was received which completed the message. But this
|
||||||
|
/// is not a strong guarantee, especially for packets received right as a connection
|
||||||
|
/// is being assigned to poll group.
|
||||||
|
///
|
||||||
|
/// Delivery order of messages on the same connection is well defined and the
|
||||||
|
/// same guarantees are present as mentioned in ReceiveMessagesOnConnection.
|
||||||
|
/// (But the messages are not grouped by connection, so they will not necessarily
|
||||||
|
/// appear consecutively in the list; they may be interleaved with messages for
|
||||||
|
/// other connections.)
|
||||||
|
virtual int ReceiveMessagesOnPollGroup( HSteamNetPollGroup hPollGroup, SteamNetworkingMessage_t **ppOutMessages, int nMaxMessages ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Clients connecting to dedicated servers hosted in a data center,
|
||||||
|
// using tickets issued by your game coordinator. If you are not
|
||||||
|
// issuing your own tickets to restrict who can attempt to connect
|
||||||
|
// to your server, then you won't use these functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Call this when you receive a ticket from your backend / matchmaking system. Puts the
|
||||||
|
/// ticket into a persistent cache, and optionally returns the parsed ticket.
|
||||||
|
///
|
||||||
|
/// See stamdatagram_ticketgen.h for more details.
|
||||||
|
virtual bool ReceivedRelayAuthTicket( const void *pvTicket, int cbTicket, SteamDatagramRelayAuthTicket *pOutParsedTicket ) = 0;
|
||||||
|
|
||||||
|
/// Search cache for a ticket to talk to the server on the specified virtual port.
|
||||||
|
/// If found, returns the number of seconds until the ticket expires, and optionally
|
||||||
|
/// the complete cracked ticket. Returns 0 if we don't have a ticket.
|
||||||
|
///
|
||||||
|
/// Typically this is useful just to confirm that you have a ticket, before you
|
||||||
|
/// call ConnectToHostedDedicatedServer to connect to the server.
|
||||||
|
virtual int FindRelayAuthTicketForServer( const SteamNetworkingIdentity &identityGameServer, int nRemoteVirtualPort, SteamDatagramRelayAuthTicket *pOutParsedTicket ) = 0;
|
||||||
|
|
||||||
|
/// Client call to connect to a server hosted in a Valve data center, on the specified virtual
|
||||||
|
/// port. You must have placed a ticket for this server into the cache, or else this connect
|
||||||
|
/// attempt will fail! If you are not issuing your own tickets, then to connect to a dedicated
|
||||||
|
/// server via SDR in auto-ticket mode, use ConnectP2P. (The server must be configured to allow
|
||||||
|
/// this type of connection by listening using CreateListenSocketP2P.)
|
||||||
|
///
|
||||||
|
/// You may wonder why tickets are stored in a cache, instead of simply being passed as an argument
|
||||||
|
/// here. The reason is to make reconnection to a gameserver robust, even if the client computer loses
|
||||||
|
/// connection to Steam or the central backend, or the app is restarted or crashes, etc.
|
||||||
|
///
|
||||||
|
/// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
|
||||||
|
/// when your app initializes
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
virtual HSteamNetConnection ConnectToHostedDedicatedServer( const SteamNetworkingIdentity &identityTarget, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Servers hosted in data centers known to the Valve relay network
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Returns the value of the SDR_LISTEN_PORT environment variable. This
|
||||||
|
/// is the UDP server your server will be listening on. This will
|
||||||
|
/// configured automatically for you in production environments.
|
||||||
|
///
|
||||||
|
/// In development, you'll need to set it yourself. See
|
||||||
|
/// https://partner.steamgames.com/doc/api/ISteamNetworkingSockets
|
||||||
|
/// for more information on how to configure dev environments.
|
||||||
|
virtual uint16 GetHostedDedicatedServerPort() = 0;
|
||||||
|
|
||||||
|
/// Returns 0 if SDR_LISTEN_PORT is not set. Otherwise, returns the data center the server
|
||||||
|
/// is running in. This will be k_SteamDatagramPOPID_dev in non-production environment.
|
||||||
|
virtual SteamNetworkingPOPID GetHostedDedicatedServerPOPID() = 0;
|
||||||
|
|
||||||
|
/// Return info about the hosted server. This contains the PoPID of the server,
|
||||||
|
/// and opaque routing information that can be used by the relays to send traffic
|
||||||
|
/// to your server.
|
||||||
|
///
|
||||||
|
/// You will need to send this information to your backend, and put it in tickets,
|
||||||
|
/// so that the relays will know how to forward traffic from
|
||||||
|
/// clients to your server. See SteamDatagramRelayAuthTicket for more info.
|
||||||
|
///
|
||||||
|
/// Also, note that the routing information is contained in SteamDatagramGameCoordinatorServerLogin,
|
||||||
|
/// so if possible, it's preferred to use GetGameCoordinatorServerLogin to send this info
|
||||||
|
/// to your game coordinator service, and also login securely at the same time.
|
||||||
|
///
|
||||||
|
/// On a successful exit, k_EResultOK is returned
|
||||||
|
///
|
||||||
|
/// Unsuccessful exit:
|
||||||
|
/// - Something other than k_EResultOK is returned.
|
||||||
|
/// - k_EResultInvalidState: We are not configured to listen for SDR (SDR_LISTEN_SOCKET
|
||||||
|
/// is not set.)
|
||||||
|
/// - k_EResultPending: we do not (yet) have the authentication information needed.
|
||||||
|
/// (See GetAuthenticationStatus.) If you use environment variables to pre-fetch
|
||||||
|
/// the network config, this data should always be available immediately.
|
||||||
|
/// - A non-localized diagnostic debug message will be placed in m_data that describes
|
||||||
|
/// the cause of the failure.
|
||||||
|
///
|
||||||
|
/// NOTE: The returned blob is not encrypted. Send it to your backend, but don't
|
||||||
|
/// directly share it with clients.
|
||||||
|
virtual EResult GetHostedDedicatedServerAddress( SteamDatagramHostedAddress *pRouting ) = 0;
|
||||||
|
|
||||||
|
/// Create a listen socket on the specified virtual port. The physical UDP port to use
|
||||||
|
/// will be determined by the SDR_LISTEN_PORT environment variable. If a UDP port is not
|
||||||
|
/// configured, this call will fail.
|
||||||
|
///
|
||||||
|
/// This call MUST be made through the SteamGameServerNetworkingSockets() interface.
|
||||||
|
///
|
||||||
|
/// This function should be used when you are using the ticket generator library
|
||||||
|
/// to issue your own tickets. Clients connecting to the server on this virtual
|
||||||
|
/// port will need a ticket, and they must connect using ConnectToHostedDedicatedServer.
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
virtual HSteamListenSocket CreateHostedDedicatedServerListenSocket( int nLocalVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Generate an authentication blob that can be used to securely login with
|
||||||
|
/// your backend, using SteamDatagram_ParseHostedServerLogin. (See
|
||||||
|
/// steamdatagram_gamecoordinator.h)
|
||||||
|
///
|
||||||
|
/// Before calling the function:
|
||||||
|
/// - Populate the app data in pLoginInfo (m_cbAppData and m_appData). You can leave
|
||||||
|
/// all other fields uninitialized.
|
||||||
|
/// - *pcbSignedBlob contains the size of the buffer at pBlob. (It should be
|
||||||
|
/// at least k_cbMaxSteamDatagramGameCoordinatorServerLoginSerialized.)
|
||||||
|
///
|
||||||
|
/// On a successful exit:
|
||||||
|
/// - k_EResultOK is returned
|
||||||
|
/// - All of the remaining fields of pLoginInfo will be filled out.
|
||||||
|
/// - *pcbSignedBlob contains the size of the serialized blob that has been
|
||||||
|
/// placed into pBlob.
|
||||||
|
///
|
||||||
|
/// Unsuccessful exit:
|
||||||
|
/// - Something other than k_EResultOK is returned.
|
||||||
|
/// - k_EResultNotLoggedOn: you are not logged in (yet)
|
||||||
|
/// - See GetHostedDedicatedServerAddress for more potential failure return values.
|
||||||
|
/// - A non-localized diagnostic debug message will be placed in pBlob that describes
|
||||||
|
/// the cause of the failure.
|
||||||
|
///
|
||||||
|
/// This works by signing the contents of the SteamDatagramGameCoordinatorServerLogin
|
||||||
|
/// with the cert that is issued to this server. In dev environments, it's OK if you do
|
||||||
|
/// not have a cert. (You will need to enable insecure dev login in SteamDatagram_ParseHostedServerLogin.)
|
||||||
|
/// Otherwise, you will need a signed cert.
|
||||||
|
///
|
||||||
|
/// NOTE: The routing blob returned here is not encrypted. Send it to your backend
|
||||||
|
/// and don't share it directly with clients.
|
||||||
|
virtual EResult GetGameCoordinatorServerLogin( SteamDatagramGameCoordinatorServerLogin *pLoginInfo, int *pcbSignedBlob, void *pBlob ) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Relayed connections using custom signaling protocol
|
||||||
|
//
|
||||||
|
// This is used if you have your own method of sending out-of-band
|
||||||
|
// signaling / rendezvous messages through a mutually trusted channel.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Create a P2P "client" connection that does signaling over a custom
|
||||||
|
/// rendezvous/signaling channel.
|
||||||
|
///
|
||||||
|
/// pSignaling points to a new object that you create just for this connection.
|
||||||
|
/// It must stay valid until Release() is called. Once you pass the
|
||||||
|
/// object to this function, it assumes ownership. Release() will be called
|
||||||
|
/// from within the function call if the call fails. Furthermore, until Release()
|
||||||
|
/// is called, you should be prepared for methods to be invoked on your
|
||||||
|
/// object from any thread! You need to make sure your object is threadsafe!
|
||||||
|
/// Furthermore, you should make sure that dispatching the methods is done
|
||||||
|
/// as quickly as possible.
|
||||||
|
///
|
||||||
|
/// This function will immediately construct a connection in the "connecting"
|
||||||
|
/// state. Soon after (perhaps before this function returns, perhaps in another thread),
|
||||||
|
/// the connection will begin sending signaling messages by calling
|
||||||
|
/// ISteamNetworkingConnectionSignaling::SendSignal.
|
||||||
|
///
|
||||||
|
/// When the remote peer accepts the connection (See
|
||||||
|
/// ISteamNetworkingSignalingRecvContext::OnConnectRequest),
|
||||||
|
/// it will begin sending signaling messages. When these messages are received,
|
||||||
|
/// you can pass them to the connection using ReceivedP2PCustomSignal.
|
||||||
|
///
|
||||||
|
/// If you know the identity of the peer that you expect to be on the other end,
|
||||||
|
/// you can pass their identity to improve debug output or just detect bugs.
|
||||||
|
/// If you don't know their identity yet, you can pass NULL, and their
|
||||||
|
/// identity will be established in the connection handshake.
|
||||||
|
///
|
||||||
|
/// If you use this, you probably want to call ISteamNetworkingUtils::InitRelayNetworkAccess()
|
||||||
|
/// when your app initializes
|
||||||
|
///
|
||||||
|
/// If you need to set any initial config options, pass them here. See
|
||||||
|
/// SteamNetworkingConfigValue_t for more about why this is preferable to
|
||||||
|
/// setting the options "immediately" after creation.
|
||||||
|
//virtual HSteamNetConnection ConnectP2PCustomSignaling( ISteamNetworkingConnectionCustomSignaling *pSignaling, const SteamNetworkingIdentity *pPeerIdentity, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
virtual HSteamNetConnection ConnectP2PCustomSignaling( ISteamNetworkingConnectionSignaling *pSignaling, const SteamNetworkingIdentity *pPeerIdentity, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// Called when custom signaling has received a message. When your
|
||||||
|
/// signaling channel receives a message, it should save off whatever
|
||||||
|
/// routing information was in the envelope into the context object,
|
||||||
|
/// and then pass the payload to this function.
|
||||||
|
///
|
||||||
|
/// A few different things can happen next, depending on the message:
|
||||||
|
///
|
||||||
|
/// - If the signal is associated with existing connection, it is dealt
|
||||||
|
/// with immediately. If any replies need to be sent, they will be
|
||||||
|
/// dispatched using the ISteamNetworkingConnectionSignaling
|
||||||
|
/// associated with the connection.
|
||||||
|
/// - If the message represents a connection request (and the request
|
||||||
|
/// is not redundant for an existing connection), a new connection
|
||||||
|
/// will be created, and ReceivedConnectRequest will be called on your
|
||||||
|
/// context object to determine how to proceed.
|
||||||
|
/// - Otherwise, the message is for a connection that does not
|
||||||
|
/// exist (anymore). In this case, we *may* call SendRejectionReply
|
||||||
|
/// on your context object.
|
||||||
|
///
|
||||||
|
/// In any case, we will not save off pContext or access it after this
|
||||||
|
/// function returns.
|
||||||
|
///
|
||||||
|
/// Returns true if the message was parsed and dispatched without anything
|
||||||
|
/// unusual or suspicious happening. Returns false if there was some problem
|
||||||
|
/// with the message that prevented ordinary handling. (Debug output will
|
||||||
|
/// usually have more information.)
|
||||||
|
///
|
||||||
|
/// If you expect to be using relayed connections, then you probably want
|
||||||
|
/// to call ISteamNetworkingUtils::InitRelayNetworkAccess() when your app initializes
|
||||||
|
//virtual bool ReceivedP2PCustomSignal( const void *pMsg, int cbMsg, ISteamNetworkingCustomSignalingRecvContext *pContext ) = 0;
|
||||||
|
virtual bool ReceivedP2PCustomSignal( const void *pMsg, int cbMsg, ISteamNetworkingSignalingRecvContext *pContext ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Certificate provision by the application. On Steam, we normally handle all this automatically
|
||||||
|
// and you will not need to use these advanced functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Get blob that describes a certificate request. You can send this to your game coordinator.
|
||||||
|
/// Upon entry, *pcbBlob should contain the size of the buffer. On successful exit, it will
|
||||||
|
/// return the number of bytes that were populated. You can pass pBlob=NULL to query for the required
|
||||||
|
/// size. (512 bytes is a conservative estimate.)
|
||||||
|
///
|
||||||
|
/// Pass this blob to your game coordinator and call SteamDatagram_CreateCert.
|
||||||
|
virtual bool GetCertificateRequest( int *pcbBlob, void *pBlob, SteamNetworkingErrMsg &errMsg ) = 0;
|
||||||
|
|
||||||
|
/// Set the certificate. The certificate blob should be the output of
|
||||||
|
/// SteamDatagram_CreateCert.
|
||||||
|
virtual bool SetCertificate( const void *pCertificate, int cbCertificate, SteamNetworkingErrMsg &errMsg ) = 0;
|
||||||
|
|
||||||
|
/// Reset the identity associated with this instance.
|
||||||
|
/// Any open connections are closed. Any previous certificates, etc are discarded.
|
||||||
|
/// You can pass a specific identity that you want to use, or you can pass NULL,
|
||||||
|
/// in which case the identity will be invalid until you set it using SetCertificate
|
||||||
|
///
|
||||||
|
/// NOTE: This function is not actually supported on Steam! It is included
|
||||||
|
/// for use on other platforms where the active user can sign out and
|
||||||
|
/// a new user can sign in.
|
||||||
|
virtual void ResetIdentity( const SteamNetworkingIdentity *pIdentity ) = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Misc
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Invoke all callback functions queued for this interface.
|
||||||
|
/// See k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, etc
|
||||||
|
///
|
||||||
|
/// You don't need to call this if you are using Steam's callback dispatch
|
||||||
|
/// mechanism (SteamAPI_RunCallbacks and SteamGameserver_RunCallbacks).
|
||||||
|
virtual void RunCallbacks() = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// "FakeIP" system.
|
||||||
|
//
|
||||||
|
// A FakeIP is essentially a temporary, arbitrary identifier that
|
||||||
|
// happens to be a valid IPv4 address. The purpose of this system is to make it
|
||||||
|
// easy to integrate with existing code that identifies hosts using IPv4 addresses.
|
||||||
|
// The FakeIP address will never actually be used to send or receive any packets
|
||||||
|
// on the Internet, it is strictly an identifier.
|
||||||
|
//
|
||||||
|
// FakeIP addresses are designed to (hopefully) pass through existing code as
|
||||||
|
// transparently as possible, while conflicting with "real" addresses that might
|
||||||
|
// be in use on networks (both the Internet and LANs) in the same code as little
|
||||||
|
// as possible. At the time this comment is being written, they come from the
|
||||||
|
// 169.254.0.0/16 range, and the port number will always be >1024. HOWEVER,
|
||||||
|
// this is subject to change! Do not make assumptions about these addresses,
|
||||||
|
// or your code might break in the future. In particular, you should use
|
||||||
|
// functions such as ISteamNetworkingUtils::IsFakeIP to determine if an IP
|
||||||
|
// address is a "fake" one used by this system.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Begin asynchronous process of allocating a fake IPv4 address that other
|
||||||
|
/// peers can use to contact us via P2P. IP addresses returned by this
|
||||||
|
/// function are globally unique for a given appid.
|
||||||
|
///
|
||||||
|
/// nNumPorts is the numbers of ports you wish to reserve. This is useful
|
||||||
|
/// for the same reason that listening on multiple UDP ports is useful for
|
||||||
|
/// different types of traffic. Because these allocations come from a global
|
||||||
|
/// namespace, there is a relatively strict limit on the maximum number of
|
||||||
|
/// ports you may request. (At the time of this writing, the limit is 4.)
|
||||||
|
/// The port assignments are *not* guaranteed to have any particular order
|
||||||
|
/// or relationship! Do *not* assume they are contiguous, even though that
|
||||||
|
/// may often occur in practice.
|
||||||
|
///
|
||||||
|
/// Returns false if a request was already in progress, true if a new request
|
||||||
|
/// was started. A SteamNetworkingFakeIPResult_t will be posted when the request
|
||||||
|
/// completes.
|
||||||
|
///
|
||||||
|
/// For gameservers, you *must* call this after initializing the SDK but before
|
||||||
|
/// beginning login. Steam needs to know in advance that FakeIP will be used.
|
||||||
|
/// Everywhere your public IP would normally appear (such as the server browser) will be
|
||||||
|
/// replaced by the FakeIP, and the fake port at index 0. The request is actually queued
|
||||||
|
/// until the logon completes, so you must not wait until the allocation completes
|
||||||
|
/// before logging in. Except for trivial failures that can be detected locally
|
||||||
|
/// (e.g. invalid parameter), a SteamNetworkingFakeIPResult_t callback (whether success or
|
||||||
|
/// failure) will not be posted until after we have logged in. Furthermore, it is assumed
|
||||||
|
/// that FakeIP allocation is essential for your application to function, and so failure
|
||||||
|
/// will not be reported until *several* retries have been attempted. This process may
|
||||||
|
/// last several minutes. It is *highly* recommended to treat failure as fatal.
|
||||||
|
///
|
||||||
|
/// To communicate using a connection-oriented (TCP-style) API:
|
||||||
|
/// - Server creates a listen socket using CreateListenSocketP2PFakeIP
|
||||||
|
/// - Client connects using ConnectByIPAddress, passing in the FakeIP address.
|
||||||
|
/// - The connection will behave mostly like a P2P connection. The identities
|
||||||
|
/// that appear in SteamNetConnectionInfo_t will be the FakeIP identity until
|
||||||
|
/// we know the real identity. Then it will be the real identity. If the
|
||||||
|
/// SteamNetConnectionInfo_t::m_addrRemote is valid, it will be a real IPv4
|
||||||
|
/// address of a NAT-punched connection. Otherwise, it will not be valid.
|
||||||
|
///
|
||||||
|
/// To communicate using an ad-hoc sendto/recv from (UDP-style) API,
|
||||||
|
/// use CreateFakeUDPPort.
|
||||||
|
virtual bool BeginAsyncRequestFakeIP( int nNumPorts ) = 0;
|
||||||
|
|
||||||
|
/// Return info about the FakeIP and port(s) that we have been assigned,
|
||||||
|
/// if any. idxFirstPort is currently reserved and must be zero.
|
||||||
|
/// Make sure and check SteamNetworkingFakeIPResult_t::m_eResult
|
||||||
|
virtual void GetFakeIP( int idxFirstPort, SteamNetworkingFakeIPResult_t *pInfo ) = 0;
|
||||||
|
|
||||||
|
/// Create a listen socket that will listen for P2P connections sent
|
||||||
|
/// to our FakeIP. A peer can initiate connections to this listen
|
||||||
|
/// socket by calling ConnectByIPAddress.
|
||||||
|
///
|
||||||
|
/// idxFakePort refers to the *index* of the fake port requested,
|
||||||
|
/// not the actual port number. For example, pass 0 to refer to the
|
||||||
|
/// first port in the reservation. You must call this only after calling
|
||||||
|
/// BeginAsyncRequestFakeIP. However, you do not need to wait for the
|
||||||
|
/// request to complete before creating the listen socket.
|
||||||
|
virtual HSteamListenSocket CreateListenSocketP2PFakeIP( int idxFakePort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
|
||||||
|
|
||||||
|
/// If the connection was initiated using the "FakeIP" system, then we
|
||||||
|
/// we can get an IP address for the remote host. If the remote host had
|
||||||
|
/// a global FakeIP at the time the connection was established, this
|
||||||
|
/// function will return that global IP. Otherwise, a FakeIP that is
|
||||||
|
/// unique locally will be allocated from the local FakeIP address space,
|
||||||
|
/// and that will be returned.
|
||||||
|
///
|
||||||
|
/// The allocation of local FakeIPs attempts to assign addresses in
|
||||||
|
/// a consistent manner. If multiple connections are made to the
|
||||||
|
/// same remote host, they *probably* will return the same FakeIP.
|
||||||
|
/// However, since the namespace is limited, this cannot be guaranteed.
|
||||||
|
///
|
||||||
|
/// On failure, returns:
|
||||||
|
/// - k_EResultInvalidParam: invalid connection handle
|
||||||
|
/// - k_EResultIPNotFound: This connection wasn't made using FakeIP system
|
||||||
|
virtual EResult GetRemoteFakeIPForConnection( HSteamNetConnection hConn, SteamNetworkingIPAddr *pOutAddr ) = 0;
|
||||||
|
|
||||||
|
/// Get an interface that can be used like a UDP port to send/receive
|
||||||
|
/// datagrams to a FakeIP address. This is intended to make it easy
|
||||||
|
/// to port existing UDP-based code to take advantage of SDR.
|
||||||
|
///
|
||||||
|
/// idxFakeServerPort refers to the *index* of the port allocated using
|
||||||
|
/// BeginAsyncRequestFakeIP and is used to create "server" ports. You may
|
||||||
|
/// call this before the allocation has completed. However, any attempts
|
||||||
|
/// to send packets will fail until the allocation has succeeded. When
|
||||||
|
/// the peer receives packets sent from this interface, the from address
|
||||||
|
/// of the packet will be the globally-unique FakeIP. If you call this
|
||||||
|
/// function multiple times and pass the same (nonnegative) fake port index,
|
||||||
|
/// the same object will be returned, and this object is not reference counted.
|
||||||
|
///
|
||||||
|
/// To create a "client" port (e.g. the equivalent of an ephemeral UDP port)
|
||||||
|
/// pass -1. In this case, a distinct object will be returned for each call.
|
||||||
|
/// When the peer receives packets sent from this interface, the peer will
|
||||||
|
/// assign a FakeIP from its own locally-controlled namespace.
|
||||||
|
virtual ISteamNetworkingFakeUDPPort *CreateFakeUDPPort( int idxFakeServerPort ) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// ~ISteamNetworkingSockets(); // Silence some warnings
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ISTEAMNETWORKINGSOCKETS011
|
147
sdk/steam/isteamremotestorage015.h
Normal file
147
sdk/steam/isteamremotestorage015.h
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
#ifndef ISTEAMREMOTESTORAGE015_H
|
||||||
|
#define ISTEAMREMOTESTORAGE015_H
|
||||||
|
#ifdef STEAM_WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// this interface version is not found in public SDK archives, it is based on reversing the returned vftable from steamclient64.dll
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Functions for accessing, reading and writing files stored remotely
|
||||||
|
// and cached locally
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ISteamRemoteStorage015
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// NOTE
|
||||||
|
//
|
||||||
|
// Filenames are case-insensitive, and will be converted to lowercase automatically.
|
||||||
|
// So "foo.bar" and "Foo.bar" are the same file, and if you write "Foo.bar" then
|
||||||
|
// iterate the files, the filename returned will be "foo.bar".
|
||||||
|
//
|
||||||
|
|
||||||
|
// file operations
|
||||||
|
virtual bool FileWrite( const char *pchFile, const void *pvData, int32 cubData ) = 0;
|
||||||
|
virtual int32 FileRead( const char *pchFile, void *pvData, int32 cubDataToRead ) = 0;
|
||||||
|
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageFileWriteAsyncComplete_t )
|
||||||
|
virtual SteamAPICall_t FileWriteAsync( const char *pchFile, const void *pvData, uint32 cubData ) = 0;
|
||||||
|
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageFileReadAsyncComplete_t )
|
||||||
|
virtual SteamAPICall_t FileReadAsync( const char *pchFile, uint32 nOffset, uint32 cubToRead ) = 0;
|
||||||
|
virtual bool FileReadAsyncComplete( SteamAPICall_t hReadCall, void *pvBuffer, uint32 cubToRead ) = 0;
|
||||||
|
|
||||||
|
virtual bool FileForget( const char *pchFile ) = 0;
|
||||||
|
virtual bool FileDelete( const char *pchFile ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageFileShareResult_t )
|
||||||
|
virtual SteamAPICall_t FileShare( const char *pchFile ) = 0;
|
||||||
|
virtual bool SetSyncPlatforms( const char *pchFile, ERemoteStoragePlatform eRemoteStoragePlatform ) = 0;
|
||||||
|
|
||||||
|
// file operations that cause network IO
|
||||||
|
virtual UGCFileWriteStreamHandle_t FileWriteStreamOpen( const char *pchFile ) = 0;
|
||||||
|
virtual bool FileWriteStreamWriteChunk( UGCFileWriteStreamHandle_t writeHandle, const void *pvData, int32 cubData ) = 0;
|
||||||
|
virtual bool FileWriteStreamClose( UGCFileWriteStreamHandle_t writeHandle ) = 0;
|
||||||
|
virtual bool FileWriteStreamCancel( UGCFileWriteStreamHandle_t writeHandle ) = 0;
|
||||||
|
|
||||||
|
// file information
|
||||||
|
virtual bool FileExists( const char *pchFile ) = 0;
|
||||||
|
virtual bool FilePersisted( const char *pchFile ) = 0;
|
||||||
|
virtual int32 GetFileSize( const char *pchFile ) = 0;
|
||||||
|
virtual int64 GetFileTimestamp( const char *pchFile ) = 0;
|
||||||
|
virtual ERemoteStoragePlatform GetSyncPlatforms( const char *pchFile ) = 0;
|
||||||
|
|
||||||
|
// iteration
|
||||||
|
virtual int32 GetFileCount() = 0;
|
||||||
|
virtual const char *GetFileNameAndSize( int iFile, int32 *pnFileSizeInBytes ) = 0;
|
||||||
|
|
||||||
|
// configuration management
|
||||||
|
virtual bool GetQuota( uint64 *pnTotalBytes, uint64 *puAvailableBytes ) = 0;
|
||||||
|
virtual bool IsCloudEnabledForAccount() = 0;
|
||||||
|
virtual bool IsCloudEnabledForApp() = 0;
|
||||||
|
virtual void SetCloudEnabledForApp( bool bEnabled ) = 0;
|
||||||
|
|
||||||
|
// user generated content
|
||||||
|
|
||||||
|
// Downloads a UGC file. A priority value of 0 will download the file immediately,
|
||||||
|
// otherwise it will wait to download the file until all downloads with a lower priority
|
||||||
|
// value are completed. Downloads with equal priority will occur simultaneously.
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageDownloadUGCResult_t )
|
||||||
|
virtual SteamAPICall_t UGCDownload( UGCHandle_t hContent, uint32 unPriority ) = 0;
|
||||||
|
|
||||||
|
// Gets the amount of data downloaded so far for a piece of content. pnBytesExpected can be 0 if function returns false
|
||||||
|
// or if the transfer hasn't started yet, so be careful to check for that before dividing to get a percentage
|
||||||
|
virtual bool GetUGCDownloadProgress( UGCHandle_t hContent, int32 *pnBytesDownloaded, int32 *pnBytesExpected ) = 0;
|
||||||
|
|
||||||
|
// Gets metadata for a file after it has been downloaded. This is the same metadata given in the RemoteStorageDownloadUGCResult_t call result
|
||||||
|
virtual bool GetUGCDetails( UGCHandle_t hContent, AppId_t *pnAppID, STEAM_OUT_STRING() char **ppchName, int32 *pnFileSizeInBytes, STEAM_OUT_STRUCT() CSteamID *pSteamIDOwner ) = 0;
|
||||||
|
|
||||||
|
// After download, gets the content of the file.
|
||||||
|
// Small files can be read all at once by calling this function with an offset of 0 and cubDataToRead equal to the size of the file.
|
||||||
|
// Larger files can be read in chunks to reduce memory usage (since both sides of the IPC client and the game itself must allocate
|
||||||
|
// enough memory for each chunk). Once the last byte is read, the file is implicitly closed and further calls to UGCRead will fail
|
||||||
|
// unless UGCDownload is called again.
|
||||||
|
// For especially large files (anything over 100MB) it is a requirement that the file is read in chunks.
|
||||||
|
virtual int32 UGCRead( UGCHandle_t hContent, void *pvData, int32 cubDataToRead, uint32 cOffset, EUGCReadAction eAction ) = 0;
|
||||||
|
|
||||||
|
// Functions to iterate through UGC that has finished downloading but has not yet been read via UGCRead()
|
||||||
|
virtual int32 GetCachedUGCCount() = 0;
|
||||||
|
virtual UGCHandle_t GetCachedUGCHandle( int32 iCachedContent ) = 0;
|
||||||
|
|
||||||
|
// publishing UGC
|
||||||
|
STEAM_CALL_RESULT( RemoteStoragePublishFileProgress_t )
|
||||||
|
virtual SteamAPICall_t PublishWorkshopFile( const char *pchFile, const char *pchPreviewFile, AppId_t nConsumerAppId, const char *pchTitle, const char *pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, SteamParamStringArray_t *pTags, EWorkshopFileType eWorkshopFileType ) = 0;
|
||||||
|
virtual PublishedFileUpdateHandle_t CreatePublishedFileUpdateRequest( PublishedFileId_t unPublishedFileId ) = 0;
|
||||||
|
virtual bool UpdatePublishedFileFile( PublishedFileUpdateHandle_t updateHandle, const char *pchFile ) = 0;
|
||||||
|
virtual bool UpdatePublishedFilePreviewFile( PublishedFileUpdateHandle_t updateHandle, const char *pchPreviewFile ) = 0;
|
||||||
|
virtual bool UpdatePublishedFileTitle( PublishedFileUpdateHandle_t updateHandle, const char *pchTitle ) = 0;
|
||||||
|
virtual bool UpdatePublishedFileDescription( PublishedFileUpdateHandle_t updateHandle, const char *pchDescription ) = 0;
|
||||||
|
virtual bool UpdatePublishedFileVisibility( PublishedFileUpdateHandle_t updateHandle, ERemoteStoragePublishedFileVisibility eVisibility ) = 0;
|
||||||
|
virtual bool UpdatePublishedFileTags( PublishedFileUpdateHandle_t updateHandle, SteamParamStringArray_t *pTags ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageUpdatePublishedFileResult_t )
|
||||||
|
virtual SteamAPICall_t CommitPublishedFileUpdate( PublishedFileUpdateHandle_t updateHandle ) = 0;
|
||||||
|
// Gets published file details for the given publishedfileid. If unMaxSecondsOld is greater than 0,
|
||||||
|
// cached data may be returned, depending on how long ago it was cached. A value of 0 will force a refresh.
|
||||||
|
// A value of k_WorkshopForceLoadPublishedFileDetailsFromCache will use cached data if it exists, no matter how old it is.
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageGetPublishedFileDetailsResult_t )
|
||||||
|
virtual SteamAPICall_t GetPublishedFileDetails( PublishedFileId_t unPublishedFileId, uint32 unMaxSecondsOld ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageDeletePublishedFileResult_t )
|
||||||
|
virtual SteamAPICall_t DeletePublishedFile( PublishedFileId_t unPublishedFileId ) = 0;
|
||||||
|
// enumerate the files that the current user published with this app
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageEnumerateUserPublishedFilesResult_t )
|
||||||
|
virtual SteamAPICall_t EnumerateUserPublishedFiles( uint32 unStartIndex ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageSubscribePublishedFileResult_t )
|
||||||
|
virtual SteamAPICall_t SubscribePublishedFile( PublishedFileId_t unPublishedFileId ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageEnumerateUserSubscribedFilesResult_t )
|
||||||
|
virtual SteamAPICall_t EnumerateUserSubscribedFiles( uint32 unStartIndex ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageUnsubscribePublishedFileResult_t )
|
||||||
|
virtual SteamAPICall_t UnsubscribePublishedFile( PublishedFileId_t unPublishedFileId ) = 0;
|
||||||
|
virtual bool UpdatePublishedFileSetChangeDescription( PublishedFileUpdateHandle_t updateHandle, const char *pchChangeDescription ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageGetPublishedItemVoteDetailsResult_t )
|
||||||
|
virtual SteamAPICall_t GetPublishedItemVoteDetails( PublishedFileId_t unPublishedFileId ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageUpdateUserPublishedItemVoteResult_t )
|
||||||
|
virtual SteamAPICall_t UpdateUserPublishedItemVote( PublishedFileId_t unPublishedFileId, bool bVoteUp ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageGetPublishedItemVoteDetailsResult_t )
|
||||||
|
virtual SteamAPICall_t GetUserPublishedItemVoteDetails( PublishedFileId_t unPublishedFileId ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageEnumerateUserPublishedFilesResult_t )
|
||||||
|
virtual SteamAPICall_t EnumerateUserSharedWorkshopFiles( CSteamID steamId, uint32 unStartIndex, SteamParamStringArray_t *pRequiredTags, SteamParamStringArray_t *pExcludedTags ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStoragePublishFileProgress_t )
|
||||||
|
virtual SteamAPICall_t PublishVideo( EWorkshopVideoProvider eVideoProvider, const char *pchVideoAccount, const char *pchVideoIdentifier, const char *pchPreviewFile, AppId_t nConsumerAppId, const char *pchTitle, const char *pchDescription, ERemoteStoragePublishedFileVisibility eVisibility, SteamParamStringArray_t *pTags ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageSetUserPublishedFileActionResult_t )
|
||||||
|
virtual SteamAPICall_t SetUserPublishedFileAction( PublishedFileId_t unPublishedFileId, EWorkshopFileAction eAction ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageEnumeratePublishedFilesByUserActionResult_t )
|
||||||
|
virtual SteamAPICall_t EnumeratePublishedFilesByUserAction( EWorkshopFileAction eAction, uint32 unStartIndex ) = 0;
|
||||||
|
// this method enumerates the public view of workshop files
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageEnumerateWorkshopFilesResult_t )
|
||||||
|
virtual SteamAPICall_t EnumeratePublishedWorkshopFiles( EWorkshopEnumerationType eEnumerationType, uint32 unStartIndex, uint32 unCount, uint32 unDays, SteamParamStringArray_t *pTags, SteamParamStringArray_t *pUserTags ) = 0;
|
||||||
|
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageDownloadUGCResult_t )
|
||||||
|
virtual SteamAPICall_t UGCDownloadToLocation( UGCHandle_t hContent, const char *pchLocation, uint32 unPriority ) = 0;
|
||||||
|
|
||||||
|
// Cloud dynamic state change notification
|
||||||
|
virtual int32 GetLocalFileChangeCount() = 0;
|
||||||
|
virtual const char *GetLocalFileChange( int iFile, ERemoteStorageLocalFileChange *pEChangeType, ERemoteStorageFilePathType *pEFilePathType ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ISTEAMREMOTESTORAGE015_H
|
161
sdk/steam/isteamugc011.h
Normal file
161
sdk/steam/isteamugc011.h
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
|
||||||
|
#ifndef ISTEAMUGC011_H
|
||||||
|
#define ISTEAMUGC011_H
|
||||||
|
#ifdef STEAM_WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// this interface version is not found in public SDK archives, it is based on reversing the returned vftable from steamclient64.dll
|
||||||
|
|
||||||
|
class ISteamUGC011
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Query UGC associated with a user. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1.
|
||||||
|
virtual UGCQueryHandle_t CreateQueryUserUGCRequest( AccountID_t unAccountID, EUserUGCList eListType, EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint32 unPage ) = 0;
|
||||||
|
|
||||||
|
// Query for all matching UGC using the new deep paging interface. Creator app id or consumer app id must be valid and be set to the current running app. pchCursor should be set to NULL or "*" to get the first result set.
|
||||||
|
virtual UGCQueryHandle_t CreateQueryAllUGCRequest( EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, const char *pchCursor = NULL ) = 0;
|
||||||
|
|
||||||
|
// Query for the details of the given published file ids (the RequestUGCDetails call is deprecated and replaced with this)
|
||||||
|
virtual UGCQueryHandle_t CreateQueryUGCDetailsRequest( PublishedFileId_t *pvecPublishedFileID, uint32 unNumPublishedFileIDs ) = 0;
|
||||||
|
|
||||||
|
// Send the query to Steam
|
||||||
|
STEAM_CALL_RESULT( SteamUGCQueryCompleted_t )
|
||||||
|
virtual SteamAPICall_t SendQueryUGCRequest( UGCQueryHandle_t handle ) = 0;
|
||||||
|
|
||||||
|
// Retrieve an individual result after receiving the callback for querying UGC
|
||||||
|
virtual bool GetQueryUGCResult( UGCQueryHandle_t handle, uint32 index, SteamUGCDetails_t *pDetails ) = 0;
|
||||||
|
virtual bool GetQueryUGCPreviewURL( UGCQueryHandle_t handle, uint32 index, STEAM_OUT_STRING_COUNT(cchURLSize) char *pchURL, uint32 cchURLSize ) = 0;
|
||||||
|
virtual bool GetQueryUGCMetadata( UGCQueryHandle_t handle, uint32 index, STEAM_OUT_STRING_COUNT(cchMetadatasize) char *pchMetadata, uint32 cchMetadatasize ) = 0;
|
||||||
|
virtual bool GetQueryUGCChildren( UGCQueryHandle_t handle, uint32 index, PublishedFileId_t* pvecPublishedFileID, uint32 cMaxEntries ) = 0;
|
||||||
|
virtual bool GetQueryUGCStatistic( UGCQueryHandle_t handle, uint32 index, EItemStatistic eStatType, uint64 *pStatValue ) = 0;
|
||||||
|
virtual uint32 GetQueryUGCNumAdditionalPreviews( UGCQueryHandle_t handle, uint32 index ) = 0;
|
||||||
|
virtual bool GetQueryUGCAdditionalPreview( UGCQueryHandle_t handle, uint32 index, uint32 previewIndex, STEAM_OUT_STRING_COUNT(cchURLSize) char *pchURLOrVideoID, uint32 cchURLSize, STEAM_OUT_STRING_COUNT(cchURLSize) char *pchOriginalFileName, uint32 cchOriginalFileNameSize, EItemPreviewType *pPreviewType ) = 0;
|
||||||
|
virtual uint32 GetQueryUGCNumKeyValueTags( UGCQueryHandle_t handle, uint32 index ) = 0;
|
||||||
|
virtual bool GetQueryUGCKeyValueTag( UGCQueryHandle_t handle, uint32 index, uint32 keyValueTagIndex, STEAM_OUT_STRING_COUNT(cchKeySize) char *pchKey, uint32 cchKeySize, STEAM_OUT_STRING_COUNT(cchValueSize) char *pchValue, uint32 cchValueSize ) = 0;
|
||||||
|
|
||||||
|
// Release the request to free up memory, after retrieving results
|
||||||
|
virtual bool ReleaseQueryUGCRequest( UGCQueryHandle_t handle ) = 0;
|
||||||
|
|
||||||
|
// Options to set for querying UGC
|
||||||
|
virtual bool AddRequiredTag( UGCQueryHandle_t handle, const char *pTagName ) = 0;
|
||||||
|
virtual bool AddExcludedTag( UGCQueryHandle_t handle, const char *pTagName ) = 0;
|
||||||
|
virtual bool SetReturnOnlyIDs( UGCQueryHandle_t handle, bool bReturnOnlyIDs ) = 0;
|
||||||
|
virtual bool SetReturnKeyValueTags( UGCQueryHandle_t handle, bool bReturnKeyValueTags ) = 0;
|
||||||
|
virtual bool SetReturnLongDescription( UGCQueryHandle_t handle, bool bReturnLongDescription ) = 0;
|
||||||
|
virtual bool SetReturnMetadata( UGCQueryHandle_t handle, bool bReturnMetadata ) = 0;
|
||||||
|
virtual bool SetReturnChildren( UGCQueryHandle_t handle, bool bReturnChildren ) = 0;
|
||||||
|
virtual bool SetReturnAdditionalPreviews( UGCQueryHandle_t handle, bool bReturnAdditionalPreviews ) = 0;
|
||||||
|
virtual bool SetReturnTotalOnly( UGCQueryHandle_t handle, bool bReturnTotalOnly ) = 0;
|
||||||
|
virtual bool SetReturnPlaytimeStats( UGCQueryHandle_t handle, uint32 unDays ) = 0;
|
||||||
|
virtual bool SetLanguage( UGCQueryHandle_t handle, const char *pchLanguage ) = 0;
|
||||||
|
virtual bool SetAllowCachedResponse( UGCQueryHandle_t handle, uint32 unMaxAgeSeconds ) = 0;
|
||||||
|
|
||||||
|
// Options only for querying user UGC
|
||||||
|
virtual bool SetCloudFileNameFilter( UGCQueryHandle_t handle, const char *pMatchCloudFileName ) = 0;
|
||||||
|
|
||||||
|
// Options only for querying all UGC
|
||||||
|
virtual bool SetMatchAnyTag( UGCQueryHandle_t handle, bool bMatchAnyTag ) = 0;
|
||||||
|
virtual bool SetSearchText( UGCQueryHandle_t handle, const char *pSearchText ) = 0;
|
||||||
|
virtual bool SetRankedByTrendDays( UGCQueryHandle_t handle, uint32 unDays ) = 0;
|
||||||
|
virtual bool AddRequiredKeyValueTag( UGCQueryHandle_t handle, const char *pKey, const char *pValue ) = 0;
|
||||||
|
|
||||||
|
// DEPRECATED - Use CreateQueryUGCDetailsRequest call above instead!
|
||||||
|
virtual SteamAPICall_t RequestUGCDetails( PublishedFileId_t nPublishedFileID, uint32 unMaxAgeSeconds ) = 0;
|
||||||
|
|
||||||
|
// Steam Workshop Creator API
|
||||||
|
STEAM_CALL_RESULT( CreateItemResult_t )
|
||||||
|
virtual SteamAPICall_t CreateItem( AppId_t nConsumerAppId, EWorkshopFileType eFileType ) = 0; // create new item for this app with no content attached yet
|
||||||
|
|
||||||
|
virtual UGCUpdateHandle_t StartItemUpdate( AppId_t nConsumerAppId, PublishedFileId_t nPublishedFileID ) = 0; // start an UGC item update. Set changed properties before commiting update with CommitItemUpdate()
|
||||||
|
|
||||||
|
virtual bool SetItemTitle( UGCUpdateHandle_t handle, const char *pchTitle ) = 0; // change the title of an UGC item
|
||||||
|
virtual bool SetItemDescription( UGCUpdateHandle_t handle, const char *pchDescription ) = 0; // change the description of an UGC item
|
||||||
|
virtual bool SetItemUpdateLanguage( UGCUpdateHandle_t handle, const char *pchLanguage ) = 0; // specify the language of the title or description that will be set
|
||||||
|
virtual bool SetItemMetadata( UGCUpdateHandle_t handle, const char *pchMetaData ) = 0; // change the metadata of an UGC item (max = k_cchDeveloperMetadataMax)
|
||||||
|
virtual bool SetItemVisibility( UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility eVisibility ) = 0; // change the visibility of an UGC item
|
||||||
|
virtual bool SetItemTags( UGCUpdateHandle_t updateHandle, const SteamParamStringArray_t *pTags ) = 0; // change the tags of an UGC item
|
||||||
|
virtual bool SetItemContent( UGCUpdateHandle_t handle, const char *pszContentFolder ) = 0; // update item content from this local folder
|
||||||
|
virtual bool SetItemPreview( UGCUpdateHandle_t handle, const char *pszPreviewFile ) = 0; // change preview image file for this item. pszPreviewFile points to local image file, which must be under 1MB in size
|
||||||
|
virtual bool SetAllowLegacyUpload( UGCUpdateHandle_t handle, bool bAllowLegacyUpload ) = 0; // use legacy upload for a single small file. The parameter to SetItemContent() should either be a directory with one file or the full path to the file. The file must also be less than 10MB in size.
|
||||||
|
virtual bool RemoveItemKeyValueTags( UGCUpdateHandle_t handle, const char *pchKey ) = 0; // remove any existing key-value tags with the specified key
|
||||||
|
virtual bool AddItemKeyValueTag( UGCUpdateHandle_t handle, const char *pchKey, const char *pchValue ) = 0; // add new key-value tags for the item. Note that there can be multiple values for a tag.
|
||||||
|
virtual bool AddItemPreviewFile( UGCUpdateHandle_t handle, const char *pszPreviewFile, EItemPreviewType type ) = 0; // add preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size
|
||||||
|
virtual bool AddItemPreviewVideo( UGCUpdateHandle_t handle, const char *pszVideoID ) = 0; // add preview video for this item
|
||||||
|
virtual bool UpdateItemPreviewFile( UGCUpdateHandle_t handle, uint32 index, const char *pszPreviewFile ) = 0; // updates an existing preview file for this item. pszPreviewFile points to local file, which must be under 1MB in size
|
||||||
|
virtual bool UpdateItemPreviewVideo( UGCUpdateHandle_t handle, uint32 index, const char *pszVideoID ) = 0; // updates an existing preview video for this item
|
||||||
|
virtual bool RemoveItemPreview( UGCUpdateHandle_t handle, uint32 index ) = 0; // remove a preview by index starting at 0 (previews are sorted)
|
||||||
|
|
||||||
|
STEAM_CALL_RESULT( SubmitItemUpdateResult_t )
|
||||||
|
virtual SteamAPICall_t SubmitItemUpdate( UGCUpdateHandle_t handle, const char *pchChangeNote ) = 0; // commit update process started with StartItemUpdate()
|
||||||
|
virtual EItemUpdateStatus GetItemUpdateProgress( UGCUpdateHandle_t handle, uint64 *punBytesProcessed, uint64* punBytesTotal ) = 0;
|
||||||
|
|
||||||
|
// Steam Workshop Consumer API
|
||||||
|
STEAM_CALL_RESULT( SetUserItemVoteResult_t )
|
||||||
|
virtual SteamAPICall_t SetUserItemVote( PublishedFileId_t nPublishedFileID, bool bVoteUp ) = 0;
|
||||||
|
STEAM_CALL_RESULT( GetUserItemVoteResult_t )
|
||||||
|
virtual SteamAPICall_t GetUserItemVote( PublishedFileId_t nPublishedFileID ) = 0;
|
||||||
|
STEAM_CALL_RESULT( UserFavoriteItemsListChanged_t )
|
||||||
|
virtual SteamAPICall_t AddItemToFavorites( AppId_t nAppId, PublishedFileId_t nPublishedFileID ) = 0;
|
||||||
|
STEAM_CALL_RESULT( UserFavoriteItemsListChanged_t )
|
||||||
|
virtual SteamAPICall_t RemoveItemFromFavorites( AppId_t nAppId, PublishedFileId_t nPublishedFileID ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageSubscribePublishedFileResult_t )
|
||||||
|
virtual SteamAPICall_t SubscribeItem( PublishedFileId_t nPublishedFileID ) = 0; // subscribe to this item, will be installed ASAP
|
||||||
|
STEAM_CALL_RESULT( RemoteStorageUnsubscribePublishedFileResult_t )
|
||||||
|
virtual SteamAPICall_t UnsubscribeItem( PublishedFileId_t nPublishedFileID ) = 0; // unsubscribe from this item, will be uninstalled after game quits
|
||||||
|
virtual uint32 GetNumSubscribedItems() = 0; // number of subscribed items
|
||||||
|
virtual uint32 GetSubscribedItems( PublishedFileId_t* pvecPublishedFileID, uint32 cMaxEntries ) = 0; // all subscribed item PublishFileIDs
|
||||||
|
|
||||||
|
// get EItemState flags about item on this client
|
||||||
|
virtual uint32 GetItemState( PublishedFileId_t nPublishedFileID ) = 0;
|
||||||
|
|
||||||
|
// get info about currently installed content on disc for items that have k_EItemStateInstalled set
|
||||||
|
// if k_EItemStateLegacyItem is set, pchFolder contains the path to the legacy file itself (not a folder)
|
||||||
|
virtual bool GetItemInstallInfo( PublishedFileId_t nPublishedFileID, uint64 *punSizeOnDisk, STEAM_OUT_STRING_COUNT( cchFolderSize ) char *pchFolder, uint32 cchFolderSize, uint32 *punTimeStamp ) = 0;
|
||||||
|
|
||||||
|
// get info about pending update for items that have k_EItemStateNeedsUpdate set. punBytesTotal will be valid after download started once
|
||||||
|
virtual bool GetItemDownloadInfo( PublishedFileId_t nPublishedFileID, uint64 *punBytesDownloaded, uint64 *punBytesTotal ) = 0;
|
||||||
|
|
||||||
|
// download new or update already installed item. If function returns true, wait for DownloadItemResult_t. If the item is already installed,
|
||||||
|
// then files on disk should not be used until callback received. If item is not subscribed to, it will be cached for some time.
|
||||||
|
// If bHighPriority is set, any other item download will be suspended and this item downloaded ASAP.
|
||||||
|
virtual bool DownloadItem( PublishedFileId_t nPublishedFileID, bool bHighPriority ) = 0;
|
||||||
|
|
||||||
|
// game servers can set a specific workshop folder before issuing any UGC commands.
|
||||||
|
// This is helpful if you want to support multiple game servers running out of the same install folder
|
||||||
|
virtual bool BInitWorkshopForGameServer( DepotId_t unWorkshopDepotID, const char *pszFolder ) = 0;
|
||||||
|
|
||||||
|
// SuspendDownloads( true ) will suspend all workshop downloads until SuspendDownloads( false ) is called or the game ends
|
||||||
|
virtual void SuspendDownloads( bool bSuspend ) = 0;
|
||||||
|
|
||||||
|
// usage tracking
|
||||||
|
STEAM_CALL_RESULT( StartPlaytimeTrackingResult_t )
|
||||||
|
virtual SteamAPICall_t StartPlaytimeTracking( PublishedFileId_t *pvecPublishedFileID, uint32 unNumPublishedFileIDs ) = 0;
|
||||||
|
STEAM_CALL_RESULT( StopPlaytimeTrackingResult_t )
|
||||||
|
virtual SteamAPICall_t StopPlaytimeTracking( PublishedFileId_t *pvecPublishedFileID, uint32 unNumPublishedFileIDs ) = 0;
|
||||||
|
STEAM_CALL_RESULT( StopPlaytimeTrackingResult_t )
|
||||||
|
virtual SteamAPICall_t StopPlaytimeTrackingForAllItems() = 0;
|
||||||
|
|
||||||
|
// parent-child relationship or dependency management
|
||||||
|
STEAM_CALL_RESULT( AddUGCDependencyResult_t )
|
||||||
|
virtual SteamAPICall_t AddDependency( PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoveUGCDependencyResult_t )
|
||||||
|
virtual SteamAPICall_t RemoveDependency( PublishedFileId_t nParentPublishedFileID, PublishedFileId_t nChildPublishedFileID ) = 0;
|
||||||
|
|
||||||
|
// add/remove app dependence/requirements (usually DLC)
|
||||||
|
STEAM_CALL_RESULT( AddAppDependencyResult_t )
|
||||||
|
virtual SteamAPICall_t AddAppDependency( PublishedFileId_t nPublishedFileID, AppId_t nAppID ) = 0;
|
||||||
|
STEAM_CALL_RESULT( RemoveAppDependencyResult_t )
|
||||||
|
virtual SteamAPICall_t RemoveAppDependency( PublishedFileId_t nPublishedFileID, AppId_t nAppID ) = 0;
|
||||||
|
// request app dependencies. note that whatever callback you register for GetAppDependenciesResult_t may be called multiple times
|
||||||
|
// until all app dependencies have been returned
|
||||||
|
STEAM_CALL_RESULT( GetAppDependenciesResult_t )
|
||||||
|
virtual SteamAPICall_t GetAppDependencies( PublishedFileId_t nPublishedFileID ) = 0;
|
||||||
|
|
||||||
|
// delete the item without prompting the user
|
||||||
|
STEAM_CALL_RESULT( DeleteItemResult_t )
|
||||||
|
virtual SteamAPICall_t DeleteItem( PublishedFileId_t nPublishedFileID ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ISTEAMUGC011_H
|
@ -120,6 +120,8 @@
|
|||||||
#include "isteamnetworkingsockets006.h"
|
#include "isteamnetworkingsockets006.h"
|
||||||
#include "isteamnetworkingsockets008.h"
|
#include "isteamnetworkingsockets008.h"
|
||||||
#include "isteamnetworkingsockets009.h"
|
#include "isteamnetworkingsockets009.h"
|
||||||
|
#include "isteamnetworkingsockets010.h"
|
||||||
|
#include "isteamnetworkingsockets011.h"
|
||||||
#include "isteamremotestorage.h"
|
#include "isteamremotestorage.h"
|
||||||
#include "isteamremotestorage001.h"
|
#include "isteamremotestorage001.h"
|
||||||
#include "isteamremotestorage002.h"
|
#include "isteamremotestorage002.h"
|
||||||
@ -135,6 +137,7 @@
|
|||||||
#include "isteamremotestorage012.h"
|
#include "isteamremotestorage012.h"
|
||||||
#include "isteamremotestorage013.h"
|
#include "isteamremotestorage013.h"
|
||||||
#include "isteamremotestorage014.h"
|
#include "isteamremotestorage014.h"
|
||||||
|
#include "isteamremotestorage015.h"
|
||||||
#include "isteamscreenshots.h"
|
#include "isteamscreenshots.h"
|
||||||
#include "isteamscreenshots001.h"
|
#include "isteamscreenshots001.h"
|
||||||
#include "isteamscreenshots002.h"
|
#include "isteamscreenshots002.h"
|
||||||
@ -161,6 +164,7 @@
|
|||||||
#include "isteamugc008.h"
|
#include "isteamugc008.h"
|
||||||
#include "isteamugc009.h"
|
#include "isteamugc009.h"
|
||||||
#include "isteamugc010.h"
|
#include "isteamugc010.h"
|
||||||
|
#include "isteamugc011.h"
|
||||||
#include "isteamugc012.h"
|
#include "isteamugc012.h"
|
||||||
#include "isteamugc013.h"
|
#include "isteamugc013.h"
|
||||||
#include "isteamugc014.h"
|
#include "isteamugc014.h"
|
||||||
|
2
third-party/build/win
vendored
2
third-party/build/win
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 07336fafed51cccbb1438bf32f90bb0d20634529
|
Subproject commit 89d0bbf43221dc758efa56f988cb0f0a34b84342
|
2
third-party/common/linux
vendored
2
third-party/common/linux
vendored
@ -1 +1 @@
|
|||||||
Subproject commit ecaee3fbfc14352b79609bc781db4881b150bd42
|
Subproject commit b4194b9019386d456031a9a0fd6b63a867ab0108
|
2
third-party/common/win
vendored
2
third-party/common/win
vendored
@ -1 +1 @@
|
|||||||
Subproject commit b7761d06842f7799a653f61a4d29f382b9873053
|
Subproject commit a70c58d93377d1a472d9320842183bc533d87e5d
|
2
third-party/deps/common
vendored
2
third-party/deps/common
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 1c1acc03760113ce5a440f46bc89c6832c695f8f
|
Subproject commit 22197753b2a01b5097610f4c62f6c9f7eb1e27d2
|
2
third-party/deps/linux
vendored
2
third-party/deps/linux
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 6cb47a3e46e49b03be7b9c0e9b3d7c5953cf038a
|
Subproject commit be07085cc615800304acf619fcc9f4b6107c0574
|
2
third-party/deps/win
vendored
2
third-party/deps/win
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 6eb71e5e7aa0f1ead9e7d0d10c6b9efb14566b26
|
Subproject commit 3171da4672b2f10a06edfed6e54e5999872f1b22
|
@ -31,9 +31,9 @@ def generate_stats_achievements(
|
|||||||
out['hidden'] = 0
|
out['hidden'] = 0
|
||||||
for x in ach['display']:
|
for x in ach['display']:
|
||||||
value = ach['display'][x]
|
value = ach['display'][x]
|
||||||
if x == 'name':
|
if f'{x}'.lower() == 'name':
|
||||||
x = 'displayName'
|
x = 'displayName'
|
||||||
elif x == 'desc':
|
elif f'{x}'.lower() == 'desc':
|
||||||
x = 'description'
|
x = 'description'
|
||||||
elif x == 'Hidden' or f'{x}'.lower() == 'hidden':
|
elif x == 'Hidden' or f'{x}'.lower() == 'hidden':
|
||||||
x = 'hidden'
|
x = 'hidden'
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
import json
|
||||||
import platform
|
import platform
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import glob
|
import glob
|
||||||
import configparser
|
import configparser
|
||||||
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import shutil
|
import shutil
|
||||||
from configobj import ConfigObj
|
from configobj import ConfigObj
|
||||||
@ -75,11 +77,17 @@ def convert_to_ini(global_settings: str):
|
|||||||
for ovl in ov_lines:
|
for ovl in ov_lines:
|
||||||
[ov_name, ov_val] = ovl.split(' ', 1)
|
[ov_name, ov_val] = ovl.split(' ', 1)
|
||||||
configs_overlay["overlay::appearance"][ov_name.strip()] = ov_val.strip() #updated ini through ConfigObj
|
configs_overlay["overlay::appearance"][ov_name.strip()] = ov_val.strip() #updated ini through ConfigObj
|
||||||
# NOTE generating 'branches.json' would require copy pasting some code from 'generate_config_emu.py'
|
elif file == 'build_id.txt':
|
||||||
# if possible, avoid using 'migrate_gse' alltogether, and use 'generate_emu_config' instead
|
with open(os.path.join(global_settings, file), "r", encoding='utf-8') as fr:
|
||||||
#elif file == 'build_id.txt':
|
create_new_steam_settings_folder()
|
||||||
#with open(os.path.join(global_settings, file), "r", encoding='utf-8') as fr:
|
with open(os.path.join(NEW_STEAM_SETTINGS_FOLDER, 'branches.json'), 'wt', encoding='utf-8') as fout:
|
||||||
#configs_app["app::general"]["build_id"] = fr.readline().strip('\n').strip('\r') #updated ini through ConfigObj
|
json.dump([{
|
||||||
|
"name": "public",
|
||||||
|
"description": "",
|
||||||
|
"protected": False,
|
||||||
|
"build_id": int(fr.readline().strip()),
|
||||||
|
"time_updated": int(time.time())
|
||||||
|
}], fout, indent=2)
|
||||||
elif file == 'disable_account_avatar.txt':
|
elif file == 'disable_account_avatar.txt':
|
||||||
configs_main["main::general"]["enable_account_avatar"] = 0 #updated ini through ConfigObj
|
configs_main["main::general"]["enable_account_avatar"] = 0 #updated ini through ConfigObj
|
||||||
elif file == 'disable_networking.txt':
|
elif file == 'disable_networking.txt':
|
||||||
@ -197,6 +205,24 @@ def write_txt_file_multi(filename: str, dict_ini: dict, section: str):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def convert_public_branch_to_txt(global_settings: str):
|
||||||
|
src_file = os.path.join(global_settings, 'branches.json')
|
||||||
|
if not os.path.isfile(src_file):
|
||||||
|
return False
|
||||||
|
build_id = -1
|
||||||
|
with open(src_file, "r", encoding='utf-8') as fr:
|
||||||
|
branches: list[dict] = json.load(fr)
|
||||||
|
for branch in branches:
|
||||||
|
if f'{branch.get("name", "")}'.lower() == "public":
|
||||||
|
build_id = branch.get('build_id', -1)
|
||||||
|
break
|
||||||
|
if build_id == -1:
|
||||||
|
return False
|
||||||
|
create_new_steam_settings_folder()
|
||||||
|
with open(os.path.join(NEW_STEAM_SETTINGS_FOLDER, 'build_id.txt'), "wt", encoding='utf-8') as fw:
|
||||||
|
fw.write(f"{build_id}")
|
||||||
|
return True
|
||||||
|
|
||||||
def convert_to_txt(global_settings: str):
|
def convert_to_txt(global_settings: str):
|
||||||
# oh no, they're too many! --- they are indeed... it seems ConfigParser does the job here
|
# oh no, they're too many! --- they are indeed... it seems ConfigParser does the job here
|
||||||
config = configparser.ConfigParser(strict=False, empty_lines_in_values=False)
|
config = configparser.ConfigParser(strict=False, empty_lines_in_values=False)
|
||||||
@ -210,9 +236,7 @@ def convert_to_txt(global_settings: str):
|
|||||||
done = 0
|
done = 0
|
||||||
done += write_txt_file_bool('achievements_bypass.txt', dict_ini, 'main::misc', 'achievements_bypass', True)
|
done += write_txt_file_bool('achievements_bypass.txt', dict_ini, 'main::misc', 'achievements_bypass', True)
|
||||||
done += write_txt_file_multi('app_paths.txt', dict_ini, 'app::paths')
|
done += write_txt_file_multi('app_paths.txt', dict_ini, 'app::paths')
|
||||||
# NOTE generating 'branches.json' would require copy pasting some code from 'generate_config_emu.py'
|
done += convert_public_branch_to_txt(global_settings)
|
||||||
# if possible, avoid using 'migrate_gse' alltogether, and use 'generate_emu_config' instead
|
|
||||||
#done += write_txt_file('build_id.txt', dict_ini, 'app::general', 'build_id') # disabled after 'branches.json' update
|
|
||||||
done += write_txt_file('crash_printer_location.txt', dict_ini, 'main::general', 'crash_printer_location')
|
done += write_txt_file('crash_printer_location.txt', dict_ini, 'main::general', 'crash_printer_location')
|
||||||
done += write_txt_file_bool('disable_account_avatar.txt', dict_ini, 'main::general', 'enable_account_avatar', False)
|
done += write_txt_file_bool('disable_account_avatar.txt', dict_ini, 'main::general', 'enable_account_avatar', False)
|
||||||
done += write_txt_file_bool('disable_lan_only.txt', dict_ini, 'main::connectivity', 'disable_lan_only',True)
|
done += write_txt_file_bool('disable_lan_only.txt', dict_ini, 'main::connectivity', 'disable_lan_only',True)
|
||||||
|
4
tools/steamclient_loader/SOURCE.txt
Normal file
4
tools/steamclient_loader/SOURCE.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
============================================================================ INFO
|
||||||
|
https://github.com/Rat431/ColdAPI_Steam
|
||||||
|
|
||||||
|
Original version of ColdClientLoader by Rat431.
|
Loading…
x
Reference in New Issue
Block a user