mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-05-13 15:19:28 +03:00
Compare commits
No commits in common. "master" and "v0.1" have entirely different histories.
100
.editorconfig
100
.editorconfig
@ -1,100 +0,0 @@
|
|||||||
# Remove the line below if you want to inherit .editorconfig settings from higher directories
|
|
||||||
root = true
|
|
||||||
|
|
||||||
# C# files
|
|
||||||
[*.cs]
|
|
||||||
indent_style = tab
|
|
||||||
indent_size = tab
|
|
||||||
tab_size = 4
|
|
||||||
|
|
||||||
# New line preferences
|
|
||||||
end_of_line = crlf
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
|
|
||||||
#### C# Coding Conventions ####
|
|
||||||
|
|
||||||
# Expression-bodied members
|
|
||||||
csharp_style_expression_bodied_accessors = true:silent
|
|
||||||
csharp_style_expression_bodied_constructors = false:silent
|
|
||||||
csharp_style_expression_bodied_indexers = true:silent
|
|
||||||
csharp_style_expression_bodied_lambdas = true:silent
|
|
||||||
csharp_style_expression_bodied_local_functions = false:silent
|
|
||||||
csharp_style_expression_bodied_methods = false:silent
|
|
||||||
csharp_style_expression_bodied_operators = false:silent
|
|
||||||
csharp_style_expression_bodied_properties = true:silent
|
|
||||||
|
|
||||||
# Pattern matching preferences
|
|
||||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
|
||||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
|
||||||
csharp_style_prefer_not_pattern = true:suggestion
|
|
||||||
csharp_style_prefer_pattern_matching = true:silent
|
|
||||||
csharp_style_prefer_switch_expression = true:suggestion
|
|
||||||
|
|
||||||
# Null-checking preferences
|
|
||||||
csharp_style_conditional_delegate_call = true:suggestion
|
|
||||||
|
|
||||||
# Code-block preferences
|
|
||||||
csharp_prefer_braces = true:silent
|
|
||||||
|
|
||||||
# Expression-level preferences
|
|
||||||
csharp_prefer_simple_default_expression = true:suggestion
|
|
||||||
csharp_style_deconstructed_variable_declaration = true:suggestion
|
|
||||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
|
||||||
csharp_style_inlined_variable_declaration = true:suggestion
|
|
||||||
csharp_style_pattern_local_over_anonymous_function = true:suggestion
|
|
||||||
csharp_style_prefer_index_operator = true:suggestion
|
|
||||||
csharp_style_prefer_range_operator = true:suggestion
|
|
||||||
csharp_style_throw_expression = true:suggestion
|
|
||||||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
|
||||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
|
||||||
|
|
||||||
# 'using' directive preferences
|
|
||||||
csharp_using_directive_placement = outside_namespace:silent
|
|
||||||
|
|
||||||
#### C# Formatting Rules ####
|
|
||||||
|
|
||||||
# New line preferences
|
|
||||||
csharp_new_line_before_catch = true
|
|
||||||
csharp_new_line_before_else = true
|
|
||||||
csharp_new_line_before_finally = true
|
|
||||||
csharp_new_line_before_members_in_anonymous_types = true
|
|
||||||
csharp_new_line_before_members_in_object_initializers = true
|
|
||||||
csharp_new_line_before_open_brace = all
|
|
||||||
csharp_new_line_between_query_expression_clauses = true
|
|
||||||
|
|
||||||
# Indentation preferences
|
|
||||||
csharp_indent_block_contents = true
|
|
||||||
csharp_indent_braces = false
|
|
||||||
csharp_indent_case_contents = true
|
|
||||||
csharp_indent_case_contents_when_block = true
|
|
||||||
csharp_indent_labels = no_change
|
|
||||||
csharp_indent_switch_labels = true
|
|
||||||
|
|
||||||
# Space preferences
|
|
||||||
csharp_space_after_cast = false
|
|
||||||
csharp_space_after_colon_in_inheritance_clause = true
|
|
||||||
csharp_space_after_comma = true
|
|
||||||
csharp_space_after_dot = false
|
|
||||||
csharp_space_after_keywords_in_control_flow_statements = true
|
|
||||||
csharp_space_after_semicolon_in_for_statement = true
|
|
||||||
csharp_space_around_binary_operators = before_and_after
|
|
||||||
csharp_space_around_declaration_statements = false
|
|
||||||
csharp_space_before_colon_in_inheritance_clause = true
|
|
||||||
csharp_space_before_comma = false
|
|
||||||
csharp_space_before_dot = false
|
|
||||||
csharp_space_before_open_square_brackets = false
|
|
||||||
csharp_space_before_semicolon_in_for_statement = false
|
|
||||||
csharp_space_between_empty_square_brackets = false
|
|
||||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
|
||||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
|
||||||
csharp_space_between_method_call_parameter_list_parentheses = true
|
|
||||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
|
||||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
|
||||||
csharp_space_between_method_declaration_parameter_list_parentheses = true
|
|
||||||
csharp_space_between_parentheses = control_flow_statements
|
|
||||||
csharp_space_between_square_brackets = false
|
|
||||||
|
|
||||||
# Wrapping preferences
|
|
||||||
csharp_preserve_single_line_blocks = true
|
|
||||||
csharp_preserve_single_line_statements = true
|
|
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: garrynewman
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Set x to y
|
|
||||||
2. Run for x minutes
|
|
||||||
3. Call x
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Calling Code**
|
|
||||||
```
|
|
||||||
// The code you're using to call into Steamworks
|
|
||||||
Steamworks.DoBug();
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
|
||||||
- OS: [e.g. iOS]
|
|
||||||
- Unity: [e.g Unity 2019.3]
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
10
.github/ISSUE_TEMPLATE/something-else.md
vendored
10
.github/ISSUE_TEMPLATE/something-else.md
vendored
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: Something Else
|
|
||||||
about: Describe this issue template's purpose here.
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
42
.github/workflows/dotnetcore.yml
vendored
42
.github/workflows/dotnetcore.yml
vendored
@ -1,42 +0,0 @@
|
|||||||
name: Build All
|
|
||||||
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: windows-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4.2.2
|
|
||||||
- name: Setup dotnet 6.0.x
|
|
||||||
uses: actions/setup-dotnet@v4.1.0
|
|
||||||
with:
|
|
||||||
dotnet-version: '6.0.x'
|
|
||||||
include-prerelease: true
|
|
||||||
|
|
||||||
- name: Restore Win64
|
|
||||||
run: dotnet restore Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj
|
|
||||||
- name: Restore Win32
|
|
||||||
run: dotnet restore Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj
|
|
||||||
- name: Restore Posix
|
|
||||||
run: dotnet restore Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj
|
|
||||||
|
|
||||||
- name: Build Win64
|
|
||||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj
|
|
||||||
- name: Build Win32
|
|
||||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj
|
|
||||||
- name: Build Posix
|
|
||||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj
|
|
||||||
|
|
||||||
- name: Build Win64 Release
|
|
||||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj --configuration Release
|
|
||||||
- name: Build Win32 Release
|
|
||||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj --configuration Release
|
|
||||||
- name: Build Posix Release
|
|
||||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj --configuration Release
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4.4.3
|
|
||||||
with:
|
|
||||||
name: Compiled Files
|
|
||||||
path: Facepunch.Steamworks/bin
|
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -55,14 +55,11 @@ Facepunch.Steamworks.Test/bin/Release/Facepunch.Steamworks.Test.dll
|
|||||||
Facepunch.Steamworks.Test/bin/Release/Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
|
Facepunch.Steamworks.Test/bin/Release/Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
|
||||||
*.user
|
*.user
|
||||||
*.cache
|
*.cache
|
||||||
*.idea
|
|
||||||
*.vscode
|
|
||||||
TestResults
|
TestResults
|
||||||
obj
|
obj
|
||||||
Facepunch.Steamworks/bin/Debug/Facepunch.Steamworks.Api.dll
|
Facepunch.Steamworks/bin/Debug/Facepunch.Steamworks.Api.dll
|
||||||
Facepunch.Steamworks/bin/Debug/Facepunch.Steamworks.dll
|
Facepunch.Steamworks/bin/Debug/Facepunch.Steamworks.dll
|
||||||
Facepunch.Steamworks/bin/Release/Facepunch.Steamworks.dll
|
Facepunch.Steamworks/bin/Release/Facepunch.Steamworks.dll
|
||||||
Facepunch.Steamworks/bin
|
|
||||||
*.opendb
|
*.opendb
|
||||||
*.db
|
*.db
|
||||||
Facepunch.Steamworks.dll
|
Facepunch.Steamworks.dll
|
||||||
@ -70,8 +67,3 @@ Facepunch.Steamworks.Test.dll
|
|||||||
*UnitTestFramework.dll
|
*UnitTestFramework.dll
|
||||||
mscorlib.dll
|
mscorlib.dll
|
||||||
*.nlp
|
*.nlp
|
||||||
packages
|
|
||||||
Generator/bin
|
|
||||||
*.XML
|
|
||||||
.vs
|
|
||||||
Facepunch.Steamworks.Test/bin/**
|
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
dotnet restore .\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj
|
|
||||||
dotnet restore .\Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj
|
|
||||||
dotnet restore .\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj
|
|
||||||
dotnet restore .\Facepunch.Steamworks.Test\Facepunch.Steamworks.TestWin32.csproj
|
|
||||||
dotnet restore .\Facepunch.Steamworks.Test\Facepunch.Steamworks.TestWin64.csproj
|
|
@ -1,121 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class AppTest
|
|
||||||
{
|
|
||||||
[AssemblyInitialize]
|
|
||||||
public static void AssemblyInit( TestContext context )
|
|
||||||
{
|
|
||||||
Steamworks.Dispatch.OnDebugCallback = ( type, str, server ) =>
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[Callback {type} {(server ? "server" : "client")}]" );
|
|
||||||
Console.WriteLine( str );
|
|
||||||
Console.WriteLine( $"" );
|
|
||||||
};
|
|
||||||
|
|
||||||
Steamworks.Dispatch.OnException = ( e ) =>
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine( e.Message );
|
|
||||||
Console.Error.WriteLine( e.StackTrace );
|
|
||||||
Assert.Fail( e.Message );
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Init Client
|
|
||||||
//
|
|
||||||
Steamworks.SteamClient.Init( 252490 );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Init Server
|
|
||||||
//
|
|
||||||
var serverInit = new SteamServerInit( "rust", "Rusty Mode" )
|
|
||||||
{
|
|
||||||
GamePort = 28015,
|
|
||||||
Secure = true,
|
|
||||||
QueryPort = 28016
|
|
||||||
};
|
|
||||||
|
|
||||||
Steamworks.SteamServer.Init( 252490, serverInit );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Needs to happen before LogOnAnonymous
|
|
||||||
//
|
|
||||||
SteamNetworkingSockets.RequestFakeIP();
|
|
||||||
|
|
||||||
SteamServer.LogOnAnonymous();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GameLangauge()
|
|
||||||
{
|
|
||||||
var gl = SteamApps.GameLanguage;
|
|
||||||
Assert.IsNotNull( gl );
|
|
||||||
Assert.IsTrue( gl.Length > 3 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"{gl}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void AppInstallDir()
|
|
||||||
{
|
|
||||||
var str = SteamApps.AppInstallDir();
|
|
||||||
Assert.IsNotNull( str );
|
|
||||||
Assert.IsTrue( str.Length > 3 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"{str}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void AppOwner()
|
|
||||||
{
|
|
||||||
var steamid = SteamApps.AppOwner;
|
|
||||||
Assert.IsTrue( steamid.Value > 70561197960279927 );
|
|
||||||
Assert.IsTrue( steamid.Value < 80561197960279927 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"{steamid.Value}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void InstalledDepots()
|
|
||||||
{
|
|
||||||
var depots = SteamApps.InstalledDepots().ToArray();
|
|
||||||
|
|
||||||
Assert.IsNotNull( depots );
|
|
||||||
Assert.IsTrue( depots.Length > 0 );
|
|
||||||
|
|
||||||
foreach ( var depot in depots )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{depot.Value}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetFileDetails()
|
|
||||||
{
|
|
||||||
var fileinfo = await SteamApps.GetFileDetailsAsync( "RustClient.exe" );
|
|
||||||
|
|
||||||
Console.WriteLine( $"fileinfo.SizeInBytes: {fileinfo?.SizeInBytes}" );
|
|
||||||
Console.WriteLine( $"fileinfo.Sha1: {fileinfo?.Sha1}" );
|
|
||||||
Console.WriteLine( $"fileinfo.Flags: {fileinfo?.Flags}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void CommandLine()
|
|
||||||
{
|
|
||||||
var cl = SteamApps.CommandLine;
|
|
||||||
|
|
||||||
Console.WriteLine( $"CommandLine: {cl}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[DeploymentItem("steam_api64.dll")]
|
|
||||||
[DeploymentItem("steam_api.dll")]
|
|
||||||
[TestClass]
|
|
||||||
public class ClanTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void GetName()
|
|
||||||
{
|
|
||||||
var clan = new Clan(103582791433666425);
|
|
||||||
|
|
||||||
Assert.AreEqual("Steamworks Development", clan.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GetClanTag()
|
|
||||||
{
|
|
||||||
var clan = new Clan(103582791433666425);
|
|
||||||
|
|
||||||
Assert.AreEqual("SteamworksDev", clan.Tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetOwner()
|
|
||||||
{
|
|
||||||
var clan = new Clan(103582791433666425);
|
|
||||||
await clan.RequestOfficerList();
|
|
||||||
|
|
||||||
Assert.AreNotEqual(new SteamId(), clan.Owner.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GetOfficers()
|
|
||||||
{
|
|
||||||
var clan = new Clan(103582791433666425);
|
|
||||||
foreach (var officer in clan.GetOfficers())
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{officer.Name} : {officer.Id}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task RequestOfficerList()
|
|
||||||
{
|
|
||||||
var clan = new Clan(103582791433666425);
|
|
||||||
bool res = await clan.RequestOfficerList();
|
|
||||||
|
|
||||||
Assert.AreEqual(true, res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
253
Facepunch.Steamworks.Test/Client/Client.cs
Normal file
253
Facepunch.Steamworks.Test/Client/Client.cs
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||||
|
[DeploymentItem( "steam_appid.txt" )]
|
||||||
|
public partial class Client
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Init_50()
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < 50; i++ )
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
}
|
||||||
|
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Name()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var username = client.Username;
|
||||||
|
Console.WriteLine( username );
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
Assert.IsNotNull( username );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void SteamId()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var steamid = client.SteamId;
|
||||||
|
Console.WriteLine( steamid );
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
Assert.AreNotEqual( 0, steamid );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AuthSessionTicket()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var ticket = client.Auth.GetAuthSessionTicket();
|
||||||
|
|
||||||
|
Assert.IsTrue( ticket != null );
|
||||||
|
Assert.IsTrue( ticket.Handle != 0 );
|
||||||
|
Assert.IsTrue( ticket.Data.Length > 0 );
|
||||||
|
|
||||||
|
ticket.Cancel();
|
||||||
|
|
||||||
|
Assert.IsTrue( ticket.Handle == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void VoiceOptimalSampleRate()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var rate = client.Voice.OptimalSampleRate;
|
||||||
|
Assert.AreNotEqual( rate, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
for( int i=0; i<1024; i++ )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MemoryStream decompressStream = new MemoryStream();
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetVoice()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
int unCompressed = 0;
|
||||||
|
int compressed = 0;
|
||||||
|
|
||||||
|
client.Voice.OnCompressedData = ( ptr, length ) =>
|
||||||
|
{
|
||||||
|
compressed += length;
|
||||||
|
|
||||||
|
if ( !client.Voice.Decompress( ptr, 0, length, decompressStream ) )
|
||||||
|
{
|
||||||
|
Assert.Fail( "Decompress returned false" );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Voice.OnUncompressedData = ( ptr, length ) =>
|
||||||
|
{
|
||||||
|
unCompressed += length;
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Voice.WantsRecording = true;
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while ( sw.Elapsed.TotalSeconds < 3 )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.AreNotEqual( unCompressed, 0 );
|
||||||
|
Assert.AreNotEqual( compressed, 0 );
|
||||||
|
|
||||||
|
// Should really be > 0 if the mic was getting audio
|
||||||
|
Console.WriteLine( "unCompressed: {0}", unCompressed );
|
||||||
|
Console.WriteLine( "compressed: {0}", compressed );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetVoice_Compressed_Only()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
int compressed = 0;
|
||||||
|
|
||||||
|
client.Voice.OnCompressedData = ( ptr, length ) =>
|
||||||
|
{
|
||||||
|
compressed += length;
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Voice.WantsRecording = true;
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while ( sw.Elapsed.TotalSeconds < 3 )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.AreNotEqual( compressed, 0 );
|
||||||
|
Console.WriteLine( "compressed: {0}", compressed );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetVoice_UnCompressed_Only()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
int unCompressed = 0;
|
||||||
|
|
||||||
|
client.Voice.OnUncompressedData = ( ptr, length ) =>
|
||||||
|
{
|
||||||
|
unCompressed += length;
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Voice.WantsRecording = true;
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while ( sw.Elapsed.TotalSeconds < 3 )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.AreNotEqual( unCompressed, 0 );
|
||||||
|
|
||||||
|
// Should really be > 0 if the mic was getting audio
|
||||||
|
Console.WriteLine( "unCompressed: {0}", unCompressed );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void InventoryDefinitions()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsNotNull( client.Inventory.Definitions );
|
||||||
|
Assert.AreNotEqual( 0, client.Inventory.Definitions.Length );
|
||||||
|
|
||||||
|
foreach ( var i in client.Inventory.Definitions )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0}: {1}", i.Id, i.Name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void InventoryItemList()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
bool CallbackCalled = false;
|
||||||
|
|
||||||
|
// OnUpdate hsould be called when we receive a list of our items
|
||||||
|
client.Inventory.OnUpdate = () => { CallbackCalled = true; };
|
||||||
|
|
||||||
|
// tell steam to download the items
|
||||||
|
client.Inventory.Refresh();
|
||||||
|
|
||||||
|
// Wait for the items
|
||||||
|
var timeout = Stopwatch.StartNew();
|
||||||
|
while ( client.Inventory.Items == null )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 1000 );
|
||||||
|
|
||||||
|
if ( timeout.Elapsed.TotalSeconds > 5 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure callback was called
|
||||||
|
Assert.IsTrue( CallbackCalled );
|
||||||
|
|
||||||
|
// Make sure items are valid
|
||||||
|
foreach ( var item in client.Inventory.Items )
|
||||||
|
{
|
||||||
|
Assert.IsNotNull( item );
|
||||||
|
Assert.IsNotNull( item.Definition );
|
||||||
|
|
||||||
|
Console.WriteLine( item.Definition.Name + " - " + item.Id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
92
Facepunch.Steamworks.Test/Client/Friends.cs
Normal file
92
Facepunch.Steamworks.Test/Client/Friends.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||||
|
[DeploymentItem( "steam_appid.txt" )]
|
||||||
|
[TestClass]
|
||||||
|
public class Friends
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void FriendList()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
client.Friends.Refresh();
|
||||||
|
|
||||||
|
Assert.IsNotNull( client.Friends.All );
|
||||||
|
|
||||||
|
foreach ( var friend in client.Friends.All )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0}: {1} (Friend:{2}) (Blocked:{3})", friend.Id, friend.Name, friend.IsFriend, friend.IsBlocked );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void FriendListWithoutRefresh()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
foreach ( var friend in client.Friends.All )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0}: {1} (Friend:{2}) (Blocked:{3})", friend.Id, friend.Name, friend.IsFriend, friend.IsBlocked );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Avatar()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
var friend = client.Friends.All.First();
|
||||||
|
|
||||||
|
var img = client.Friends.GetAvatar( Steamworks.Friends.AvatarSize.Medium, friend.Id );
|
||||||
|
|
||||||
|
Assert.AreEqual( img.Width, 64 );
|
||||||
|
Assert.AreEqual( img.Height, 64 );
|
||||||
|
|
||||||
|
while ( !img.IsLoaded && !img.IsError )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.AreEqual( img.Data.Length, img.Width * img.Height * 4 );
|
||||||
|
|
||||||
|
DrawImage( img );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DrawImage( Image img )
|
||||||
|
{
|
||||||
|
var grad = " -:+#";
|
||||||
|
|
||||||
|
for ( int y = 0; y<img.Height; y++ )
|
||||||
|
{
|
||||||
|
var str = "";
|
||||||
|
|
||||||
|
for ( int x = 0; x < img.Width; x++ )
|
||||||
|
{
|
||||||
|
var p = img.GetPixel( x, y );
|
||||||
|
|
||||||
|
var brightness = 1 - ((float)(p.r + p.g + p.b) / (255.0f * 3.0f));
|
||||||
|
var c = (int) ((grad.Length) * brightness);
|
||||||
|
str += grad[c];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine( str );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
Facepunch.Steamworks.Test/Client/Networking.cs
Normal file
108
Facepunch.Steamworks.Test/Client/Networking.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||||
|
[DeploymentItem( "steam_appid.txt" )]
|
||||||
|
public partial class Networking
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void PeerToPeerSend()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var TestString = "This string will be transformed to bytes, sent over the Steam P2P network, then converted back to a string.";
|
||||||
|
var OutputReceived = false;
|
||||||
|
var data = Encoding.UTF8.GetBytes( TestString );
|
||||||
|
|
||||||
|
client.Networking.OnP2PData = ( steamid, ms, channel ) =>
|
||||||
|
{
|
||||||
|
var str = Encoding.UTF8.GetString( ms.GetBuffer() );
|
||||||
|
Assert.AreEqual( str, TestString );
|
||||||
|
Assert.AreEqual( steamid, client.SteamId );
|
||||||
|
OutputReceived = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Networking.OnIncomingConnection = ( steamid ) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine( "Incoming P2P Connection: " + steamid );
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Networking.OnConnectionFailed = ( steamid, error ) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine( "Connection Error: " + steamid + " - " + error );
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Networking.SendP2PPacket( client.SteamId, data, data.Length );
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
Thread.Sleep( 10 );
|
||||||
|
client.Update();
|
||||||
|
|
||||||
|
if ( OutputReceived )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void PeerToPeerFailure()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var TestString = "This string will be transformed to bytes, sent over the Steam P2P network, then converted back to a string.";
|
||||||
|
var TimeoutReceived = false;
|
||||||
|
var data = Encoding.UTF8.GetBytes( TestString );
|
||||||
|
|
||||||
|
client.Networking.OnIncomingConnection = ( steamid ) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine( "Incoming P2P Connection: " + steamid );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Networking.OnConnectionFailed = ( steamid, error ) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine( "Connection Error: " + steamid + " - " + error );
|
||||||
|
TimeoutReceived = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ulong rand = (ulong) new Random().Next( 1024 * 16 );
|
||||||
|
|
||||||
|
// Send to an invalid, not listening steamid
|
||||||
|
if ( !client.Networking.SendP2PPacket( client.SteamId + rand, data, data.Length ) )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "Couldn't send packet" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
Thread.Sleep( 10 );
|
||||||
|
client.Update();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Timout is usually around 15 seconds
|
||||||
|
//
|
||||||
|
if ( TimeoutReceived )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( sw.Elapsed.TotalSeconds > 30 )
|
||||||
|
{
|
||||||
|
Assert.Fail( "Didn't time out" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
/*
|
|
||||||
namespace Facepunch.Steamworks.Test
|
|
||||||
{
|
|
||||||
public partial class Server
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void StatsGet()
|
|
||||||
{
|
|
||||||
using ( var server = new Facepunch.Steamworks.Server( 252490, new ServerInit( "rust", "Rust" ) ) )
|
|
||||||
{
|
|
||||||
Assert.IsTrue( server.IsValid );
|
|
||||||
server.LogOnAnonymous();
|
|
||||||
|
|
||||||
ulong MySteamId = 76561197960279927;
|
|
||||||
|
|
||||||
bool GotStats = false;
|
|
||||||
|
|
||||||
server.Stats.Refresh( MySteamId, (steamid, success) =>
|
|
||||||
{
|
|
||||||
GotStats = true;
|
|
||||||
Assert.IsTrue( success );
|
|
||||||
|
|
||||||
var deathsInCallback = server.Stats.GetInt( MySteamId, "deaths", -1 );
|
|
||||||
Console.WriteLine( "deathsInCallback: {0}", deathsInCallback );
|
|
||||||
Assert.IsTrue( deathsInCallback > 0 );
|
|
||||||
} );
|
|
||||||
|
|
||||||
|
|
||||||
server.UpdateWhile( () => !GotStats );
|
|
||||||
|
|
||||||
var deaths = server.Stats.GetInt( MySteamId, "deaths", -1 );
|
|
||||||
Console.WriteLine( "deathsInCallback: {0}", deaths );
|
|
||||||
Assert.IsTrue( deaths > 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
357
Facepunch.Steamworks.Test/Client/Serverlist.cs
Normal file
357
Facepunch.Steamworks.Test/Client/Serverlist.cs
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||||
|
[DeploymentItem( "steam_appid.txt" )]
|
||||||
|
public partial class ServerList
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void InternetList()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
||||||
|
filter.Add( "appid", client.AppId.ToString() );
|
||||||
|
filter.Add( "gamedir", "rust" );
|
||||||
|
filter.Add( "secure", "1" );
|
||||||
|
|
||||||
|
var query = client.ServerList.Internet( filter );
|
||||||
|
|
||||||
|
for ( int i = 0; i < 1000; i++ )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 10 );
|
||||||
|
|
||||||
|
foreach ( var s in query.Responded )
|
||||||
|
{
|
||||||
|
Assert.AreEqual( s.AppId, client.AppId );
|
||||||
|
Assert.AreEqual( s.GameDir, "rust" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( query.Finished )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
||||||
|
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
||||||
|
|
||||||
|
foreach ( var server in query.Responded.Take( 20 ) )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0} {1}", server.AddressString, server.Name );
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Dispose();
|
||||||
|
|
||||||
|
for ( int i = 0; i < 100; i++ )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void MultipleInternetList()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var queries = new List<Facepunch.Steamworks.ServerList.Request>();
|
||||||
|
|
||||||
|
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
||||||
|
filter.Add( "map", "barren" );
|
||||||
|
|
||||||
|
for ( int i = 0; i < 10; i++ )
|
||||||
|
queries.Add( client.ServerList.Internet( filter ) );
|
||||||
|
|
||||||
|
for ( int i = 0; i < 100; i++ )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 5 );
|
||||||
|
|
||||||
|
if ( queries.Any( x => x.Finished ) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( var query in queries )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
||||||
|
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
||||||
|
|
||||||
|
client.Update();
|
||||||
|
query.Dispose();
|
||||||
|
client.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Filters()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
||||||
|
filter.Add( "map", "barren" );
|
||||||
|
|
||||||
|
|
||||||
|
var query = client.ServerList.Internet( filter );
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 2 );
|
||||||
|
|
||||||
|
if ( query.Finished )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( var x in query.Responded )
|
||||||
|
{
|
||||||
|
Assert.AreEqual( x.Map.ToLower(), "barren" );
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Dispose();
|
||||||
|
|
||||||
|
for ( int i = 0; i < 100; i++ )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void HistoryList()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var query = client.ServerList.History();
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 2 );
|
||||||
|
|
||||||
|
if ( query.Finished )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
||||||
|
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
||||||
|
|
||||||
|
foreach ( var x in query.Responded )
|
||||||
|
{
|
||||||
|
Console.WriteLine( x.Map );
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Dispose();
|
||||||
|
|
||||||
|
for ( int i = 0; i < 100; i++ )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CustomList()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var servers = new List<string>();
|
||||||
|
|
||||||
|
servers.Add( "158.85.101.20:28015" );
|
||||||
|
servers.Add( "158.85.101.20:28022" );
|
||||||
|
servers.Add( "173.192.176.171:28615" );
|
||||||
|
servers.Add( "109.95.212.35:28215" );
|
||||||
|
servers.Add( "109.95.212.35:28115" );
|
||||||
|
servers.Add( "27.50.72.176:28015" );
|
||||||
|
servers.Add( "109.95.212.40:28015" );
|
||||||
|
servers.Add( "212.38.168.149:28215" );
|
||||||
|
servers.Add( "27.50.72.167:28215" );
|
||||||
|
servers.Add( "85.236.105.7:28215" );
|
||||||
|
servers.Add( "107.182.233.216:28215" );
|
||||||
|
servers.Add( "85.236.105.11:28215" );
|
||||||
|
servers.Add( "109.95.211.198:28215" );
|
||||||
|
servers.Add( "8.26.94.190:28015" );
|
||||||
|
servers.Add( "221.121.151.37:28215" );
|
||||||
|
servers.Add( "161.202.144.216:28215" );
|
||||||
|
servers.Add( "107.182.230.181:28215" );
|
||||||
|
servers.Add( "107.182.231.134:27101" );
|
||||||
|
servers.Add( "107.182.233.181:27101" );
|
||||||
|
servers.Add( "78.129.153.47:27101" );
|
||||||
|
servers.Add( "109.95.211.206:27101" );
|
||||||
|
servers.Add( "169.57.142.73:27101" );
|
||||||
|
servers.Add( "221.121.154.147:27101" );
|
||||||
|
servers.Add( "31.216.52.44:30015" );
|
||||||
|
servers.Add( "109.169.94.17:28215" );
|
||||||
|
servers.Add( "109.169.94.17:28315" );
|
||||||
|
servers.Add( "109.169.94.17:28015" );
|
||||||
|
servers.Add( "41.0.11.167:27141" );
|
||||||
|
servers.Add( "78.129.153.47:27131" );
|
||||||
|
servers.Add( "109.95.211.206:27111" );
|
||||||
|
servers.Add( "107.182.231.134:27111" );
|
||||||
|
servers.Add( "198.27.70.162:28015" );
|
||||||
|
servers.Add( "198.27.70.162:28215" );
|
||||||
|
servers.Add( "198.27.70.162:28115" );
|
||||||
|
servers.Add( "169.57.142.73:27111" );
|
||||||
|
servers.Add( "221.121.154.147:27111" );
|
||||||
|
servers.Add( "107.182.233.181:27111" );
|
||||||
|
servers.Add( "78.129.153.47:27111" );
|
||||||
|
servers.Add( "109.95.211.215:28015" );
|
||||||
|
servers.Add( "50.23.131.208:28015" );
|
||||||
|
servers.Add( "50.23.131.208:28115" );
|
||||||
|
servers.Add( "50.23.131.208:28215" );
|
||||||
|
servers.Add( "63.251.114.37:28215" );
|
||||||
|
servers.Add( "63.251.114.37:28115" );
|
||||||
|
servers.Add( "63.251.114.37:28015" );
|
||||||
|
servers.Add( "149.202.89.85:27101" );
|
||||||
|
servers.Add( "149.202.89.85:27111" );
|
||||||
|
servers.Add( "149.202.89.85:27131" );
|
||||||
|
servers.Add( "8.26.94.147:27101" );
|
||||||
|
servers.Add( "8.26.94.147:27111" );
|
||||||
|
servers.Add( "8.26.94.147:27121" );
|
||||||
|
servers.Add( "159.8.147.197:28025" );
|
||||||
|
servers.Add( "162.248.88.203:27038" );
|
||||||
|
servers.Add( "162.248.88.203:28091" );
|
||||||
|
servers.Add( "74.91.119.142:28069" );
|
||||||
|
servers.Add( "162.248.88.203:25063" );
|
||||||
|
servers.Add( "64.251.7.189:28115" );
|
||||||
|
servers.Add( "64.251.7.189:28015" );
|
||||||
|
servers.Add( "216.52.0.170:28215" );
|
||||||
|
servers.Add( "217.147.91.80:28215" );
|
||||||
|
servers.Add( "63.251.112.121:28215" );
|
||||||
|
servers.Add( "162.248.88.203:28074" );
|
||||||
|
servers.Add( "74.91.119.142:27095" );
|
||||||
|
servers.Add( "95.172.92.176:28065" );
|
||||||
|
servers.Add( "192.223.26.55:26032" );
|
||||||
|
servers.Add( "40.114.199.6:28085" );
|
||||||
|
servers.Add( "95.172.92.176:27095" );
|
||||||
|
servers.Add( "216.52.0.172:28015" );
|
||||||
|
servers.Add( "216.52.0.171:28115" );
|
||||||
|
servers.Add( "27.50.72.179:28015" );
|
||||||
|
servers.Add( "27.50.72.180:28115" );
|
||||||
|
servers.Add( "221.121.158.203:28015" );
|
||||||
|
servers.Add( "63.251.242.246:28015" );
|
||||||
|
servers.Add( "85.236.105.51:28015" );
|
||||||
|
servers.Add( "85.236.105.47:28015" );
|
||||||
|
servers.Add( "209.95.60.216:28015" );
|
||||||
|
servers.Add( "212.38.168.14:28015" );
|
||||||
|
servers.Add( "217.147.91.138:28015" );
|
||||||
|
servers.Add( "31.216.52.42:28015" );
|
||||||
|
servers.Add( "107.182.226.225:28015" );
|
||||||
|
servers.Add( "109.95.211.69:28015" );
|
||||||
|
servers.Add( "209.95.56.13:28015" );
|
||||||
|
servers.Add( "173.244.192.101:28015" );
|
||||||
|
servers.Add( "221.121.158.201:28115" );
|
||||||
|
servers.Add( "63.251.242.245:28115" );
|
||||||
|
servers.Add( "85.236.105.50:28115" );
|
||||||
|
servers.Add( "85.236.105.46:28115" );
|
||||||
|
servers.Add( "209.95.60.217:28115" );
|
||||||
|
servers.Add( "212.38.168.13:28115" );
|
||||||
|
servers.Add( "217.147.91.139:28115" );
|
||||||
|
servers.Add( "107.182.226.224:28115" );
|
||||||
|
servers.Add( "109.95.211.14:28115" );
|
||||||
|
servers.Add( "109.95.211.16:28115" );
|
||||||
|
servers.Add( "109.95.211.17:28115" );
|
||||||
|
servers.Add( "209.95.56.14:28115" );
|
||||||
|
servers.Add( "173.244.192.100:28115" );
|
||||||
|
servers.Add( "209.95.60.218:28215" );
|
||||||
|
servers.Add( "109.95.211.13:28215" );
|
||||||
|
servers.Add( "109.95.211.15:28215" );
|
||||||
|
servers.Add( "31.216.52.41:29015" );
|
||||||
|
|
||||||
|
var query = client.ServerList.Custom( servers );
|
||||||
|
|
||||||
|
for ( int i = 0; i < 1000; i++ )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep( 20 );
|
||||||
|
|
||||||
|
if ( query.Finished )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
||||||
|
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
||||||
|
|
||||||
|
foreach ( var s in query.Responded )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0} - {1}", s.AddressString, s.Name );
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Rules()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
||||||
|
filter.Add( "appid", client.AppId.ToString() );
|
||||||
|
filter.Add( "gamedir", "rust" );
|
||||||
|
filter.Add( "secure", "1" );
|
||||||
|
|
||||||
|
using ( var query = client.ServerList.Internet( filter ) )
|
||||||
|
{
|
||||||
|
|
||||||
|
for ( int i = 0; i < 1000; i++ )
|
||||||
|
{
|
||||||
|
GC.Collect();
|
||||||
|
client.Update();
|
||||||
|
GC.Collect();
|
||||||
|
System.Threading.Thread.Sleep( 10 );
|
||||||
|
|
||||||
|
if ( query.Responded.Count > 20 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( query.Finished )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Dispose();
|
||||||
|
|
||||||
|
foreach ( var server in query.Responded.Take( 20 ) )
|
||||||
|
{
|
||||||
|
GC.Collect();
|
||||||
|
server.FetchRules();
|
||||||
|
GC.Collect();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while ( !server.HasRules )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
GC.Collect();
|
||||||
|
client.Update();
|
||||||
|
GC.Collect();
|
||||||
|
System.Threading.Thread.Sleep( 2 );
|
||||||
|
|
||||||
|
if ( i > 100 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( server.HasRules )
|
||||||
|
{
|
||||||
|
foreach ( var rule in server.Rules )
|
||||||
|
{
|
||||||
|
Console.WriteLine( rule.Key + " = " + rule.Value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
Facepunch.Steamworks.Test/Client/Stats.cs
Normal file
73
Facepunch.Steamworks.Test/Client/Stats.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||||
|
[DeploymentItem( "steam_appid.txt" )]
|
||||||
|
public class Stats
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void UpdateStats()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
client.Stats.UpdateStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UpdateSUpdateGlobalStatstats()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
client.Stats.UpdateGlobalStats( 1 );
|
||||||
|
client.Stats.UpdateGlobalStats( 3 );
|
||||||
|
client.Stats.UpdateGlobalStats( 7 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetClientFloat()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var v = client.Stats.GetFloat( "deaths" );
|
||||||
|
Console.WriteLine( v );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetClientInt()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var v = client.Stats.GetInt( "deaths" );
|
||||||
|
Console.WriteLine( v );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetGlobalFloat()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var v = client.Stats.GetGlobalFloat( "deaths" );
|
||||||
|
Console.WriteLine( v );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetGlobalInt()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
var v = client.Stats.GetGlobalInt( "deaths" );
|
||||||
|
Console.WriteLine( v );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
425
Facepunch.Steamworks.Test/Client/Workshop.cs
Normal file
425
Facepunch.Steamworks.Test/Client/Workshop.cs
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||||
|
[DeploymentItem( "steam_appid.txt" )]
|
||||||
|
public class WorkshopTest
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void Query()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
var Query = client.Workshop.CreateQuery();
|
||||||
|
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
// Block, wait for result
|
||||||
|
// (don't do this in realtime)
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
|
||||||
|
// results
|
||||||
|
|
||||||
|
Console.WriteLine( "Searching" );
|
||||||
|
|
||||||
|
Query.Order = Workshop.Order.RankedByTextSearch;
|
||||||
|
Query.QueryType = Workshop.QueryType.MicrotransactionItems;
|
||||||
|
Query.SearchText = "black";
|
||||||
|
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
// Block, wait for result
|
||||||
|
// (don't do this in realtime)
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
foreach ( var item in Query.Items )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0}", item.Title );
|
||||||
|
Console.WriteLine( "\t WebsiteViews: {0}", item.WebsiteViews );
|
||||||
|
Console.WriteLine( "\t VotesUp: {0}", item.VotesUp );
|
||||||
|
Console.WriteLine( "\t PreviewUrl: {0}", item.PreviewImageUrl );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void QueryTagRequire()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
using ( var Query = client.Workshop.CreateQuery() )
|
||||||
|
{
|
||||||
|
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
foreach ( var item in Query.Items )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0}", item.Title );
|
||||||
|
Console.WriteLine( "\t{0}", string.Join( ";", item.Tags ) );
|
||||||
|
|
||||||
|
Assert.IsTrue( item.Tags.Contains( "LongTShirt Skin" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void QueryTagRequireMultiple()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
using ( var Query = client.Workshop.CreateQuery() )
|
||||||
|
{
|
||||||
|
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||||
|
Query.RequireTags.Add( "version2" );
|
||||||
|
Query.RequireAllTags = true;
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
foreach ( var item in Query.Items )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0}", item.Title );
|
||||||
|
Console.WriteLine( "\t{0}", string.Join( ";", item.Tags ) );
|
||||||
|
|
||||||
|
Assert.IsTrue( item.Tags.Contains( "LongTShirt Skin" ) );
|
||||||
|
Assert.IsTrue( item.Tags.Contains( "version2" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void QueryTagExclude()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
using ( var Query = client.Workshop.CreateQuery() )
|
||||||
|
{
|
||||||
|
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||||
|
Query.ExcludeTags.Add( "version2" );
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
foreach ( var item in Query.Items )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0}", item.Title );
|
||||||
|
Console.WriteLine( "\t{0}", string.Join( ";", item.Tags ) );
|
||||||
|
|
||||||
|
Assert.IsTrue( item.Tags.Contains( "LongTShirt Skin" ) );
|
||||||
|
Assert.IsFalse( item.Tags.Contains( "version2" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void QueryFile()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
using ( var Query = client.Workshop.CreateQuery() )
|
||||||
|
{
|
||||||
|
Query.FileId.Add( 751993251 );
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.IsRunning );
|
||||||
|
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.AreEqual( Query.TotalResults, 1 );
|
||||||
|
Assert.AreEqual( Query.Items.Length, 1 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
|
||||||
|
Assert.AreEqual<ulong>( Query.Items[0].Id, 751993251 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void QueryFiles()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
using ( var Query = client.Workshop.CreateQuery() )
|
||||||
|
{
|
||||||
|
Query.FileId.Add( 751993251 );
|
||||||
|
Query.FileId.Add( 747266909 );
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.IsRunning );
|
||||||
|
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.AreEqual( Query.TotalResults, 2 );
|
||||||
|
Assert.AreEqual( Query.Items.Length, 2 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.Items.Any( x => x.Id == 751993251 ) );
|
||||||
|
Assert.IsTrue( Query.Items.Any( x => x.Id == 747266909 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Query_255()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
using ( var Query = client.Workshop.CreateQuery() )
|
||||||
|
{
|
||||||
|
Query.PerPage = 255;
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.IsRunning );
|
||||||
|
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.AreEqual( Query.Items.Length, 255 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Query_28()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
using ( var Query = client.Workshop.CreateQuery() )
|
||||||
|
{
|
||||||
|
Query.PerPage = 28;
|
||||||
|
Query.Run();
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
var firstPage = Query.Items;
|
||||||
|
Assert.AreEqual( firstPage.Length, 28 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Page 2" );
|
||||||
|
Query.Page++;
|
||||||
|
Query.Run();
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
|
||||||
|
var secondPage = Query.Items;
|
||||||
|
Assert.AreEqual( secondPage.Length, 28 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Page 3" );
|
||||||
|
Query.Page++;
|
||||||
|
Query.Run();
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
var thirdPage = Query.Items;
|
||||||
|
Assert.AreEqual( thirdPage.Length, 28 );
|
||||||
|
|
||||||
|
foreach ( var i in firstPage )
|
||||||
|
{
|
||||||
|
Assert.IsFalse( secondPage.Any( x => x.Id == i.Id ) );
|
||||||
|
Assert.IsFalse( thirdPage.Any( x => x.Id == i.Id ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( var i in secondPage )
|
||||||
|
{
|
||||||
|
Assert.IsFalse( firstPage.Any( x => x.Id == i.Id ) );
|
||||||
|
Assert.IsFalse( thirdPage.Any( x => x.Id == i.Id ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( var i in thirdPage )
|
||||||
|
{
|
||||||
|
Assert.IsFalse( secondPage.Any( x => x.Id == i.Id ) );
|
||||||
|
Assert.IsFalse( firstPage.Any( x => x.Id == i.Id ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void DownloadFile()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
using ( var Query = client.Workshop.CreateQuery() )
|
||||||
|
{
|
||||||
|
Query.FileId.Add( 661319648 );
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
Assert.IsTrue( Query.IsRunning );
|
||||||
|
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.AreEqual( Query.TotalResults, 1 );
|
||||||
|
Assert.AreEqual( Query.Items.Length, 1 );
|
||||||
|
|
||||||
|
var item = Query.Items[0];
|
||||||
|
|
||||||
|
if ( !item.Installed )
|
||||||
|
{
|
||||||
|
item.Download();
|
||||||
|
|
||||||
|
while ( item.Downloading )
|
||||||
|
{
|
||||||
|
Thread.Sleep( 500 );
|
||||||
|
client.Update();
|
||||||
|
Console.WriteLine( "Download Progress: {0}", item.DownloadProgress );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsNotNull( item.Directory );
|
||||||
|
Assert.AreNotEqual( 0, item.Size );
|
||||||
|
|
||||||
|
Console.WriteLine( "item.Installed: {0}", item.Installed );
|
||||||
|
Console.WriteLine( "item.Downloading: {0}", item.Downloading );
|
||||||
|
Console.WriteLine( "item.DownloadPending: {0}", item.DownloadPending );
|
||||||
|
Console.WriteLine( "item.Directory: {0}", item.Directory );
|
||||||
|
Console.WriteLine( "item.Size: {0}mb", (item.Size / 1024 / 1024) );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[TestCategory( "Run Manually" )]
|
||||||
|
public void CreatePublish()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
var item = client.Workshop.CreateItem( Workshop.ItemType.Microtransaction );
|
||||||
|
|
||||||
|
item.Title = "Facepunch.Steamworks Unit test";
|
||||||
|
item.Tags.Add( "Apple" );
|
||||||
|
item.Tags.Add( "Banana" );
|
||||||
|
item.Publish();
|
||||||
|
|
||||||
|
while ( item.Publishing )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
Thread.Sleep( 100 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsFalse( item.Publishing );
|
||||||
|
Assert.AreNotEqual( 0, item.Id );
|
||||||
|
Assert.IsNull( item.Error );
|
||||||
|
|
||||||
|
Console.WriteLine( "item.Id: {0}", item.Id );
|
||||||
|
|
||||||
|
item.Delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UserQuery()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
var Query = client.Workshop.CreateQuery();
|
||||||
|
|
||||||
|
Query.UserId = 76561197960279927;
|
||||||
|
Query.UserQueryType = Workshop.UserQueryType.Published;
|
||||||
|
|
||||||
|
Query.Run();
|
||||||
|
|
||||||
|
// Block, wait for result
|
||||||
|
// (don't do this in realtime)
|
||||||
|
Query.Block();
|
||||||
|
|
||||||
|
Assert.IsFalse( Query.IsRunning );
|
||||||
|
Assert.IsTrue( Query.TotalResults > 0 );
|
||||||
|
Assert.IsTrue( Query.Items.Length > 0 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||||
|
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||||
|
|
||||||
|
foreach ( var item in Query.Items )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "{0}", item.Title );
|
||||||
|
Assert.AreEqual<ulong>( item.OwnerId, 76561197960279927 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
137
Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj
Normal file
137
Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{3F6183AD-D966-44F2-A6EB-42E61E591B49}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>Facepunch.Steamworks.Test</RootNamespace>
|
||||||
|
<AssemblyName>Facepunch.Steamworks.Test</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||||
|
<IsCodedUITest>False</IsCodedUITest>
|
||||||
|
<TestProjectType>UnitTest</TestProjectType>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||||
|
<OutputPath>bin\x64\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||||
|
<OutputPath>bin\x86\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
<Otherwise>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework">
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</Otherwise>
|
||||||
|
</Choose>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Client\Client.cs" />
|
||||||
|
<Compile Include="Client\Workshop.cs" />
|
||||||
|
<Compile Include="Client\Networking.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Client\Friends.cs" />
|
||||||
|
<Compile Include="Server\Inventory.cs" />
|
||||||
|
<Compile Include="Server\Server.cs" />
|
||||||
|
<Compile Include="Server\Stats.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.csproj">
|
||||||
|
<Project>{dc2d9fa9-f005-468f-8581-85c79f4e0034}</Project>
|
||||||
|
<Name>Facepunch.Steamworks</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Client\Serverlist.cs" />
|
||||||
|
<Compile Include="Client\Stats.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Choose>
|
||||||
|
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</When>
|
||||||
|
</Choose>
|
||||||
|
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
@ -1,55 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DefineConstants>TRACE;DEBUG;TEST_WIN32</DefineConstants>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DefineConstants>TRACE;TEST_WIN32</DefineConstants>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
|
||||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="steam_api.dll">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.*" />
|
|
||||||
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0-beta4" />
|
|
||||||
<PackageReference Include="MSTest.TestFramework" Version="2.0.0-beta4" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.2-beta1" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="ClanTest.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,54 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DefineConstants>TRACE;DEBUG;TEST_WIN64</DefineConstants>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
|
||||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="steam_api64.dll">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.*" />
|
|
||||||
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0-beta4" />
|
|
||||||
<PackageReference Include="MSTest.TestFramework" Version="2.0.0-beta4" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.2-beta1" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="ClanTest.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,154 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
[TestClass]
|
|
||||||
public class FriendsTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void GetFriends()
|
|
||||||
{
|
|
||||||
foreach ( var friend in SteamFriends.GetFriends() )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{friend.Id.Value}: {friend.Name} (Friend:{friend.IsFriend}) (Blocked:{friend.IsBlocked})" );
|
|
||||||
Console.WriteLine( $" {string.Join( ", ", friend.NameHistory )}" );
|
|
||||||
|
|
||||||
// Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GetBlocked()
|
|
||||||
{
|
|
||||||
foreach ( var friend in SteamFriends.GetBlocked() )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{friend.Id.Value}: {friend.Name} (Friend:{friend.IsFriend}) (Blocked:{friend.IsBlocked})" );
|
|
||||||
Console.WriteLine( $" {string.Join( ", ", friend.NameHistory )}" );
|
|
||||||
|
|
||||||
// Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetPlayedWith()
|
|
||||||
{
|
|
||||||
foreach ( var friend in SteamFriends.GetPlayedWith() )
|
|
||||||
{
|
|
||||||
await friend.RequestInfoAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"{friend.Id.Value}: {friend.Name} (Friend:{friend.IsFriend}) (Blocked:{friend.IsBlocked})" );
|
|
||||||
Console.WriteLine( $" {string.Join( ", ", friend.NameHistory )}" );
|
|
||||||
|
|
||||||
// Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task LargeAvatar()
|
|
||||||
{
|
|
||||||
ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000));
|
|
||||||
|
|
||||||
var image = await SteamFriends.GetLargeAvatarAsync( id );
|
|
||||||
if ( !image.HasValue )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Console.WriteLine( $"image.Width {image.Value.Width}" );
|
|
||||||
Console.WriteLine( $"image.Height {image.Value.Height}" );
|
|
||||||
|
|
||||||
DrawImage( image.Value );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task MediumAvatar()
|
|
||||||
{
|
|
||||||
ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000));
|
|
||||||
|
|
||||||
Console.WriteLine( $"Steam: http://steamcommunity.com/profiles/{id}" );
|
|
||||||
|
|
||||||
var image = await SteamFriends.GetMediumAvatarAsync( id );
|
|
||||||
if ( !image.HasValue )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Console.WriteLine( $"image.Width {image.Value.Width}" );
|
|
||||||
Console.WriteLine( $"image.Height {image.Value.Height}" );
|
|
||||||
|
|
||||||
DrawImage( image.Value );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task SmallAvatar()
|
|
||||||
{
|
|
||||||
ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000));
|
|
||||||
|
|
||||||
var image = await SteamFriends.GetSmallAvatarAsync( id );
|
|
||||||
if ( !image.HasValue )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Console.WriteLine( $"image.Width {image.Value.Width}" );
|
|
||||||
Console.WriteLine( $"image.Height {image.Value.Height}" );
|
|
||||||
|
|
||||||
DrawImage( image.Value );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetFriendsAvatars()
|
|
||||||
{
|
|
||||||
foreach ( var friend in SteamFriends.GetFriends() )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{friend.Id.Value}: {friend.Name}" );
|
|
||||||
|
|
||||||
var image = await friend.GetSmallAvatarAsync();
|
|
||||||
if ( image.HasValue )
|
|
||||||
{
|
|
||||||
DrawImage( image.Value );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task OpenWebOverlay()
|
|
||||||
{
|
|
||||||
if ( SteamUtils.IsOverlayEnabled )
|
|
||||||
Console.WriteLine( "Overlay Is Enabled" );
|
|
||||||
else
|
|
||||||
Console.WriteLine( "Overlay Is Not Enabled" );
|
|
||||||
|
|
||||||
SteamFriends.OpenWebOverlay( "https://www.google.com/" );
|
|
||||||
|
|
||||||
await Task.Delay( 2000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void DrawImage( Image img )
|
|
||||||
{
|
|
||||||
var grad = " -:+#";
|
|
||||||
|
|
||||||
for ( int y = 0; y < img.Height; y++ )
|
|
||||||
{
|
|
||||||
var str = "";
|
|
||||||
|
|
||||||
for ( int x = 0; x < img.Width; x++ )
|
|
||||||
{
|
|
||||||
var p = img.GetPixel( x, y );
|
|
||||||
|
|
||||||
var brightness = 1 - ((float)(p.r + p.g + p.b) / (255.0f * 3.0f));
|
|
||||||
var c = (int)((grad.Length) * brightness);
|
|
||||||
if ( c > 3 ) c = 3;
|
|
||||||
str += grad[c];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( str );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class GameServerStatsTest
|
|
||||||
{
|
|
||||||
static SteamId Garry = 76561197960279927;
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetAchievement()
|
|
||||||
{
|
|
||||||
var result = await SteamServerStats.RequestUserStatsAsync( Garry );
|
|
||||||
Assert.AreEqual( result, Result.OK );
|
|
||||||
|
|
||||||
var value = SteamServerStats.GetAchievement( Garry, "COLLECT_100_WOOD" );
|
|
||||||
Assert.IsTrue( value );
|
|
||||||
|
|
||||||
value = SteamServerStats.GetAchievement( Garry, "ACHIVEMENT_THAT_DOESNT_EXIST" );
|
|
||||||
Assert.IsFalse( value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,128 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
[TestClass]
|
|
||||||
public partial class GameServerTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
SteamServer.DedicatedServer = true;
|
|
||||||
SteamServer.DedicatedServer = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task PublicIp()
|
|
||||||
{
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
var ip = SteamServer.PublicIp;
|
|
||||||
|
|
||||||
if ( ip == null )
|
|
||||||
{
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.IsNotNull( ip );
|
|
||||||
Console.WriteLine( ip.ToString() );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task BeginAuthSession()
|
|
||||||
{
|
|
||||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
||||||
bool finished = false;
|
|
||||||
string failed = null;
|
|
||||||
AuthResponse response = AuthResponse.AuthTicketInvalidAlreadyUsed;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Clientside calls this function, gets ticket
|
|
||||||
//
|
|
||||||
var clientTicket = SteamUser.GetAuthSessionTicket( NetIdentity.LocalHost );
|
|
||||||
|
|
||||||
//
|
|
||||||
// The client sends this data to the server along with their steamid
|
|
||||||
//
|
|
||||||
var ticketData = clientTicket.Data;
|
|
||||||
var clientSteamId = SteamClient.SteamId;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Server listens to auth responses from Gabe
|
|
||||||
//
|
|
||||||
SteamServer.OnValidateAuthTicketResponse += ( steamid, ownerid, rsponse ) =>
|
|
||||||
{
|
|
||||||
finished = true;
|
|
||||||
response = rsponse;
|
|
||||||
|
|
||||||
if ( steamid == 0 )
|
|
||||||
failed = $"steamid is 0! {steamid} != {ownerid} ({rsponse})";
|
|
||||||
|
|
||||||
if ( ownerid == 0 )
|
|
||||||
failed = $"ownerid is 0! {steamid} != {ownerid} ({rsponse})";
|
|
||||||
|
|
||||||
if ( steamid != ownerid )
|
|
||||||
failed = $"Steamid and Ownerid are different! {steamid} != {ownerid} ({rsponse})";
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Server gets the ticket, starts authing
|
|
||||||
//
|
|
||||||
if ( !SteamServer.BeginAuthSession( ticketData, clientSteamId ) )
|
|
||||||
{
|
|
||||||
Assert.Fail( "BeginAuthSession returned false, called bullshit without even having to check with Gabe" );
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Wait for that to go through steam
|
|
||||||
//
|
|
||||||
while ( !finished )
|
|
||||||
{
|
|
||||||
if ( stopwatch.Elapsed.TotalSeconds > 5 )
|
|
||||||
throw new System.Exception( "Took too long waiting for AuthSessionResponse.OK" );
|
|
||||||
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.AreEqual( response, AuthResponse.OK );
|
|
||||||
|
|
||||||
if ( failed != null )
|
|
||||||
Assert.Fail( failed );
|
|
||||||
|
|
||||||
finished = false;
|
|
||||||
stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
||||||
|
|
||||||
//
|
|
||||||
// The client is leaving, and now wants to cancel the ticket
|
|
||||||
//
|
|
||||||
|
|
||||||
Assert.AreNotEqual( 0, clientTicket.Handle );
|
|
||||||
clientTicket.Cancel();
|
|
||||||
|
|
||||||
//
|
|
||||||
// We should get another callback
|
|
||||||
//
|
|
||||||
while ( !finished )
|
|
||||||
{
|
|
||||||
if ( stopwatch.Elapsed.TotalSeconds > 5 )
|
|
||||||
throw new System.Exception( "Took too long waiting for AuthSessionResponse.AuthTicketCanceled" );
|
|
||||||
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( failed != null )
|
|
||||||
Assert.Fail( failed );
|
|
||||||
|
|
||||||
//Assert.AreEqual( response, AuthResponse.AuthTicketCanceled );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
[DeploymentItem( "controller_config/game_actions_252490.vdf" )]
|
|
||||||
public class InputTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void ControllerList()
|
|
||||||
{
|
|
||||||
foreach ( var controller in SteamInput.Controllers )
|
|
||||||
{
|
|
||||||
Console.Write( $"Controller: {controller}" );
|
|
||||||
|
|
||||||
var dstate = controller.GetDigitalState( "fire" );
|
|
||||||
var astate = controller.GetAnalogState( "Move" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,223 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class InventoryTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public async Task LoadItemDefinitionsAsync()
|
|
||||||
{
|
|
||||||
var result = await SteamInventory.WaitForDefinitions( 5 );
|
|
||||||
Assert.IsTrue( result );
|
|
||||||
|
|
||||||
result = await SteamInventory.WaitForDefinitions( 5 );
|
|
||||||
Assert.IsTrue( result );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetDefinitions()
|
|
||||||
{
|
|
||||||
await SteamInventory.WaitForDefinitions();
|
|
||||||
|
|
||||||
Assert.IsNotNull( SteamInventory.Definitions );
|
|
||||||
|
|
||||||
foreach ( var def in SteamInventory.Definitions )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[{def.Id:0000000000}] {def.Name} [{def.Type}]" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetDefinitionsWithPrices()
|
|
||||||
{
|
|
||||||
var defs = await SteamInventory.GetDefinitionsWithPricesAsync();
|
|
||||||
|
|
||||||
foreach ( var def in defs )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[{def.Id:0000000000}] {def.Name} [{def.LocalPriceFormatted}]" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetAllItems()
|
|
||||||
{
|
|
||||||
await SteamInventory.WaitForDefinitions();
|
|
||||||
|
|
||||||
var result = await SteamInventory.GetAllItemsAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
Assert.IsTrue( result.Value.ItemCount > 0 );
|
|
||||||
|
|
||||||
using ( result )
|
|
||||||
{
|
|
||||||
var items = result.Value.GetItems( true );
|
|
||||||
|
|
||||||
Assert.IsNotNull( items );
|
|
||||||
|
|
||||||
foreach ( var item in items )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{item.Id} / {item.DefId} / {item.Quantity} / {item.Def?.Name} /[{item.IsNoTrade}|{item.IsRemoved}|{item.IsConsumed}] " );
|
|
||||||
|
|
||||||
foreach ( var prop in item.Properties )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" {prop.Key} : {prop.Value}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetItemSpecialProperties()
|
|
||||||
{
|
|
||||||
await SteamInventory.WaitForDefinitions();
|
|
||||||
|
|
||||||
var result = await SteamInventory.GetAllItemsAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
Assert.IsTrue( result.Value.ItemCount > 0 );
|
|
||||||
|
|
||||||
using ( result )
|
|
||||||
{
|
|
||||||
var items = result.Value.GetItems( true );
|
|
||||||
|
|
||||||
Assert.IsNotNull( items );
|
|
||||||
|
|
||||||
foreach ( var item in items )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{item.Id} / {item.DefId} / {item.Quantity} / {item.Def?.Name} " );
|
|
||||||
|
|
||||||
Console.WriteLine( $" Acquired: {item.Acquired}" );
|
|
||||||
Console.WriteLine( $" Origin: {item.Origin}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetAllItemsMultipleTimes()
|
|
||||||
{
|
|
||||||
await SteamInventory.WaitForDefinitions();
|
|
||||||
|
|
||||||
var fresult = await SteamInventory.GetAllItemsAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( fresult.HasValue );
|
|
||||||
Assert.IsTrue( fresult.Value.ItemCount > 0 );
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
var result = await SteamInventory.GetAllItemsAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
Assert.IsTrue( result.Value.GetItems().Length == fresult.Value.ItemCount );
|
|
||||||
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
result = await SteamInventory.GetAllItemsAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
Assert.IsTrue( result.Value.ItemCount == fresult.Value.ItemCount );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task Items()
|
|
||||||
{
|
|
||||||
SteamInventory.GetAllItems();
|
|
||||||
await SteamInventory.WaitForDefinitions();
|
|
||||||
|
|
||||||
while ( SteamInventory.Items == null )
|
|
||||||
{
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.IsNotNull( SteamInventory.Items );
|
|
||||||
|
|
||||||
foreach ( var item in SteamInventory.Items )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{item.Id} / {item.DefId} / {item.Quantity} / {item.Def.Name}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetExchanges()
|
|
||||||
{
|
|
||||||
var result = await SteamInventory.WaitForDefinitions( 5 );
|
|
||||||
Assert.IsTrue( result );
|
|
||||||
|
|
||||||
foreach ( var def in SteamInventory.Definitions )
|
|
||||||
{
|
|
||||||
var exchangelist = def.GetRecipes();
|
|
||||||
if ( exchangelist == null ) continue;
|
|
||||||
|
|
||||||
foreach ( var exchange in exchangelist )
|
|
||||||
{
|
|
||||||
Assert.AreEqual( exchange.Result, def );
|
|
||||||
|
|
||||||
Console.WriteLine( $"{def.Name}:" );
|
|
||||||
|
|
||||||
foreach ( var item in exchange.Ingredients )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" {item.Count} x {item.Definition?.Name ?? item.DefinitionId.ToString()}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( $"" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task Serialize()
|
|
||||||
{
|
|
||||||
await SteamInventory.WaitForDefinitions();
|
|
||||||
|
|
||||||
var result = await SteamInventory.GetAllItemsAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
|
|
||||||
var data = result.Value.Serialize();
|
|
||||||
|
|
||||||
Assert.IsNotNull( data );
|
|
||||||
|
|
||||||
Console.WriteLine( string.Join( "", data.Select( x => x.ToString( "x" ) ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task Deserialize()
|
|
||||||
{
|
|
||||||
await SteamInventory.WaitForDefinitions();
|
|
||||||
|
|
||||||
byte[] data;
|
|
||||||
int itemCount;
|
|
||||||
|
|
||||||
// Serialize
|
|
||||||
{
|
|
||||||
var result = await SteamInventory.GetAllItemsAsync();
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
itemCount = result.Value.ItemCount;
|
|
||||||
data = result.Value.Serialize();
|
|
||||||
Assert.IsNotNull( data );
|
|
||||||
result.Value.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay( 2000 );
|
|
||||||
|
|
||||||
// Deserialize
|
|
||||||
{
|
|
||||||
var result = await SteamInventory.DeserializeAsync( data );
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
Assert.AreEqual( itemCount, result.Value.ItemCount );
|
|
||||||
result.Value.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,163 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public partial class NetworkingSocketsTest
|
|
||||||
{
|
|
||||||
void DebugOutput( NetDebugOutput type, string text )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[NET:{type}]\t\t{text}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CreateRelayServer()
|
|
||||||
{
|
|
||||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Everything;
|
|
||||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
|
||||||
|
|
||||||
var si = SteamNetworkingSockets.CreateRelaySocket<TestSocketInterface>();
|
|
||||||
|
|
||||||
Console.WriteLine( $"Created Socket: {si}" );
|
|
||||||
|
|
||||||
// Give it a second for something to happen
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
si.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CreateNormalServer()
|
|
||||||
{
|
|
||||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Everything;
|
|
||||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
|
||||||
|
|
||||||
var si = SteamNetworkingSockets.CreateNormalSocket<TestSocketInterface>( Data.NetAddress.AnyIp( 21893 ) );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Created Socket: {si}" );
|
|
||||||
|
|
||||||
// Give it a second for something to happen
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
si.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CreateRelayServerFakeIP()
|
|
||||||
{
|
|
||||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Everything;
|
|
||||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
|
||||||
|
|
||||||
var si = SteamNetworkingSockets.CreateRelaySocketFakeIP<TestSocketInterface>();
|
|
||||||
|
|
||||||
Console.WriteLine( $"Created Socket: {si}" );
|
|
||||||
|
|
||||||
// Give it a second for something to happen
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
si.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task RelayEndtoEnd()
|
|
||||||
{
|
|
||||||
SteamNetworkingUtils.InitRelayNetworkAccess();
|
|
||||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Warning;
|
|
||||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
|
||||||
|
|
||||||
// For some reason giving steam a couple of seconds here
|
|
||||||
// seems to prevent it returning null connections from ConnectNormal
|
|
||||||
await Task.Delay( 2000 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"----- Creating Socket Relay Socket.." );
|
|
||||||
var socket = SteamNetworkingSockets.CreateRelaySocket<TestSocketInterface>( 6 );
|
|
||||||
var server = socket.RunAsync();
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"----- Connecting To Socket via SteamId ({SteamClient.SteamId})" );
|
|
||||||
var connection = SteamNetworkingSockets.ConnectRelay<TestConnectionInterface>( SteamClient.SteamId, 6 );
|
|
||||||
var client = connection.RunAsync();
|
|
||||||
|
|
||||||
await Task.WhenAll( server, client );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task NormalEndtoEnd()
|
|
||||||
{
|
|
||||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Everything;
|
|
||||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
|
||||||
|
|
||||||
// For some reason giving steam a couple of seconds here
|
|
||||||
// seems to prevent it returning null connections from ConnectNormal
|
|
||||||
await Task.Delay( 2000 );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the server
|
|
||||||
//
|
|
||||||
Console.WriteLine( "CreateNormalSocket" );
|
|
||||||
var socket = SteamNetworkingSockets.CreateNormalSocket<TestSocketInterface>( NetAddress.AnyIp( 12445 ) );
|
|
||||||
var server = socket.RunAsync();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start the client
|
|
||||||
//
|
|
||||||
Console.WriteLine( "ConnectNormal" );
|
|
||||||
var connection = SteamNetworkingSockets.ConnectNormal<TestConnectionInterface>( NetAddress.From( "127.0.0.1", 12445 ) );
|
|
||||||
var client = connection.RunAsync();
|
|
||||||
|
|
||||||
await Task.WhenAll( server, client );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task RelayEndtoEndFakeIP()
|
|
||||||
{
|
|
||||||
SteamNetworkingUtils.InitRelayNetworkAccess();
|
|
||||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Warning;
|
|
||||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
|
||||||
|
|
||||||
// For some reason giving steam a couple of seconds here
|
|
||||||
// seems to prevent it returning null connections from ConnectNormal
|
|
||||||
await Task.Delay( 2000 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"----- Creating Socket Relay Socket.." );
|
|
||||||
var socket = SteamNetworkingSockets.CreateRelaySocketFakeIP<TestSocketInterface>();
|
|
||||||
var server = socket.RunAsync();
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"----- Retrieving Fake IP.." );
|
|
||||||
SteamNetworkingSockets.GetFakeIP( 0, out NetAddress address );
|
|
||||||
|
|
||||||
Console.WriteLine( $"----- Connecting To Socket via Fake IP ({address})" );
|
|
||||||
var connection = SteamNetworkingSockets.ConnectNormal<TestConnectionInterface>( address );
|
|
||||||
var client = connection.RunAsync();
|
|
||||||
|
|
||||||
await Task.WhenAll( server, client );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void NetAddressTest()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
var n = NetAddress.From( "127.0.0.1", 12445 );
|
|
||||||
Assert.AreEqual( n.ToString(), "127.0.0.1:12445" );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var n = NetAddress.AnyIp( 5543 );
|
|
||||||
Assert.AreEqual( n.ToString(), "[::]:5543" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
public partial class NetworkingSocketsTest
|
|
||||||
{
|
|
||||||
private class TestConnectionInterface : ConnectionManager
|
|
||||||
{
|
|
||||||
public override void OnConnectionChanged( ConnectionInfo data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[Connection][{Connection}] [{data.State}]" );
|
|
||||||
|
|
||||||
base.OnConnectionChanged( data );
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnConnecting( ConnectionInfo data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" - OnConnecting" );
|
|
||||||
base.OnConnecting( data );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Client is connected. They move from connecting to Connections
|
|
||||||
/// </summary>
|
|
||||||
public override void OnConnected( ConnectionInfo data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" - OnConnected" );
|
|
||||||
base.OnConnected( data );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The connection has been closed remotely or disconnected locally. Check data.State for details.
|
|
||||||
/// </summary>
|
|
||||||
public override void OnDisconnected( ConnectionInfo data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" - OnDisconnected" );
|
|
||||||
base.OnDisconnected( data );
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async Task RunAsync()
|
|
||||||
{
|
|
||||||
Console.WriteLine( "[Connection] RunAsync" );
|
|
||||||
|
|
||||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
|
||||||
|
|
||||||
Console.WriteLine( "[Connection] Connecting" );
|
|
||||||
while ( Connecting )
|
|
||||||
{
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
|
|
||||||
if ( sw.Elapsed.TotalSeconds > 10 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !Connected )
|
|
||||||
{
|
|
||||||
Console.WriteLine( "[Connection] Couldn't connect!" );
|
|
||||||
Console.WriteLine( Connection.DetailedStatus() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( "[Connection] Hey We're Connected!" );
|
|
||||||
|
|
||||||
|
|
||||||
sw = System.Diagnostics.Stopwatch.StartNew();
|
|
||||||
while ( Connected )
|
|
||||||
{
|
|
||||||
Receive();
|
|
||||||
await Task.Delay( 100 );
|
|
||||||
|
|
||||||
if ( sw.Elapsed.TotalSeconds > 30 )
|
|
||||||
{
|
|
||||||
Assert.Fail( "Client Took Too Long" );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override unsafe void OnMessage( IntPtr data, int size, long messageNum, long recvTime, int channel )
|
|
||||||
{
|
|
||||||
// We're only sending strings, so it's fine to read this like this
|
|
||||||
var str = Utility.Utf8NoBom.GetString( (byte*) data, size );
|
|
||||||
|
|
||||||
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] \"{str}\"" );
|
|
||||||
|
|
||||||
if ( str.Contains( "Hello" ) )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] Sending: Hello, How are you!?" );
|
|
||||||
Connection.SendMessage( "Hello, How are you!?" );
|
|
||||||
|
|
||||||
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] Sending: How do you like 20 messages in a row?" );
|
|
||||||
Connection.SendMessage( "How do you like 20 messages in a row?" );
|
|
||||||
|
|
||||||
var connections = new[] { Connection };
|
|
||||||
var results = new Result[1];
|
|
||||||
for ( int i=0; i<20; i++ )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] Sending: BLAMMO {i}!" );
|
|
||||||
SendMessages( connections, connections.Length, $"BLAMMO {i}!", results: results );
|
|
||||||
Assert.AreEqual( Result.OK, results[0] );
|
|
||||||
}
|
|
||||||
|
|
||||||
Connection.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( str.Contains( "status" ))
|
|
||||||
{
|
|
||||||
Console.WriteLine( Connection.DetailedStatus() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( str.Contains( "how about yourself" ) )
|
|
||||||
{
|
|
||||||
Connection.SendMessage( "I'm great, but I have to go now, bye." );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( str.Contains( "hater" ) )
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,137 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
public partial class NetworkingSocketsTest
|
|
||||||
{
|
|
||||||
private class TestSocketInterface : SocketManager
|
|
||||||
{
|
|
||||||
public bool HasFinished = false;
|
|
||||||
|
|
||||||
public override void OnConnectionChanged( Connection connection, ConnectionInfo data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[Socket{Socket}][connection:{connection}][data.Identity:{data.Identity}] [data.State:{data.State}]" );
|
|
||||||
|
|
||||||
base.OnConnectionChanged( connection, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnConnecting( Connection connection, ConnectionInfo data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" - OnConnecting" );
|
|
||||||
base.OnConnecting( connection, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Client is connected. They move from connecting to Connections
|
|
||||||
/// </summary>
|
|
||||||
public override void OnConnected( Connection connection, ConnectionInfo data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"" );
|
|
||||||
Console.WriteLine( $"Socket -> OnConnected:" );
|
|
||||||
Console.WriteLine( $" data.Address: {data.Address}" );
|
|
||||||
Console.WriteLine( $" data.Identity: {data.Identity}" );
|
|
||||||
Console.WriteLine( $" data.Identity.Steamid: {data.Identity.SteamId}" );
|
|
||||||
Console.WriteLine( $" data.Identity.IsIpAddress: {data.Identity.IsIpAddress}" );
|
|
||||||
Console.WriteLine( $" data.Identity.IsLocalHost: {data.Identity.IsLocalHost}" );
|
|
||||||
Console.WriteLine( $" data.Identity.IsSteamId: {data.Identity.IsSteamId}" );
|
|
||||||
Console.WriteLine( $" data.Identity.Address: {data.Identity.Address}" );
|
|
||||||
Console.WriteLine( $" data.Identity.Address.Address: {data.Identity.Address.Address}" );
|
|
||||||
Console.WriteLine( $" data.Identity.Address.Port: {data.Identity.Address.Port}" );
|
|
||||||
Console.WriteLine( $"" );
|
|
||||||
|
|
||||||
base.OnConnected( connection, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The connection has been closed remotely or disconnected locally. Check data.State for details.
|
|
||||||
/// </summary>
|
|
||||||
public override void OnDisconnected( Connection connection, ConnectionInfo data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" - OnDisconnected" );
|
|
||||||
|
|
||||||
base.OnDisconnected( connection, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async Task RunAsync()
|
|
||||||
{
|
|
||||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
|
||||||
|
|
||||||
while ( Connected.Count == 0 )
|
|
||||||
{
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
|
|
||||||
if ( sw.Elapsed.TotalSeconds > 10 )
|
|
||||||
{
|
|
||||||
Assert.Fail( "Client Took Too Long To Connect" );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
var singleClient = Connected.First();
|
|
||||||
|
|
||||||
singleClient.SendMessage( "Hey?" );
|
|
||||||
await Task.Delay( 100 );
|
|
||||||
singleClient.SendMessage( "Anyone?" );
|
|
||||||
await Task.Delay( 100 );
|
|
||||||
singleClient.SendMessage( "What's this?" );
|
|
||||||
await Task.Delay( 100 );
|
|
||||||
singleClient.SendMessage( "What's your status?" );
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
singleClient.SendMessage( "Greetings!!??" );
|
|
||||||
await Task.Delay( 100 );
|
|
||||||
singleClient.SendMessage( "Hello Client!?" );
|
|
||||||
|
|
||||||
sw = System.Diagnostics.Stopwatch.StartNew();
|
|
||||||
|
|
||||||
Console.WriteLine( $"Socket: Listening" );
|
|
||||||
|
|
||||||
while ( Connected.Contains( singleClient ) )
|
|
||||||
{
|
|
||||||
Receive();
|
|
||||||
await Task.Delay( 100 );
|
|
||||||
|
|
||||||
if ( sw.Elapsed.TotalSeconds > 30 )
|
|
||||||
{
|
|
||||||
Console.WriteLine( "Socket: This all took too long - throwing an exception" );
|
|
||||||
Assert.Fail( "Socket Took Too Long" );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( $"Socket: Closing connection because {Connected.Count()} Connected" );
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override unsafe void OnMessage( Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel )
|
|
||||||
{
|
|
||||||
// We're only sending strings, so it's fine to read this like this
|
|
||||||
var str = Utility.Utf8NoBom.GetString( (byte*)data, size );
|
|
||||||
|
|
||||||
Console.WriteLine( $"[SOCKET][{connection}[{identity}][{messageNum}][{recvTime}][{channel}] \"{str}\"" );
|
|
||||||
|
|
||||||
if ( str.Contains( "Hello, How are you" ) )
|
|
||||||
{
|
|
||||||
connection.SendMessage( "I'm great thanks, how about yourself?" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( str.Contains( "bye" ) )
|
|
||||||
{
|
|
||||||
connection.SendMessage( "See you later, hater." );
|
|
||||||
connection.Flush();
|
|
||||||
connection.Close( true, 10, "Said Bye" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class NetworkUtilsTest
|
|
||||||
{
|
|
||||||
static string GarrysLocation = "lhr=4+0,ams=13+1/10+0,par=17+1/12+0,lux=17+1,fra=18+1/18+0,sto=25+2,sto2=26+2,mad=27+2,vie=31+3/30+0,iad=90+9/75+0,sgp=173+17/174+17,gru=200+20/219+0";
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task LocalPingLocation()
|
|
||||||
{
|
|
||||||
await SteamNetworkingUtils.WaitForPingDataAsync();
|
|
||||||
|
|
||||||
for ( int i = 0; i < 10; i++ )
|
|
||||||
{
|
|
||||||
var pl = SteamNetworkingUtils.LocalPingLocation;
|
|
||||||
if ( !pl.HasValue )
|
|
||||||
{
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( $"{i} Seconds Until Result: {pl}" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.Fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void PingLocationParse()
|
|
||||||
{
|
|
||||||
var pl = Data.NetPingLocation.TryParseFromString( GarrysLocation );
|
|
||||||
|
|
||||||
Assert.IsTrue( pl.HasValue );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Parsed OKAY! {pl}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetEstimatedPing()
|
|
||||||
{
|
|
||||||
await SteamNetworkingUtils.WaitForPingDataAsync();
|
|
||||||
|
|
||||||
var garrysping = Data.NetPingLocation.TryParseFromString( GarrysLocation );
|
|
||||||
Assert.IsTrue( garrysping.HasValue );
|
|
||||||
|
|
||||||
var ping = SteamNetworkingUtils.EstimatePingTo( garrysping.Value );
|
|
||||||
Assert.IsTrue( ping > 0 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Ping returned: {ping}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class RemotePlayTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void BasicUsability()
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"Sessions: {SteamRemotePlay.SessionCount}" );
|
|
||||||
|
|
||||||
var session = SteamRemotePlay.GetSession( 4 );
|
|
||||||
|
|
||||||
Assert.IsFalse( session.IsValid );
|
|
||||||
Assert.IsFalse( session.SteamId.IsValid );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class RemoteStorageTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void Quotas()
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"SteamRemoteStorage.QuotaBytes: {SteamRemoteStorage.QuotaBytes}" );
|
|
||||||
Console.WriteLine( $"SteamRemoteStorage.QuotaRemainingBytes: {SteamRemoteStorage.QuotaRemainingBytes}" );
|
|
||||||
Console.WriteLine( $"SteamRemoteStorage.QuotaUsedBytes: {SteamRemoteStorage.QuotaUsedBytes}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsCloudEnabled()
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabled: {SteamRemoteStorage.IsCloudEnabled}" );
|
|
||||||
Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabledForAccount: {SteamRemoteStorage.IsCloudEnabledForAccount}" );
|
|
||||||
Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabledForApp: {SteamRemoteStorage.IsCloudEnabledForApp}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void FileWrite()
|
|
||||||
{
|
|
||||||
var rand = new Random();
|
|
||||||
var testFile = new byte[1024 * 1024 * 100];
|
|
||||||
|
|
||||||
for( int i=0; i< testFile.Length; i++ )
|
|
||||||
{
|
|
||||||
testFile[i] = (byte) i;
|
|
||||||
}
|
|
||||||
|
|
||||||
var written = SteamRemoteStorage.FileWrite( "testfile", testFile );
|
|
||||||
|
|
||||||
Assert.IsTrue( written );
|
|
||||||
Assert.IsTrue( SteamRemoteStorage.FileExists( "testfile" ) );
|
|
||||||
Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), testFile.Length );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void FileRead()
|
|
||||||
{
|
|
||||||
FileWrite();
|
|
||||||
|
|
||||||
var data = SteamRemoteStorage.FileRead( "testfile" );
|
|
||||||
|
|
||||||
Assert.IsNotNull( data );
|
|
||||||
|
|
||||||
for ( int i = 0; i < data.Length; i++ )
|
|
||||||
{
|
|
||||||
Assert.AreEqual( data[i], (byte)i );
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), data.Length );
|
|
||||||
Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), 1024 * 1024 * 100 );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Files()
|
|
||||||
{
|
|
||||||
foreach ( var file in SteamRemoteStorage.Files )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{file} ({SteamRemoteStorage.FileSize(file)} {SteamRemoteStorage.FileTime( file )})" );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
53
Facepunch.Steamworks.Test/Server/Inventory.cs
Normal file
53
Facepunch.Steamworks.Test/Server/Inventory.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
public partial class Server
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void InventoryDeserialize()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
|
||||||
|
Assert.IsNull( client.Inventory.SerializedItems );
|
||||||
|
|
||||||
|
client.Inventory.Refresh();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Block until we have the items
|
||||||
|
//
|
||||||
|
while ( client.Inventory.SerializedItems == null )
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsNotNull( client.Inventory.SerializedItems );
|
||||||
|
Assert.IsTrue( client.Inventory.SerializedItems.Length > 4 );
|
||||||
|
|
||||||
|
using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30002, true, "VersionString" ) )
|
||||||
|
{
|
||||||
|
server.LogOnAnonymous();
|
||||||
|
Assert.IsTrue( server.IsValid );
|
||||||
|
|
||||||
|
var result = server.Inventory.Deserialize( client.Inventory.SerializedItems );
|
||||||
|
|
||||||
|
Assert.IsTrue( result.Block() );
|
||||||
|
Assert.IsNotNull( result.Items );
|
||||||
|
|
||||||
|
foreach ( var item in result.Items )
|
||||||
|
{
|
||||||
|
Console.WriteLine( "Item: {0} ({1})", item.Id, item.DefinitionId );
|
||||||
|
Console.WriteLine( "Item: {0} ({1})", item.Id, item.DefinitionId );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
115
Facepunch.Steamworks.Test/Server/Server.cs
Normal file
115
Facepunch.Steamworks.Test/Server/Server.cs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||||
|
[DeploymentItem( "steam_appid.txt" )]
|
||||||
|
[DeploymentItem( "tier0_s.dll" )]
|
||||||
|
[DeploymentItem( "vstdlib_s.dll" )]
|
||||||
|
[DeploymentItem( "steamclient.dll" )]
|
||||||
|
[TestClass]
|
||||||
|
public partial class Server
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
using ( var server = new Facepunch.Steamworks.Server( 252490, 30001, 30002, 30003, false, "VersionString" ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( server.IsValid );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AuthCallback()
|
||||||
|
{
|
||||||
|
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( client.IsValid );
|
||||||
|
var ticket = client.Auth.GetAuthSessionTicket();
|
||||||
|
var ticketBinary = ticket.Data;
|
||||||
|
|
||||||
|
using ( var server = new Facepunch.Steamworks.Server( 252490, 30001, 30002, 30003, true, "VersionString" ) )
|
||||||
|
{
|
||||||
|
server.LogOnAnonymous();
|
||||||
|
|
||||||
|
Assert.IsTrue( server.IsValid );
|
||||||
|
|
||||||
|
var auth = server.Auth;
|
||||||
|
|
||||||
|
var Authed = false;
|
||||||
|
|
||||||
|
server.Auth.OnAuthChange = ( steamid, ownerid, status ) =>
|
||||||
|
{
|
||||||
|
Authed = status == ServerAuth.Status.OK;
|
||||||
|
|
||||||
|
Assert.AreEqual( steamid, client.SteamId );
|
||||||
|
Assert.AreEqual( steamid, ownerid );
|
||||||
|
|
||||||
|
Console.WriteLine( "steamid: {0}", steamid );
|
||||||
|
Console.WriteLine( "ownerid: {0}", ownerid );
|
||||||
|
Console.WriteLine( "status: {0}", status );
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( int i = 0; i < 16; i++ )
|
||||||
|
{
|
||||||
|
System.Threading.Thread.Sleep( 10 );
|
||||||
|
GC.Collect();
|
||||||
|
server.Update();
|
||||||
|
GC.Collect();
|
||||||
|
client.Update();
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
GC.Collect();
|
||||||
|
if ( !server.Auth.StartSession( ticketBinary, client.SteamId ) )
|
||||||
|
{
|
||||||
|
Assert.Fail( "Start Session returned false" );
|
||||||
|
}
|
||||||
|
GC.Collect();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Server should receive a ServerAuth.Status.OK
|
||||||
|
// message via the OnAuthChange callback
|
||||||
|
//
|
||||||
|
|
||||||
|
for ( int i = 0; i< 100; i++ )
|
||||||
|
{
|
||||||
|
GC.Collect();
|
||||||
|
System.Threading.Thread.Sleep( 100 );
|
||||||
|
GC.Collect();
|
||||||
|
server.Update();
|
||||||
|
client.Update();
|
||||||
|
|
||||||
|
if ( Authed )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue( Authed );
|
||||||
|
|
||||||
|
//
|
||||||
|
// Client cancels ticket
|
||||||
|
//
|
||||||
|
ticket.Cancel();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Server should receive a ticket cancelled message
|
||||||
|
//
|
||||||
|
|
||||||
|
for ( int i = 0; i < 100; i++ )
|
||||||
|
{
|
||||||
|
System.Threading.Thread.Sleep( 100 );
|
||||||
|
server.Update();
|
||||||
|
client.Update();
|
||||||
|
|
||||||
|
if ( !Authed )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue( !Authed );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
Facepunch.Steamworks.Test/Server/Stats.cs
Normal file
34
Facepunch.Steamworks.Test/Server/Stats.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
public partial class Server
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void StatsGet()
|
||||||
|
{
|
||||||
|
using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30002, true, "VersionString" ) )
|
||||||
|
{
|
||||||
|
Assert.IsTrue( server.IsValid );
|
||||||
|
server.LogOnAnonymous();
|
||||||
|
|
||||||
|
ulong MySteamId = 76561197960279927;
|
||||||
|
|
||||||
|
server.Stats.Refresh( MySteamId );
|
||||||
|
|
||||||
|
// TODO - Callback on complete
|
||||||
|
|
||||||
|
Thread.Sleep( 2000 );
|
||||||
|
|
||||||
|
var deaths = server.Stats.GetInt( MySteamId, "deaths", -1 );
|
||||||
|
|
||||||
|
Console.WriteLine( "Deaths: {0}", deaths );
|
||||||
|
Assert.IsTrue( deaths > 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,251 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public partial class ServerListTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void IpAddressConversions()
|
|
||||||
{
|
|
||||||
var ipstr = "185.38.150.40";
|
|
||||||
var ip = IPAddress.Parse( ipstr );
|
|
||||||
|
|
||||||
var ip_int = Utility.IpToInt32( ip );
|
|
||||||
|
|
||||||
var ip_back = Utility.Int32ToIp( ip_int );
|
|
||||||
|
|
||||||
Console.WriteLine( "ipstr: " + ipstr );
|
|
||||||
Console.WriteLine( "ip: " + ip );
|
|
||||||
Console.WriteLine( "ip int: " + ip_int );
|
|
||||||
Console.WriteLine( "ip_back: " + ip_back );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ServerListInternetInterupted()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.Internet() )
|
|
||||||
{
|
|
||||||
var task = list.RunQueryAsync();
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Querying.." );
|
|
||||||
|
|
||||||
list.Cancel();
|
|
||||||
|
|
||||||
foreach ( var s in list.Responsive )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{s.Address} {s.Name}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
Console.WriteLine( $"task.IsCompleted {task.IsCompleted}" );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ServerListInternet()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.Internet() )
|
|
||||||
{
|
|
||||||
var success = await list.RunQueryAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"success {success}" );
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to reproduce steam serverlist stopping querying after ~10s around august 2023
|
|
||||||
[TestMethod]
|
|
||||||
public async Task RustServerListTest()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.Internet() )
|
|
||||||
{
|
|
||||||
list.AddFilter( "secure", "1" );
|
|
||||||
list.AddFilter( "and", "1" );
|
|
||||||
list.AddFilter( "gametype", "v2405" );
|
|
||||||
list.AddFilter( "appid", "252490" );
|
|
||||||
list.AddFilter( "gamedir", "rust" );
|
|
||||||
list.AddFilter( "empty", "1" );
|
|
||||||
|
|
||||||
var success = await list.RunQueryAsync( 90 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"success {success}" );
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task SourceQuery()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.Internet() )
|
|
||||||
{
|
|
||||||
var task = list.RunQueryAsync();
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
list.Cancel();
|
|
||||||
|
|
||||||
foreach ( var s in list.Responsive.Take( 10 ).ToArray() )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{s.Name} [{s.Address}]" );
|
|
||||||
|
|
||||||
var rules = await s.QueryRulesAsync();
|
|
||||||
Assert.IsNotNull( rules );
|
|
||||||
|
|
||||||
foreach ( var rule in rules )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" {rule.Key} = {rule.Value}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ServerListLan()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.LocalNetwork() )
|
|
||||||
{
|
|
||||||
var success = await list.RunQueryAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"success {success}" );
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ServerListFavourites()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.Favourites() )
|
|
||||||
{
|
|
||||||
var success = await list.RunQueryAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"success {success}" );
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ServerListFriends()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.Friends() )
|
|
||||||
{
|
|
||||||
var success = await list.RunQueryAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"success {success}" );
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ServerListHistory()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.History() )
|
|
||||||
{
|
|
||||||
var success = await list.RunQueryAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"success {success}" );
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task FilterByMap()
|
|
||||||
{
|
|
||||||
using ( var list = new ServerList.Internet() )
|
|
||||||
{
|
|
||||||
list.AddFilter( "map", "de_dust" );
|
|
||||||
|
|
||||||
var success = await list.RunQueryAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"success {success}" );
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
|
|
||||||
foreach ( var server in list.Responsive )
|
|
||||||
{
|
|
||||||
Assert.AreEqual( server.Map.ToLower(), "de_dust" );
|
|
||||||
|
|
||||||
Console.WriteLine( $"[{server.Map}] - {server.Name}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ServerListIps()
|
|
||||||
{
|
|
||||||
var ips = new string[]
|
|
||||||
{
|
|
||||||
"31.186.251.76",
|
|
||||||
"31.186.251.76",
|
|
||||||
"31.186.251.76",
|
|
||||||
"31.186.251.76",
|
|
||||||
"31.186.251.76",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"139.99.144.70",
|
|
||||||
"139.99.144.70",
|
|
||||||
"139.99.144.70",
|
|
||||||
"139.99.144.70",
|
|
||||||
"139.99.144.70",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"74.91.119.142",
|
|
||||||
"95.172.92.176",
|
|
||||||
"95.172.92.176",
|
|
||||||
"95.172.92.176",
|
|
||||||
"95.172.92.176",
|
|
||||||
"95.172.92.176",
|
|
||||||
"164.132.205.154",
|
|
||||||
"164.132.205.154",
|
|
||||||
"164.132.205.154",
|
|
||||||
"164.132.205.154",
|
|
||||||
"164.132.205.154",
|
|
||||||
};
|
|
||||||
|
|
||||||
using ( var list = new ServerList.IpList( ips ) )
|
|
||||||
{
|
|
||||||
var success = await list.RunQueryAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"success {success}" );
|
|
||||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
|
||||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
|
||||||
|
|
||||||
Assert.AreNotEqual( list.Responsive.Count, 0 );
|
|
||||||
|
|
||||||
foreach ( var server in list.Responsive )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[{server.Address}:{server.ConnectionPort}] - {server.Name}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class SteamMatchmakingTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public async Task LobbyList()
|
|
||||||
{
|
|
||||||
await CreateLobby();
|
|
||||||
|
|
||||||
var list = await SteamMatchmaking.LobbyList
|
|
||||||
.RequestAsync();
|
|
||||||
|
|
||||||
if ( list == null )
|
|
||||||
{
|
|
||||||
Console.WriteLine( "No Lobbies Found!" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ( var lobby in list )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[{lobby.Id}] owned by {lobby.Owner} ({lobby.MemberCount}/{lobby.MaxMembers})" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task LobbyListWithAtLeastOne()
|
|
||||||
{
|
|
||||||
await CreateLobby();
|
|
||||||
await LobbyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CreateLobby()
|
|
||||||
{
|
|
||||||
var lobbyr = await SteamMatchmaking.CreateLobbyAsync( 32 );
|
|
||||||
if ( !lobbyr.HasValue )
|
|
||||||
{
|
|
||||||
Assert.Fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
var lobby = lobbyr.Value;
|
|
||||||
lobby.SetPublic();
|
|
||||||
lobby.SetData( "gametype", "sausage" );
|
|
||||||
lobby.SetData( "dicks", "unlicked" );
|
|
||||||
|
|
||||||
Console.WriteLine( $"lobby: {lobby.Id}" );
|
|
||||||
|
|
||||||
foreach ( var entry in lobby.Data )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" - {entry.Key} {entry.Value}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( $"members: {lobby.MemberCount}/{lobby.MaxMembers}" );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Owner: {lobby.Owner}" );
|
|
||||||
Console.WriteLine( $"Owner Is Local Player: {lobby.Owner.IsMe}" );
|
|
||||||
|
|
||||||
lobby.SendChatString( "Hello I Love Lobbies" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task LobbyChat()
|
|
||||||
{
|
|
||||||
SteamMatchmaking.OnChatMessage += ( lbby, member, message ) =>
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"[{lbby}] {member}: {message}" );
|
|
||||||
};
|
|
||||||
|
|
||||||
var lobbyr = await SteamMatchmaking.CreateLobbyAsync( 10 );
|
|
||||||
if ( !lobbyr.HasValue )
|
|
||||||
Assert.Fail();
|
|
||||||
|
|
||||||
var lobby = lobbyr.Value;
|
|
||||||
lobby.SetPublic();
|
|
||||||
lobby.SetData( "name", "Dave's Chat Room" );
|
|
||||||
Console.WriteLine( $"lobby: {lobby.Id}" );
|
|
||||||
|
|
||||||
lobby.SendChatString( "Hello Friends, It's me - your big fat daddy" );
|
|
||||||
|
|
||||||
await Task.Delay( 50 );
|
|
||||||
|
|
||||||
lobby.SendChatString( "What? No love for daddy?" );
|
|
||||||
|
|
||||||
await Task.Delay( 500 );
|
|
||||||
|
|
||||||
lobby.SendChatString( "Okay I will LEAVE" );
|
|
||||||
lobby.SendChatString( "BYE FOREVER" );
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
lobby.Leave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class SteamNetworkingTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public async Task SendP2PPacket()
|
|
||||||
{
|
|
||||||
var sent = SteamNetworking.SendP2PPacket( SteamClient.SteamId, new byte[] { 1, 2, 3 } );
|
|
||||||
Assert.IsTrue( sent );
|
|
||||||
|
|
||||||
while ( !SteamNetworking.IsP2PPacketAvailable() )
|
|
||||||
{
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
}
|
|
||||||
|
|
||||||
var packet = SteamNetworking.ReadP2PPacket();
|
|
||||||
|
|
||||||
Assert.IsTrue( packet.HasValue );
|
|
||||||
|
|
||||||
Assert.AreEqual( packet.Value.SteamId, SteamClient.SteamId );
|
|
||||||
Assert.AreEqual( packet.Value.Data[1], 2 );
|
|
||||||
Assert.AreEqual( packet.Value.Data.Length, 3 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,183 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class UgcEditor
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CreateFile()
|
|
||||||
{
|
|
||||||
var result = await Ugc.Editor.NewCommunityFile
|
|
||||||
.WithTitle( "Unit Test Created Item" )
|
|
||||||
.WithDescription( "This item was created by Facepunch Steamworks unit tests.\n\n" +
|
|
||||||
"It should have technically been deleted so you should never get to " +
|
|
||||||
"read this unless something terrible has happened." )
|
|
||||||
.WithTag( "Arsehole" )
|
|
||||||
.WithTag( "Spiteful" )
|
|
||||||
.WithTag( "Fat-Head" )
|
|
||||||
.SubmitAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( result.Success );
|
|
||||||
Assert.AreNotEqual( result.FileId.Value, 0 );
|
|
||||||
|
|
||||||
var deleted = await SteamUGC.DeleteFileAsync( result.FileId );
|
|
||||||
Assert.IsTrue( deleted );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CreateChineseFile()
|
|
||||||
{
|
|
||||||
string fileName = "这是我的项目";
|
|
||||||
string description = "此项目由Facepunch Steamworks单元测试创建";
|
|
||||||
|
|
||||||
var result = await Ugc.Editor.NewCommunityFile
|
|
||||||
.WithTitle( fileName )
|
|
||||||
.WithDescription( description )
|
|
||||||
.WithTag( "Arsehole" )
|
|
||||||
.WithTag( "Spiteful" )
|
|
||||||
.WithTag( "Fat-Head" )
|
|
||||||
.SubmitAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $"Title: {fileName}" );
|
|
||||||
Console.WriteLine( $"Description: {description}" );
|
|
||||||
|
|
||||||
Assert.IsTrue( result.Success );
|
|
||||||
Assert.AreNotEqual( result.FileId.Value, 0 );
|
|
||||||
|
|
||||||
var file = await Steamworks.SteamUGC.QueryFileAsync( result.FileId );
|
|
||||||
|
|
||||||
Console.WriteLine( $"FileId: {result.FileId}" );
|
|
||||||
Console.WriteLine( $"Title: {file.Value.Title}" );
|
|
||||||
Console.WriteLine( $"Description: {file.Value.Description}" );
|
|
||||||
|
|
||||||
Assert.AreEqual( file.Value.Title, fileName );
|
|
||||||
Assert.AreEqual( file.Value.Description, description );
|
|
||||||
|
|
||||||
var deleted = await SteamUGC.DeleteFileAsync( result.FileId );
|
|
||||||
Assert.IsTrue( deleted );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProgressBar : IProgress<float>
|
|
||||||
{
|
|
||||||
float Value = 0;
|
|
||||||
|
|
||||||
public void Report( float value )
|
|
||||||
{
|
|
||||||
if ( Value >= value ) return;
|
|
||||||
|
|
||||||
Value = value;
|
|
||||||
|
|
||||||
Console.WriteLine( value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task UploadBigishFile()
|
|
||||||
{
|
|
||||||
var created = Ugc.Editor.NewCommunityFile
|
|
||||||
.WithTitle( "Unit Test Upload Item" )
|
|
||||||
.WithDescription( "This item was created by Facepunch Steamworks unit tests.\n\n" +
|
|
||||||
"It should have technically been deleted so you should never get to " +
|
|
||||||
"read this unless something terrible has happened." )
|
|
||||||
//.WithTag( "Apple" )
|
|
||||||
//.WithTag( "Banana" )
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
// Make a folder
|
|
||||||
var testFolder = new System.IO.DirectoryInfo( "WorkshopUpload" );
|
|
||||||
if ( !testFolder.Exists ) testFolder.Create();
|
|
||||||
|
|
||||||
created = created.WithContent( testFolder.FullName );
|
|
||||||
|
|
||||||
// Upload a file of random bytes
|
|
||||||
var rand = new Random();
|
|
||||||
var testFile = new byte[1024 * 1024 * 32];
|
|
||||||
rand.NextBytes( testFile );
|
|
||||||
System.IO.File.WriteAllBytes( testFolder.FullName + "/testfile1.bin", testFile );
|
|
||||||
|
|
||||||
Console.WriteLine( testFolder.FullName );
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var done = await created.SubmitAsync( new ProgressBar() );
|
|
||||||
|
|
||||||
Assert.IsTrue( done.Success );
|
|
||||||
Console.WriteLine( "item.Id: {0}", done.FileId );
|
|
||||||
|
|
||||||
var deleted = await SteamUGC.DeleteFileAsync( done.FileId );
|
|
||||||
Assert.IsTrue( deleted );
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
System.IO.File.Delete( testFolder.FullName + "/testfile.bin" );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CreateAndThenEditFile()
|
|
||||||
{
|
|
||||||
PublishedFileId fileid;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Make a file
|
|
||||||
//
|
|
||||||
{
|
|
||||||
var result = await Ugc.Editor.NewCommunityFile
|
|
||||||
.WithTitle( "Unedited File" )
|
|
||||||
.SubmitAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( result.Success );
|
|
||||||
Assert.AreNotEqual( result.FileId.Value, 0 );
|
|
||||||
|
|
||||||
fileid = result.FileId;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Edit it
|
|
||||||
//
|
|
||||||
{
|
|
||||||
var editor = new Ugc.Editor( fileid );
|
|
||||||
editor = editor.WithTitle( "An Edited File" );
|
|
||||||
var result = await editor.SubmitAsync();
|
|
||||||
|
|
||||||
Assert.IsTrue( result.Success );
|
|
||||||
Assert.AreEqual( result.FileId, fileid );
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay( 1000 );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Make sure the edited file matches
|
|
||||||
//
|
|
||||||
{
|
|
||||||
var details = await SteamUGC.QueryFileAsync( fileid ) ?? throw new Exception( "Somethign went wrong" );
|
|
||||||
Assert.AreEqual( details.Id, fileid );
|
|
||||||
Assert.AreEqual( details.Title, "An Edited File" );
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Clean up
|
|
||||||
//
|
|
||||||
var deleted = await SteamUGC.DeleteFileAsync( fileid );
|
|
||||||
Assert.IsTrue( deleted );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class UgcQueryTests
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public async Task QueryAll()
|
|
||||||
{
|
|
||||||
var q = Ugc.Query.All;
|
|
||||||
|
|
||||||
var result = await q.GetPageAsync( 1 );
|
|
||||||
Assert.IsNotNull( result );
|
|
||||||
|
|
||||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
|
||||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task QueryWithTags()
|
|
||||||
{
|
|
||||||
var q = Ugc.Query.All
|
|
||||||
.WithTag( "Version3" )
|
|
||||||
.WithTag( "Hunting Bow" )
|
|
||||||
.MatchAllTags();
|
|
||||||
|
|
||||||
var result = await q.GetPageAsync( 1 );
|
|
||||||
Assert.IsNotNull( result );
|
|
||||||
Assert.IsTrue( result?.ResultCount > 0 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
|
||||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
|
||||||
|
|
||||||
foreach ( var entry in result.Value.Entries )
|
|
||||||
{
|
|
||||||
Assert.IsTrue( entry.HasTag( "Version3" ), "Has Tag Version3" );
|
|
||||||
Assert.IsTrue( entry.HasTag( "Hunting Bow" ), "Has Tag HuntingBow" );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task QueryAllFromFriends()
|
|
||||||
{
|
|
||||||
var q = Ugc.Query.All
|
|
||||||
.CreatedByFriends();
|
|
||||||
|
|
||||||
var result = await q.GetPageAsync( 1 );
|
|
||||||
Assert.IsNotNull( result );
|
|
||||||
|
|
||||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
|
||||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
|
||||||
|
|
||||||
foreach ( var entry in result.Value.Entries )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" {entry.Title}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task QueryUserOwn()
|
|
||||||
{
|
|
||||||
var q = Ugc.Query.All
|
|
||||||
.WhereUserPublished();
|
|
||||||
|
|
||||||
var result = await q.GetPageAsync( 1 );
|
|
||||||
Assert.IsNotNull( result );
|
|
||||||
|
|
||||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
|
||||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
|
||||||
|
|
||||||
foreach ( var entry in result.Value.Entries )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" {entry.Title}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task QueryGarry()
|
|
||||||
{
|
|
||||||
var q = Ugc.Query.All
|
|
||||||
.WhereUserPublished( 76561197960279927 );
|
|
||||||
|
|
||||||
var result = await q.GetPageAsync( 1 );
|
|
||||||
Assert.IsNotNull( result );
|
|
||||||
Assert.IsTrue( result?.ResultCount > 0 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
|
||||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
|
||||||
|
|
||||||
foreach ( var entry in result.Value.Entries )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $" {entry.Title}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task QuerySpecificFile()
|
|
||||||
{
|
|
||||||
var item = await SteamUGC.QueryFileAsync( 1734427277 );
|
|
||||||
|
|
||||||
Assert.IsTrue( item.HasValue );
|
|
||||||
Assert.IsNotNull( item.Value.Title );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Title: {item?.Title}" );
|
|
||||||
Console.WriteLine( $"Desc: {item?.Description}" );
|
|
||||||
Console.WriteLine( $"Tags: {string.Join( ",", item?.Tags )}" );
|
|
||||||
Console.WriteLine( $"Author: {item?.Owner.Name} [{item?.Owner.Id}]" );
|
|
||||||
Console.WriteLine( $"PreviewImageUrl: {item?.PreviewImageUrl}" );
|
|
||||||
Console.WriteLine( $"NumComments: {item?.NumComments}" );
|
|
||||||
Console.WriteLine( $"Url: {item?.Url}" );
|
|
||||||
Console.WriteLine( $"Directory: {item?.Directory}" );
|
|
||||||
Console.WriteLine( $"IsInstalled: {item?.IsInstalled}" );
|
|
||||||
Console.WriteLine( $"IsAcceptedForUse: {item?.IsAcceptedForUse}" );
|
|
||||||
Console.WriteLine( $"IsPublic: {item?.IsPublic}" );
|
|
||||||
Console.WriteLine( $"Created: {item?.Created}" );
|
|
||||||
Console.WriteLine( $"Updated: {item?.Updated}" );
|
|
||||||
Console.WriteLine( $"Score: {item?.Score}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class UgcTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void Download()
|
|
||||||
{
|
|
||||||
SteamUGC.Download( 1717844711 );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetInformation()
|
|
||||||
{
|
|
||||||
var itemInfo = await Ugc.Item.GetAsync( 1720164672 );
|
|
||||||
|
|
||||||
Assert.IsTrue( itemInfo.HasValue );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Title: {itemInfo?.Title}" );
|
|
||||||
Console.WriteLine( $"IsInstalled: {itemInfo?.IsInstalled}" );
|
|
||||||
Console.WriteLine( $"IsDownloading: {itemInfo?.IsDownloading}" );
|
|
||||||
Console.WriteLine( $"IsDownloadPending: {itemInfo?.IsDownloadPending}" );
|
|
||||||
Console.WriteLine( $"IsSubscribed: {itemInfo?.IsSubscribed}" );
|
|
||||||
Console.WriteLine( $"NeedsUpdate: {itemInfo?.NeedsUpdate}" );
|
|
||||||
Console.WriteLine( $"Description: {itemInfo?.Description}" );
|
|
||||||
Console.WriteLine( $"Owner: {itemInfo?.Owner}" );
|
|
||||||
Console.WriteLine( $"Score: {itemInfo?.Score}" );
|
|
||||||
Console.WriteLine( $"PreviewImageUrl: {itemInfo?.PreviewImageUrl}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,222 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class UserStatsTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public async Task AchievementList()
|
|
||||||
{
|
|
||||||
foreach ( var a in SteamUserStats.Achievements )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{a.Identifier}" );
|
|
||||||
Console.WriteLine( $" a.State: {a.State}" );
|
|
||||||
Console.WriteLine( $" a.UnlockTime: {a.UnlockTime}" );
|
|
||||||
Console.WriteLine( $" a.Name: {a.Name}" );
|
|
||||||
Console.WriteLine( $" a.Description: {a.Description}" );
|
|
||||||
Console.WriteLine( $" a.GlobalUnlocked: {a.GlobalUnlocked}" );
|
|
||||||
|
|
||||||
var icon = await a.GetIconAsync();
|
|
||||||
|
|
||||||
Console.WriteLine( $" a.Icon: {icon}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task PlayerCountAsync()
|
|
||||||
{
|
|
||||||
var players = await SteamUserStats.PlayerCountAsync();
|
|
||||||
Assert.AreNotEqual( players, -1 );
|
|
||||||
Console.WriteLine( $"players: {players}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task StoreStats()
|
|
||||||
{
|
|
||||||
var result = Result.NotSettled;
|
|
||||||
|
|
||||||
SteamUserStats.OnUserStatsStored += ( r ) =>
|
|
||||||
{
|
|
||||||
result = r;
|
|
||||||
};
|
|
||||||
|
|
||||||
SteamUserStats.StoreStats();
|
|
||||||
|
|
||||||
while ( result == Result.NotSettled )
|
|
||||||
{
|
|
||||||
await Task.Delay( 10 );
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.AreEqual( result, Result.OK );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CreateLeaderboard()
|
|
||||||
{
|
|
||||||
var leaderboard = await SteamUserStats.FindOrCreateLeaderboardAsync( "Testleaderboard", Data.LeaderboardSort.Ascending, Data.LeaderboardDisplay.Numeric );
|
|
||||||
|
|
||||||
Assert.IsTrue( leaderboard.HasValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task FindLeaderboard()
|
|
||||||
{
|
|
||||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
|
||||||
Assert.IsTrue( leaderboard.HasValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task SubmitScore()
|
|
||||||
{
|
|
||||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
|
||||||
Assert.IsTrue( leaderboard.HasValue );
|
|
||||||
|
|
||||||
var result = await leaderboard.Value.SubmitScoreAsync( 576 );
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
|
|
||||||
Console.WriteLine( $"result.Changed: {result?.Changed}" );
|
|
||||||
Console.WriteLine( $"result.OldGlobalRank: {result?.OldGlobalRank}" );
|
|
||||||
Console.WriteLine( $"result.NewGlobalRank: {result?.NewGlobalRank}" );
|
|
||||||
Console.WriteLine( $"result.RankChange: {result?.RankChange}" );
|
|
||||||
Console.WriteLine( $"result.Score: {result?.Score}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ReplaceScore()
|
|
||||||
{
|
|
||||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
|
||||||
Assert.IsTrue( leaderboard.HasValue );
|
|
||||||
|
|
||||||
var result = await leaderboard.Value.ReplaceScore( 576 );
|
|
||||||
Assert.IsTrue( result.HasValue );
|
|
||||||
|
|
||||||
Console.WriteLine( $"result.Changed: {result?.Changed}" );
|
|
||||||
Console.WriteLine( $"result.OldGlobalRank: {result?.OldGlobalRank}" );
|
|
||||||
Console.WriteLine( $"result.NewGlobalRank: {result?.NewGlobalRank}" );
|
|
||||||
Console.WriteLine( $"result.RankChange: {result?.RankChange}" );
|
|
||||||
Console.WriteLine( $"result.Score: {result?.Score}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetScoresFromFriends()
|
|
||||||
{
|
|
||||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
|
||||||
|
|
||||||
var friendScores = await leaderboard.Value.GetScoresFromFriendsAsync();
|
|
||||||
|
|
||||||
foreach ( var e in friendScores )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetScoresAroundUserAsync()
|
|
||||||
{
|
|
||||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
|
||||||
Assert.IsTrue( leaderboard.HasValue );
|
|
||||||
|
|
||||||
for ( int i = 1; i < 10; i++ )
|
|
||||||
{
|
|
||||||
// Get entries around user
|
|
||||||
var relativeScores = await leaderboard.Value.GetScoresAroundUserAsync( -i, i );
|
|
||||||
Assert.IsNotNull( relativeScores );
|
|
||||||
|
|
||||||
Console.WriteLine( $"" );
|
|
||||||
Console.WriteLine( $"Relative Scores:" );
|
|
||||||
foreach ( var e in relativeScores )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetScoresAsync()
|
|
||||||
{
|
|
||||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
|
||||||
Assert.IsTrue( leaderboard.HasValue );
|
|
||||||
|
|
||||||
// Get top 20 global scores
|
|
||||||
var globalsScores = await leaderboard.Value.GetScoresAsync( 20 );
|
|
||||||
Assert.IsNotNull( globalsScores );
|
|
||||||
|
|
||||||
Console.WriteLine( $"" );
|
|
||||||
Console.WriteLine( $"Global Scores:" );
|
|
||||||
foreach ( var e in globalsScores )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GetStatInt()
|
|
||||||
{
|
|
||||||
var deaths = new Stat( "deaths" );
|
|
||||||
Console.WriteLine( $"{deaths.Name} {deaths.GetInt()} times" );
|
|
||||||
Console.WriteLine( $"{deaths.Name} {deaths.GetFloat()} times" );
|
|
||||||
|
|
||||||
Assert.AreNotEqual( 0, deaths.GetInt() );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetFriendStats()
|
|
||||||
{
|
|
||||||
var friend = new Friend( 76561197965732579 ); // Hezzy
|
|
||||||
|
|
||||||
// Download stats
|
|
||||||
var status = await friend.RequestUserStatsAsync();
|
|
||||||
Assert.AreNotEqual( false, status );
|
|
||||||
|
|
||||||
var deaths = friend.GetStatInt( "deaths" );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Hezzy has died {deaths} times" );
|
|
||||||
|
|
||||||
Assert.AreNotEqual( 0, deaths );
|
|
||||||
|
|
||||||
var unlocked = friend.GetAchievement( "COLLECT_100_WOOD" );
|
|
||||||
Assert.AreNotEqual( false, unlocked );
|
|
||||||
|
|
||||||
var when = friend.GetAchievementUnlockTime( "COLLECT_100_WOOD" );
|
|
||||||
Assert.AreNotEqual( when, DateTime.MinValue );
|
|
||||||
|
|
||||||
Console.WriteLine( $"Hezzy unlocked COLLECT_100_WOOD {when}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetStatGlobalInt()
|
|
||||||
{
|
|
||||||
var deaths = new Stat( "deaths" );
|
|
||||||
await deaths.GetGlobalIntDaysAsync( 5 );
|
|
||||||
|
|
||||||
var totalStartups = deaths.GetGlobalInt();
|
|
||||||
Assert.AreNotEqual( 0, totalStartups );
|
|
||||||
Console.WriteLine( $"Rust has had {totalStartups} deaths" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetStatGlobalHistoryInt()
|
|
||||||
{
|
|
||||||
var deaths = new Stat( "deaths" );
|
|
||||||
|
|
||||||
var history = await deaths.GetGlobalIntDaysAsync( 10 );
|
|
||||||
Assert.AreNotEqual( 0, history.Length );
|
|
||||||
|
|
||||||
for ( int i=0; i< history.Length; i++ )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"{i} : {history[i]}" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,191 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class UserTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void GetVoice()
|
|
||||||
{
|
|
||||||
using ( var stream = new MemoryStream() )
|
|
||||||
{
|
|
||||||
int compressed = 0;
|
|
||||||
|
|
||||||
SteamUser.VoiceRecord = true;
|
|
||||||
|
|
||||||
var sw = Stopwatch.StartNew();
|
|
||||||
|
|
||||||
while ( sw.Elapsed.TotalSeconds < 3 )
|
|
||||||
{
|
|
||||||
System.Threading.Thread.Sleep( 10 );
|
|
||||||
compressed += SteamUser.ReadVoiceData( stream );
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.AreEqual( compressed, stream.Length );
|
|
||||||
Console.WriteLine( $"compressed: {compressed}", compressed );
|
|
||||||
Console.WriteLine( $"stream.Length: {stream.Length}", stream.Length );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[TestMethod]
|
|
||||||
public void OptimalSampleRate()
|
|
||||||
{
|
|
||||||
var rate = SteamUser.OptimalSampleRate;
|
|
||||||
Assert.AreNotEqual( rate, 0 );
|
|
||||||
Console.WriteLine( $"User.OptimalSampleRate: {SteamUser.OptimalSampleRate}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsLoggedOn()
|
|
||||||
{
|
|
||||||
Assert.AreNotEqual( false, SteamClient.IsLoggedOn );
|
|
||||||
Console.WriteLine( $"User.IsLoggedOn: {SteamClient.IsLoggedOn}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void SteamID()
|
|
||||||
{
|
|
||||||
Assert.AreNotEqual( 0, SteamClient.SteamId.Value );
|
|
||||||
Console.WriteLine( $"User.SteamID: {SteamClient.SteamId.Value}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void AuthSession()
|
|
||||||
{
|
|
||||||
var ticket = SteamUser.GetAuthSessionTicket( SteamClient.SteamId );
|
|
||||||
|
|
||||||
Assert.AreNotEqual( 0, ticket.Handle );
|
|
||||||
Assert.AreNotEqual( 0, ticket.Data.Length );
|
|
||||||
Console.WriteLine( $"ticket.Handle: {ticket.Handle}" );
|
|
||||||
Console.WriteLine( $"ticket.Data: { string.Join( "", ticket.Data.Select( x => x.ToString( "x" ) ) ) }" );
|
|
||||||
|
|
||||||
var result = SteamUser.BeginAuthSession( ticket.Data, SteamClient.SteamId );
|
|
||||||
Console.WriteLine( $"result: { result }" );
|
|
||||||
Assert.AreEqual( result, BeginAuthResult.OK );
|
|
||||||
|
|
||||||
SteamUser.EndAuthSession( SteamClient.SteamId );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task AuthSessionAsync()
|
|
||||||
{
|
|
||||||
var ticket = await SteamUser.GetAuthSessionTicketAsync( SteamClient.SteamId, 5.0 );
|
|
||||||
|
|
||||||
Assert.AreNotEqual( 0, ticket.Handle );
|
|
||||||
Assert.AreNotEqual( 0, ticket.Data.Length );
|
|
||||||
Console.WriteLine( $"ticket.Handle: {ticket.Handle}" );
|
|
||||||
Console.WriteLine( $"ticket.Data: { string.Join( "", ticket.Data.Select( x => x.ToString( "x" ) ) ) }" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task AuthTicketForWebApiAsync()
|
|
||||||
{
|
|
||||||
var ticket = await SteamUser.GetAuthTicketForWebApiAsync( "Test" );
|
|
||||||
|
|
||||||
Assert.AreNotEqual( 0, ticket.Handle );
|
|
||||||
Assert.AreNotEqual( 0, ticket.Data.Length );
|
|
||||||
Console.WriteLine( $"ticket.Handle: {ticket.Handle}" );
|
|
||||||
Console.WriteLine( $"ticket.Data: { string.Join( "", ticket.Data.Select( x => x.ToString( "x" ) ) ) }" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void SteamLevel()
|
|
||||||
{
|
|
||||||
Assert.AreNotEqual( 0, SteamUser.SteamLevel );
|
|
||||||
Console.WriteLine( $"User.SteamLevel: {SteamUser.SteamLevel}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Name()
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"SteamClient.Name: {SteamClient.Name}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task GetStoreAuthUrlAsync()
|
|
||||||
{
|
|
||||||
var rustskins = await SteamUser.GetStoreAuthUrlAsync( "https://store.steampowered.com/itemstore/252490/" );
|
|
||||||
|
|
||||||
Assert.IsNotNull( rustskins );
|
|
||||||
Console.WriteLine( $"rustskins: {rustskins}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsPhoneVerified()
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"User.IsPhoneVerified: {SteamUser.IsPhoneVerified}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsTwoFactorEnabled()
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"User.IsTwoFactorEnabled: {SteamUser.IsTwoFactorEnabled}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsPhoneIdentifying()
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"User.IsPhoneIdentifying: {SteamUser.IsPhoneIdentifying}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsPhoneRequiringVerification()
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"User.IsPhoneRequiringVerification: {SteamUser.IsPhoneRequiringVerification}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task RequestEncryptedAppTicketAsyncWithData()
|
|
||||||
{
|
|
||||||
for ( int i=0; i<10; i++ )
|
|
||||||
{
|
|
||||||
var data = await SteamUser.RequestEncryptedAppTicketAsync( new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 } );
|
|
||||||
|
|
||||||
if ( data == null )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"Attempt {i}: Returned null.. waiting 1 seconds" );
|
|
||||||
await Task.Delay( 10000 );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( $"data: {BitConverter.ToString( data )}" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.Fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task RequestEncryptedAppTicketAsync()
|
|
||||||
{
|
|
||||||
for ( int i = 0; i < 6; i++ )
|
|
||||||
{
|
|
||||||
var data = await SteamUser.RequestEncryptedAppTicketAsync();
|
|
||||||
|
|
||||||
if ( data == null )
|
|
||||||
{
|
|
||||||
Console.WriteLine( $"Attempt {i}: Returned null.. waiting 1 seconds" );
|
|
||||||
await Task.Delay( 10000 );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( $"data: {BitConverter.ToString( data )}" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.Fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
[TestClass]
|
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
|
||||||
[DeploymentItem( "steam_api.dll" )]
|
|
||||||
public class UtilsTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public void SecondsSinceAppActive()
|
|
||||||
{
|
|
||||||
var time = SteamUtils.SecondsSinceAppActive;
|
|
||||||
Console.WriteLine( $"{time}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void SecondsSinceComputerActive()
|
|
||||||
{
|
|
||||||
var time = SteamUtils.SecondsSinceComputerActive;
|
|
||||||
Console.WriteLine( $"{time}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void ConnectedUniverse()
|
|
||||||
{
|
|
||||||
var u = SteamUtils.ConnectedUniverse;
|
|
||||||
Console.WriteLine( $"{u}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void SteamServerTime()
|
|
||||||
{
|
|
||||||
var time = SteamUtils.SteamServerTime;
|
|
||||||
Console.WriteLine( $"{time}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IpCountry()
|
|
||||||
{
|
|
||||||
var cnt = SteamUtils.IpCountry;
|
|
||||||
Console.WriteLine( $"{cnt}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void UsingBatteryPower()
|
|
||||||
{
|
|
||||||
var cnt = SteamUtils.UsingBatteryPower;
|
|
||||||
Console.WriteLine( $"{cnt}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void CurrentBatteryPower()
|
|
||||||
{
|
|
||||||
var cnt = SteamUtils.CurrentBatteryPower;
|
|
||||||
Console.WriteLine( $"{cnt}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void AppId()
|
|
||||||
{
|
|
||||||
var cnt = SteamClient.AppId;
|
|
||||||
|
|
||||||
Assert.IsTrue( cnt.Value > 0 );
|
|
||||||
|
|
||||||
Console.WriteLine( $"{cnt.Value}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsOverlayEnabled()
|
|
||||||
{
|
|
||||||
var cnt = SteamUtils.IsOverlayEnabled;
|
|
||||||
Console.WriteLine( $"{cnt}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task CheckFileSignature()
|
|
||||||
{
|
|
||||||
var sig = await SteamUtils.CheckFileSignatureAsync( "hl2.exe" );
|
|
||||||
Console.WriteLine( $"{sig}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void SteamUILanguage()
|
|
||||||
{
|
|
||||||
var cnt = SteamUtils.SteamUILanguage;
|
|
||||||
Console.WriteLine( $"{cnt}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsSteamRunningInVR()
|
|
||||||
{
|
|
||||||
var cnt = SteamUtils.IsSteamRunningInVR;
|
|
||||||
Console.WriteLine( $"{cnt}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void IsSteamInBigPictureMode()
|
|
||||||
{
|
|
||||||
var cnt = SteamUtils.IsSteamInBigPictureMode;
|
|
||||||
Console.WriteLine( $"{cnt}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void VrHeadsetStreaming()
|
|
||||||
{
|
|
||||||
var cnt = SteamUtils.VrHeadsetStreaming;
|
|
||||||
Console.WriteLine( $"{cnt}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
BIN
Facepunch.Steamworks.Test/bin/Debug/FacepunchSteamworksApi.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/FacepunchSteamworksApi.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Debug/FacepunchSteamworksApi32.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/FacepunchSteamworksApi32.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Debug/FacepunchSteamworksApi64.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/FacepunchSteamworksApi64.dll
Normal file
Binary file not shown.
@ -1,74 +0,0 @@
|
|||||||
"In Game Actions"
|
|
||||||
{
|
|
||||||
"actions"
|
|
||||||
{
|
|
||||||
"InGameControls"
|
|
||||||
{
|
|
||||||
"title" "#Set_Ingame"
|
|
||||||
"StickPadGyro"
|
|
||||||
{
|
|
||||||
"Move"
|
|
||||||
{
|
|
||||||
"title" "#Action_Move"
|
|
||||||
"input_mode" "joystick_move"
|
|
||||||
}
|
|
||||||
"Camera"
|
|
||||||
{
|
|
||||||
"title" "#Action_Camera"
|
|
||||||
"input_mode" "absolute_mouse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"AnalogTrigger"
|
|
||||||
{
|
|
||||||
"Throttle" "#Action_Throttle"
|
|
||||||
}
|
|
||||||
"Button"
|
|
||||||
{
|
|
||||||
"fire" "#Action_Fire"
|
|
||||||
"Jump" "#Action_Jump"
|
|
||||||
"pause_menu" "#Action_Menu"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"MenuControls"
|
|
||||||
{
|
|
||||||
"title" "#Set_Menu"
|
|
||||||
"StickPadGyro"
|
|
||||||
{
|
|
||||||
}
|
|
||||||
"AnalogTrigger"
|
|
||||||
{
|
|
||||||
}
|
|
||||||
"Button"
|
|
||||||
{
|
|
||||||
"menu_up" "#Menu_Up"
|
|
||||||
"menu_down" "#Menu_Down"
|
|
||||||
"menu_left" "#Menu_Left"
|
|
||||||
"menu_right" "#Menu_Right"
|
|
||||||
"menu_select" "#Menu_Select"
|
|
||||||
"menu_cancel" "#Menu_Cancel"
|
|
||||||
"pause_menu" "#Action_ReturnToGame"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"localization"
|
|
||||||
{
|
|
||||||
"english"
|
|
||||||
{
|
|
||||||
"Set_Ingame" "In-Game Controls"
|
|
||||||
"Set_Menu" "Menu Controls"
|
|
||||||
"Action_Move" "Movement"
|
|
||||||
"Action_Camera" "Camera"
|
|
||||||
"Action_Throttle" "Throttle"
|
|
||||||
"Action_Fire" "Fire Weapon"
|
|
||||||
"Action_Jump" "Jump"
|
|
||||||
"Action_Menu" "Pause Menu"
|
|
||||||
"Action_ReturnToGame" "Return To Game"
|
|
||||||
"Menu_Up" "Up"
|
|
||||||
"Menu_Down" "Down"
|
|
||||||
"Menu_Left" "Left"
|
|
||||||
"Menu_Right" "Right"
|
|
||||||
"Menu_Select" "Select"
|
|
||||||
"Menu_Cancel" "Cancel"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
BIN
Facepunch.Steamworks.Test/bin/Debug/steam_api.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/steam_api.dll
Normal file
Binary file not shown.
1
Facepunch.Steamworks.Test/bin/Debug/steam_appid.txt
Normal file
1
Facepunch.Steamworks.Test/bin/Debug/steam_appid.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
252490
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Release/FacepunchSteamworksApi.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Release/FacepunchSteamworksApi.dll
Normal file
Binary file not shown.
@ -1,74 +0,0 @@
|
|||||||
"In Game Actions"
|
|
||||||
{
|
|
||||||
"actions"
|
|
||||||
{
|
|
||||||
"InGameControls"
|
|
||||||
{
|
|
||||||
"title" "#Set_Ingame"
|
|
||||||
"StickPadGyro"
|
|
||||||
{
|
|
||||||
"Move"
|
|
||||||
{
|
|
||||||
"title" "#Action_Move"
|
|
||||||
"input_mode" "joystick_move"
|
|
||||||
}
|
|
||||||
"Camera"
|
|
||||||
{
|
|
||||||
"title" "#Action_Camera"
|
|
||||||
"input_mode" "absolute_mouse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"AnalogTrigger"
|
|
||||||
{
|
|
||||||
"Throttle" "#Action_Throttle"
|
|
||||||
}
|
|
||||||
"Button"
|
|
||||||
{
|
|
||||||
"fire" "#Action_Fire"
|
|
||||||
"Jump" "#Action_Jump"
|
|
||||||
"pause_menu" "#Action_Menu"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"MenuControls"
|
|
||||||
{
|
|
||||||
"title" "#Set_Menu"
|
|
||||||
"StickPadGyro"
|
|
||||||
{
|
|
||||||
}
|
|
||||||
"AnalogTrigger"
|
|
||||||
{
|
|
||||||
}
|
|
||||||
"Button"
|
|
||||||
{
|
|
||||||
"menu_up" "#Menu_Up"
|
|
||||||
"menu_down" "#Menu_Down"
|
|
||||||
"menu_left" "#Menu_Left"
|
|
||||||
"menu_right" "#Menu_Right"
|
|
||||||
"menu_select" "#Menu_Select"
|
|
||||||
"menu_cancel" "#Menu_Cancel"
|
|
||||||
"pause_menu" "#Action_ReturnToGame"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"localization"
|
|
||||||
{
|
|
||||||
"english"
|
|
||||||
{
|
|
||||||
"Set_Ingame" "In-Game Controls"
|
|
||||||
"Set_Menu" "Menu Controls"
|
|
||||||
"Action_Move" "Movement"
|
|
||||||
"Action_Camera" "Camera"
|
|
||||||
"Action_Throttle" "Throttle"
|
|
||||||
"Action_Fire" "Fire Weapon"
|
|
||||||
"Action_Jump" "Jump"
|
|
||||||
"Action_Menu" "Pause Menu"
|
|
||||||
"Action_ReturnToGame" "Return To Game"
|
|
||||||
"Menu_Up" "Up"
|
|
||||||
"Menu_Down" "Down"
|
|
||||||
"Menu_Left" "Left"
|
|
||||||
"Menu_Right" "Right"
|
|
||||||
"Menu_Select" "Select"
|
|
||||||
"Menu_Cancel" "Cancel"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
1
Facepunch.Steamworks.Test/bin/Release/steam_appid.txt
Normal file
1
Facepunch.Steamworks.Test/bin/Release/steam_appid.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
252490
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<packages>
|
|
||||||
<package id="MSTest.TestAdapter" version="2.0.0-beta4" targetFramework="net46" />
|
|
||||||
<package id="MSTest.TestFramework" version="2.0.0-beta4" targetFramework="net46" />
|
|
||||||
<package id="Newtonsoft.Json" version="9.0.2-beta1" targetFramework="net452" />
|
|
||||||
</packages>
|
|
Binary file not shown.
Binary file not shown.
@ -1,107 +1,28 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 16.0.29009.5
|
VisualStudioVersion = 14.0.25123.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Generator", "Generator\Generator.csproj", "{B7225D11-2AAA-49D6-AE93-A73696EA35FE}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks", "Facepunch.Steamworks\Facepunch.Steamworks.csproj", "{DC2D9FA9-F005-468F-8581-85C79F4E0034}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.Win64", "Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj", "{8C73DA93-73AD-4445-9A2C-15D4A44337D3}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks.Test", "Facepunch.Steamworks.Test\Facepunch.Steamworks.Test.csproj", "{3F6183AD-D966-44F2-A6EB-42E61E591B49}"
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.Win32", "Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj", "{2D6247F6-8AB2-405F-A00E-3A364B808A55}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.Posix", "Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj", "{C62FF421-BE44-4DB0-B99A-E13E007A30B9}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks.TestWin32", "Facepunch.Steamworks.Test\Facepunch.Steamworks.TestWin32.csproj", "{3F6183AD-D966-44F2-A6EB-42E61E591B49}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks.TestWin64", "Facepunch.Steamworks.Test\Facepunch.Steamworks.TestWin64.csproj", "{165081E3-BD96-404B-B83E-A635F1AF7CDE}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|x64 = Release|x64
|
|
||||||
Release|x86 = Release|x86
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|x64.Build.0 = Debug|Any CPU
|
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|Any CPU.Build.0 = Release|Any CPU
|
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|x64.Build.0 = Release|x64
|
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|x86.Build.0 = Release|x86
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|x64.Build.0 = Release|x64
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|x86.Build.0 = Release|x86
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {506FC2EC-38D1-45E2-BAE8-D61584162F7D}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
146
Facepunch.Steamworks/BaseSteamworks.cs
Normal file
146
Facepunch.Steamworks/BaseSteamworks.cs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Facepunch.Steamworks.Interop;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public class BaseSteamworks : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Current running program's AppId
|
||||||
|
/// </summary>
|
||||||
|
public uint AppId { get; internal set; }
|
||||||
|
|
||||||
|
public Networking Networking { get; internal set; }
|
||||||
|
public Inventory Inventory { get; internal set; }
|
||||||
|
public Workshop Workshop { get; internal set; }
|
||||||
|
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
foreach ( var d in Disposables )
|
||||||
|
{
|
||||||
|
d.Dispose();
|
||||||
|
}
|
||||||
|
Disposables.Clear();
|
||||||
|
|
||||||
|
Workshop.Dispose();
|
||||||
|
Workshop = null;
|
||||||
|
|
||||||
|
Inventory.Dispose();
|
||||||
|
Inventory = null;
|
||||||
|
|
||||||
|
Networking.Dispose();
|
||||||
|
Networking = null;
|
||||||
|
|
||||||
|
if ( native != null )
|
||||||
|
{
|
||||||
|
native.Dispose();
|
||||||
|
native = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetupCommonInterfaces()
|
||||||
|
{
|
||||||
|
Networking = new Steamworks.Networking( this, native.networking );
|
||||||
|
Inventory = new Steamworks.Inventory( native.inventory, IsGameServer );
|
||||||
|
Workshop = new Steamworks.Workshop( this, native.ugc, native.remoteStorage );
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsValid
|
||||||
|
{
|
||||||
|
get { return native != null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Interop.NativeInterface native;
|
||||||
|
internal virtual bool IsGameServer { get { return false; } }
|
||||||
|
|
||||||
|
private List<IDisposable> Disposables = new List<IDisposable>();
|
||||||
|
|
||||||
|
public enum MessageType : int
|
||||||
|
{
|
||||||
|
Message = 0,
|
||||||
|
Warning = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called with a message from Steam
|
||||||
|
/// </summary>
|
||||||
|
public Action<MessageType, string> OnMessage;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Global callback type
|
||||||
|
/// </summary>
|
||||||
|
internal void AddCallback<T, TSmall>( Action<T> Callback, int id )
|
||||||
|
{
|
||||||
|
var callback = new Callback<T, TSmall>( IsGameServer, id, Callback );
|
||||||
|
Disposables.Add( callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddCallback<T>( Action<T> Callback, int id )
|
||||||
|
{
|
||||||
|
AddCallback<T, T>( Callback, id );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action OnUpdate;
|
||||||
|
|
||||||
|
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
RunCallbackQueue();
|
||||||
|
|
||||||
|
Inventory.Update();
|
||||||
|
Networking.Update();
|
||||||
|
|
||||||
|
if ( OnUpdate != null )
|
||||||
|
OnUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CallResult> Callbacks = new List<CallResult>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call results are results to specific actions
|
||||||
|
/// </summary>
|
||||||
|
internal void AddCallResult( CallResult call )
|
||||||
|
{
|
||||||
|
if ( call == null ) throw new ArgumentNullException( "call" );
|
||||||
|
|
||||||
|
if ( FinishCallback( call ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Callbacks.Add( call );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunCallbackQueue()
|
||||||
|
{
|
||||||
|
for ( int i=0; i< Callbacks.Count(); i++ )
|
||||||
|
{
|
||||||
|
if ( !FinishCallback( Callbacks[i] ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Callbacks.RemoveAt( i );
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FinishCallback( CallResult call )
|
||||||
|
{
|
||||||
|
bool failed = true;
|
||||||
|
|
||||||
|
if ( !native.utils.IsAPICallCompleted( call.Handle, ref failed ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( failed )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// TODO - failure reason?
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
call.Run( native.utils );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,98 +0,0 @@
|
|||||||
using Steamworks.Data;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An awaitable version of a SteamAPICall_t
|
|
||||||
/// </summary>
|
|
||||||
internal struct CallResult<T> : INotifyCompletion where T : struct, ICallbackData
|
|
||||||
{
|
|
||||||
SteamAPICall_t call;
|
|
||||||
ISteamUtils utils;
|
|
||||||
bool server;
|
|
||||||
|
|
||||||
public CallResult( SteamAPICall_t call, bool server )
|
|
||||||
{
|
|
||||||
this.call = call;
|
|
||||||
this.server = server;
|
|
||||||
|
|
||||||
utils = (server ? SteamUtils.InterfaceServer : SteamUtils.InterfaceClient) as ISteamUtils;
|
|
||||||
|
|
||||||
if ( utils == null )
|
|
||||||
utils = SteamUtils.Interface as ISteamUtils;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This gets called if IsComplete returned false on the first call.
|
|
||||||
/// The Action "continues" the async call. We pass it to the Dispatch
|
|
||||||
/// to be called when the callback returns.
|
|
||||||
/// </summary>
|
|
||||||
public void OnCompleted( Action continuation )
|
|
||||||
{
|
|
||||||
if (IsCompleted)
|
|
||||||
continuation();
|
|
||||||
else
|
|
||||||
Dispatch.OnCallComplete<T>(call, continuation, server);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the result. This is called internally by the async shit.
|
|
||||||
/// </summary>
|
|
||||||
public T? GetResult()
|
|
||||||
{
|
|
||||||
bool failed = false;
|
|
||||||
if ( !utils.IsAPICallCompleted( call, ref failed ) || failed )
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var t = default( T );
|
|
||||||
var size = t.DataSize;
|
|
||||||
var ptr = Marshal.AllocHGlobal( size );
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if ( !utils.GetAPICallResult( call, ptr, size, (int)t.CallbackType, ref failed ) || failed )
|
|
||||||
{
|
|
||||||
Dispatch.OnDebugCallback?.Invoke( t.CallbackType, "!GetAPICallResult or failed", server );
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dispatch.OnDebugCallback?.Invoke( t.CallbackType, Dispatch.CallbackToString( t.CallbackType, ptr, size ), server );
|
|
||||||
|
|
||||||
return ((T)Marshal.PtrToStructure( ptr, typeof( T ) ));
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal( ptr );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Return true if complete or failed
|
|
||||||
/// </summary>
|
|
||||||
public bool IsCompleted
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
bool failed = false;
|
|
||||||
if ( utils.IsAPICallCompleted( call, ref failed ) || failed )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is what makes this struct awaitable
|
|
||||||
/// </summary>
|
|
||||||
internal CallResult<T> GetAwaiter()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using Steamworks.Data;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gives us a generic way to get the CallbackId of structs
|
|
||||||
/// </summary>
|
|
||||||
internal interface ICallbackData
|
|
||||||
{
|
|
||||||
CallbackType CallbackType { get; }
|
|
||||||
int DataSize { get; }
|
|
||||||
}
|
|
||||||
}
|
|
124
Facepunch.Steamworks/Callbacks/Index.cs
Normal file
124
Facepunch.Steamworks/Callbacks/Index.cs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Callbacks
|
||||||
|
{
|
||||||
|
internal static class Index
|
||||||
|
{
|
||||||
|
internal const int User = 100;
|
||||||
|
internal const int Networking = 1200;
|
||||||
|
internal const int RemoteStorage = 1300;
|
||||||
|
internal const int UGC = 3400;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Result : int
|
||||||
|
{
|
||||||
|
OK = 1, // success
|
||||||
|
Fail = 2, // generic failure
|
||||||
|
NoConnection = 3, // no/failed network connection
|
||||||
|
// k_EResultNoConnectionRetry = 4, // OBSOLETE - removed
|
||||||
|
InvalidPassword = 5, // password/ticket is invalid
|
||||||
|
LoggedInElsewhere = 6, // same user logged in elsewhere
|
||||||
|
InvalidProtocolVer = 7, // protocol version is incorrect
|
||||||
|
InvalidParam = 8, // a parameter is incorrect
|
||||||
|
FileNotFound = 9, // file was not found
|
||||||
|
Busy = 10, // called method busy - action not taken
|
||||||
|
InvalidState = 11, // called object was in an invalid state
|
||||||
|
InvalidName = 12, // name is invalid
|
||||||
|
InvalidEmail = 13, // email is invalid
|
||||||
|
DuplicateName = 14, // name is not unique
|
||||||
|
AccessDenied = 15, // access is denied
|
||||||
|
Timeout = 16, // operation timed out
|
||||||
|
Banned = 17, // VAC2 banned
|
||||||
|
AccountNotFound = 18, // account not found
|
||||||
|
InvalidSteamID = 19, // steamID is invalid
|
||||||
|
ServiceUnavailable = 20, // The requested service is currently unavailable
|
||||||
|
NotLoggedOn = 21, // The user is not logged on
|
||||||
|
Pending = 22, // Request is pending (may be in process, or waiting on third party)
|
||||||
|
EncryptionFailure = 23, // Encryption or Decryption failed
|
||||||
|
InsufficientPrivilege = 24, // Insufficient privilege
|
||||||
|
LimitExceeded = 25, // Too much of a good thing
|
||||||
|
Revoked = 26, // Access has been revoked (used for revoked guest passes)
|
||||||
|
Expired = 27, // License/Guest pass the user is trying to access is expired
|
||||||
|
AlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again
|
||||||
|
DuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time
|
||||||
|
AlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user
|
||||||
|
IPNotFound = 31, // IP address not found
|
||||||
|
PersistFailed = 32, // failed to write change to the data store
|
||||||
|
LockingFailed = 33, // failed to acquire access lock for this operation
|
||||||
|
LogonSessionReplaced = 34,
|
||||||
|
ConnectFailed = 35,
|
||||||
|
HandshakeFailed = 36,
|
||||||
|
IOFailure = 37,
|
||||||
|
RemoteDisconnect = 38,
|
||||||
|
ShoppingCartNotFound = 39, // failed to find the shopping cart requested
|
||||||
|
Blocked = 40, // a user didn't allow it
|
||||||
|
Ignored = 41, // target is ignoring sender
|
||||||
|
NoMatch = 42, // nothing matching the request found
|
||||||
|
AccountDisabled = 43,
|
||||||
|
ServiceReadOnly = 44, // this service is not accepting content changes right now
|
||||||
|
AccountNotFeatured = 45, // account doesn't have value, so this feature isn't available
|
||||||
|
AdministratorOK = 46, // allowed to take this action, but only because requester is admin
|
||||||
|
ContentVersion = 47, // A Version mismatch in content transmitted within the Steam protocol.
|
||||||
|
TryAnotherCM = 48, // The current CM can't service the user making a request, user should try another.
|
||||||
|
PasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed.
|
||||||
|
AlreadyLoggedInElsewhere = 50, // You are already logged in elsewhere, you must wait
|
||||||
|
Suspended = 51, // Long running operation (content download) suspended/paused
|
||||||
|
Cancelled = 52, // Operation canceled (typically by user: content download)
|
||||||
|
DataCorruption = 53, // Operation canceled because data is ill formed or unrecoverable
|
||||||
|
DiskFull = 54, // Operation canceled - not enough disk space.
|
||||||
|
RemoteCallFailed = 55, // an remote call or IPC call failed
|
||||||
|
PasswordUnset = 56, // Password could not be verified as it's unset server side
|
||||||
|
ExternalAccountUnlinked = 57, // External account (PSN, Facebook...) is not linked to a Steam account
|
||||||
|
PSNTicketInvalid = 58, // PSN ticket was invalid
|
||||||
|
ExternalAccountAlreadyLinked = 59, // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first
|
||||||
|
RemoteFileConflict = 60, // The sync cannot resume due to a conflict between the local and remote files
|
||||||
|
IllegalPassword = 61, // The requested new password is not legal
|
||||||
|
SameAsPreviousValue = 62, // new value is the same as the old one ( secret question and answer )
|
||||||
|
AccountLogonDenied = 63, // account login denied due to 2nd factor authentication failure
|
||||||
|
CannotUseOldPassword = 64, // The requested new password is not legal
|
||||||
|
InvalidLoginAuthCode = 65, // account login denied due to auth code invalid
|
||||||
|
AccountLogonDeniedNoMail = 66, // account login denied due to 2nd factor auth failure - and no mail has been sent
|
||||||
|
HardwareNotCapableOfIPT = 67, //
|
||||||
|
IPTInitError = 68, //
|
||||||
|
ParentalControlRestricted = 69, // operation failed due to parental control restrictions for current user
|
||||||
|
FacebookQueryError = 70, // Facebook query returned an error
|
||||||
|
ExpiredLoginAuthCode = 71, // account login denied due to auth code expired
|
||||||
|
IPLoginRestrictionFailed = 72,
|
||||||
|
AccountLockedDown = 73,
|
||||||
|
AccountLogonDeniedVerifiedEmailRequired = 74,
|
||||||
|
NoMatchingURL = 75,
|
||||||
|
BadResponse = 76, // parse failure, missing field, etc.
|
||||||
|
RequirePasswordReEntry = 77, // The user cannot complete the action until they re-enter their password
|
||||||
|
ValueOutOfRange = 78, // the value entered is outside the acceptable range
|
||||||
|
UnexpectedError = 79, // something happened that we didn't expect to ever happen
|
||||||
|
Disabled = 80, // The requested service has been configured to be unavailable
|
||||||
|
InvalidCEGSubmission = 81, // The set of files submitted to the CEG server are not valid !
|
||||||
|
RestrictedDevice = 82, // The device being used is not allowed to perform this action
|
||||||
|
RegionLocked = 83, // The action could not be complete because it is region restricted
|
||||||
|
RateLimitExceeded = 84, // Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent
|
||||||
|
AccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to login
|
||||||
|
ItemDeleted = 86, // The thing we're trying to access has been deleted
|
||||||
|
AccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker
|
||||||
|
TwoFactorCodeMismatch = 88, // two factor code mismatch
|
||||||
|
TwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match
|
||||||
|
AccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners
|
||||||
|
NotModified = 91, // data not modified
|
||||||
|
NoMobileDevice = 92, // the account does not have a mobile device associated with it
|
||||||
|
TimeNotSynced = 93, // the time presented is out of range or tolerance
|
||||||
|
SmsCodeFailed = 94, // SMS code failure (no match, none pending, etc.)
|
||||||
|
AccountLimitExceeded = 95, // Too many accounts access this resource
|
||||||
|
AccountActivityLimitExceeded = 96, // Too many changes to this account
|
||||||
|
PhoneActivityLimitExceeded = 97, // Too many changes to this phone
|
||||||
|
RefundToWallet = 98, // Cannot refund to payment method, must use wallet
|
||||||
|
EmailSendFailure = 99, // Cannot send an email
|
||||||
|
NotSettled = 100, // Can't perform operation till payment has settled
|
||||||
|
NeedCaptcha = 101, // Needs to provide a valid captcha
|
||||||
|
GSLTDenied = 102, // a game server login token owned by this token's owner has been banned
|
||||||
|
GSOwnerDenied = 103, // game server owner is denied for other reason (account lock, community ban, vac ban, missing phone)
|
||||||
|
InvalidItemType = 104, // the type of thing we were requested to act on is invalid
|
||||||
|
IPBanned = 105, // the ip address has been banned from taking this action
|
||||||
|
};
|
||||||
|
}
|
27
Facepunch.Steamworks/Callbacks/Networking.cs
Normal file
27
Facepunch.Steamworks/Callbacks/Networking.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Callbacks.Networking
|
||||||
|
{
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
internal class P2PSessionRequest
|
||||||
|
{
|
||||||
|
public ulong SteamID;
|
||||||
|
|
||||||
|
public const int CallbackId = Index.Networking + 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
internal class P2PSessionConnectFail
|
||||||
|
{
|
||||||
|
public ulong SteamID;
|
||||||
|
public Steamworks.Networking.SessionError Error;
|
||||||
|
|
||||||
|
public const int CallbackId = Index.Networking + 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
34
Facepunch.Steamworks/Callbacks/User.cs
Normal file
34
Facepunch.Steamworks/Callbacks/User.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Callbacks.User
|
||||||
|
{
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
internal struct ValidateAuthTicketResponse
|
||||||
|
{
|
||||||
|
public ulong SteamID;
|
||||||
|
public int AuthResponse;
|
||||||
|
public ulong OwnerSteamID;
|
||||||
|
|
||||||
|
public const int CallbackId = Index.User + 43;
|
||||||
|
|
||||||
|
public enum Response : int
|
||||||
|
{
|
||||||
|
Okay = 0, // Steam has verified the user is online, the ticket is valid and ticket has not been reused.
|
||||||
|
UserNotConnectedToSteam = 1, // The user in question is not connected to steam
|
||||||
|
NoLicenseOrExpired = 2, // The license has expired.
|
||||||
|
VACBanned = 3, // The user is VAC banned for this game.
|
||||||
|
LoggedInElseWhere = 4, // The user account has logged in elsewhere and the session containing the game instance has been disconnected.
|
||||||
|
VACCheckTimedOut = 5, // VAC has been unable to perform anti-cheat checks on this user
|
||||||
|
AuthTicketCanceled = 6, // The ticket has been canceled by the issuer
|
||||||
|
AuthTicketInvalidAlreadyUsed = 7, // This ticket has already been used, it is not valid.
|
||||||
|
AuthTicketInvalid = 8, // This ticket is not from a user instance currently connected to steam.
|
||||||
|
PublisherIssuedBan = 9, // The user is banned for this game. The ban came via the web api and not VAC
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
107
Facepunch.Steamworks/Callbacks/Workshop.cs
Normal file
107
Facepunch.Steamworks/Callbacks/Workshop.cs
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Facepunch.Steamworks.Interop;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Callbacks.Workshop
|
||||||
|
{
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
|
internal struct ItemInstalled
|
||||||
|
{
|
||||||
|
public uint AppId;
|
||||||
|
public ulong FileId;
|
||||||
|
|
||||||
|
public const int CallbackId = Index.UGC + 5;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
public uint AppId;
|
||||||
|
public ulong FileId;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
|
internal struct DownloadResult
|
||||||
|
{
|
||||||
|
public uint AppId;
|
||||||
|
public ulong FileId;
|
||||||
|
public Result Result;
|
||||||
|
|
||||||
|
public const int CallbackId = Index.UGC + 6;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
public uint AppId;
|
||||||
|
public ulong FileId;
|
||||||
|
public Result Result;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
internal class QueryCompleted : CallResult<QueryCompleted.Data, QueryCompleted.Data.Small>
|
||||||
|
{
|
||||||
|
public override int CallbackId { get { return Index.UGC + 1; } }
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
|
internal struct Data
|
||||||
|
{
|
||||||
|
internal ulong Handle;
|
||||||
|
internal int Result;
|
||||||
|
internal uint NumResultsReturned;
|
||||||
|
internal uint TotalMatchingResults;
|
||||||
|
internal bool CachedData;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
internal ulong Handle;
|
||||||
|
internal int Result;
|
||||||
|
internal uint NumResultsReturned;
|
||||||
|
internal uint TotalMatchingResults;
|
||||||
|
internal bool CachedData;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CreateItem : CallResult<CreateItem.Data, CreateItem.Data.Small>
|
||||||
|
{
|
||||||
|
public override int CallbackId { get { return Index.UGC + 3; } }
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
|
internal struct Data
|
||||||
|
{
|
||||||
|
internal Result Result;
|
||||||
|
internal ulong FileId;
|
||||||
|
internal bool NeedsLegalAgreement;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
internal Result Result;
|
||||||
|
internal ulong FileId;
|
||||||
|
|
||||||
|
internal bool NeedsLegalAgreement;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class SubmitItemUpdate : CallResult<SubmitItemUpdate.Data, SubmitItemUpdate.Data.Small>
|
||||||
|
{
|
||||||
|
public override int CallbackId { get { return Index.UGC + 4; } }
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
|
internal struct Data
|
||||||
|
{
|
||||||
|
internal Result Result;
|
||||||
|
internal bool NeedsLegalAgreement;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
internal Result Result;
|
||||||
|
internal bool NeedsLegalAgreement;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
public class AuthTicket : IDisposable
|
|
||||||
{
|
|
||||||
public byte[] Data;
|
|
||||||
public uint Handle;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cancels a ticket.
|
|
||||||
/// You should cancel your ticket when you close the game or leave a server.
|
|
||||||
/// </summary>
|
|
||||||
public void Cancel()
|
|
||||||
{
|
|
||||||
if ( Handle != 0 )
|
|
||||||
{
|
|
||||||
SteamUser.Internal.CancelAuthTicket( Handle );
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle = 0;
|
|
||||||
Data = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,334 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Steamworks.Data;
|
|
||||||
using Steamworks;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Responsible for all callback/callresult handling
|
|
||||||
///
|
|
||||||
/// This manually pumps Steam's message queue and dispatches those
|
|
||||||
/// events to any waiting callbacks/callresults.
|
|
||||||
/// </summary>
|
|
||||||
public static class Dispatch
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// If set then we'll call this function every time a callback is generated.
|
|
||||||
///
|
|
||||||
/// This is SLOW!! - it's for debugging - don't keep it on all the time. If you want to access a specific
|
|
||||||
/// callback then please create an issue on github and I'll add it!
|
|
||||||
///
|
|
||||||
/// Params are : [Callback Type] [Callback Contents] [server]
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static Action<CallbackType, string, bool> OnDebugCallback;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called if an exception happens during a callback/callresult.
|
|
||||||
/// This is needed because the exception isn't always accessible when running
|
|
||||||
/// async.. and can fail silently. With this hooked you won't be stuck wondering
|
|
||||||
/// what happened.
|
|
||||||
/// </summary>
|
|
||||||
public static Action<Exception> OnException;
|
|
||||||
|
|
||||||
#region interop
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_Init", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
internal static extern void SteamAPI_ManualDispatch_Init();
|
|
||||||
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_RunFrame", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
internal static extern void SteamAPI_ManualDispatch_RunFrame( HSteamPipe pipe );
|
|
||||||
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_GetNextCallback", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
[return: MarshalAs( UnmanagedType.I1 )]
|
|
||||||
internal static extern bool SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe pipe, [In, Out] ref CallbackMsg_t msg );
|
|
||||||
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_FreeLastCallback", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
[return: MarshalAs( UnmanagedType.I1 )]
|
|
||||||
internal static extern bool SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe pipe );
|
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Sequential, Pack = Platform.StructPlatformPackSize )]
|
|
||||||
internal struct CallbackMsg_t
|
|
||||||
{
|
|
||||||
public HSteamUser m_hSteamUser; // Specific user to whom this callback applies.
|
|
||||||
public CallbackType Type; // Callback identifier. (Corresponds to the k_iCallback enum in the callback structure.)
|
|
||||||
public IntPtr Data; // Points to the callback structure
|
|
||||||
public int DataSize; // Size of the data pointed to by m_pubParam
|
|
||||||
};
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
internal static HSteamPipe ClientPipe { get; set; }
|
|
||||||
internal static HSteamPipe ServerPipe { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This gets called from Client/Server Init
|
|
||||||
/// It's important to switch to the manual dispatcher
|
|
||||||
/// </summary>
|
|
||||||
internal static void Init()
|
|
||||||
{
|
|
||||||
SteamAPI_ManualDispatch_Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Make sure we don't call Frame in a callback - because that'll cause some issues for everyone.
|
|
||||||
/// </summary>
|
|
||||||
static bool runningFrame = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls RunFrame and processes events from this Steam Pipe
|
|
||||||
/// </summary>
|
|
||||||
internal static void Frame( HSteamPipe pipe )
|
|
||||||
{
|
|
||||||
if ( runningFrame )
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
runningFrame = true;
|
|
||||||
|
|
||||||
SteamAPI_ManualDispatch_RunFrame( pipe );
|
|
||||||
SteamNetworkingUtils.OutputDebugMessages();
|
|
||||||
|
|
||||||
CallbackMsg_t msg = default;
|
|
||||||
|
|
||||||
while ( SteamAPI_ManualDispatch_GetNextCallback( pipe, ref msg ) )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ProcessCallback( msg, pipe == ServerPipe );
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
SteamAPI_ManualDispatch_FreeLastCallback( pipe );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ( System.Exception e )
|
|
||||||
{
|
|
||||||
OnException?.Invoke( e );
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
runningFrame = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// To be safe we don't call the continuation functions while iterating
|
|
||||||
/// the Callback list. This is maybe overly safe because the only way this
|
|
||||||
/// could be an issue is if the callback list is modified in the continuation
|
|
||||||
/// which would only happen if starting or shutting down in the callback.
|
|
||||||
/// </summary>
|
|
||||||
static List<Action<IntPtr>> actionsToCall = new List<Action<IntPtr>>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A callback is a general global message
|
|
||||||
/// </summary>
|
|
||||||
private static void ProcessCallback( CallbackMsg_t msg, bool isServer )
|
|
||||||
{
|
|
||||||
OnDebugCallback?.Invoke( msg.Type, CallbackToString( msg.Type, msg.Data, msg.DataSize ), isServer );
|
|
||||||
|
|
||||||
// Is this a special callback telling us that the call result is ready?
|
|
||||||
if ( msg.Type == CallbackType.SteamAPICallCompleted )
|
|
||||||
{
|
|
||||||
ProcessResult( msg );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( Callbacks.TryGetValue( msg.Type, out var list ) )
|
|
||||||
{
|
|
||||||
actionsToCall.Clear();
|
|
||||||
|
|
||||||
foreach ( var item in list )
|
|
||||||
{
|
|
||||||
if ( item.server != isServer )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
actionsToCall.Add( item.action );
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ( var action in actionsToCall )
|
|
||||||
{
|
|
||||||
action( msg.Data );
|
|
||||||
}
|
|
||||||
|
|
||||||
actionsToCall.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Given a callback, try to turn it into a string
|
|
||||||
/// </summary>
|
|
||||||
internal static string CallbackToString( CallbackType type, IntPtr data, int expectedsize )
|
|
||||||
{
|
|
||||||
if ( !CallbackTypeFactory.All.TryGetValue( type, out var t ) )
|
|
||||||
return $"[{type} not in sdk]";
|
|
||||||
|
|
||||||
var strct = data.ToType( t );
|
|
||||||
if ( strct == null )
|
|
||||||
return "[null]";
|
|
||||||
|
|
||||||
var str = "";
|
|
||||||
|
|
||||||
var fields = t.GetFields( System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic );
|
|
||||||
|
|
||||||
if ( fields.Length == 0 )
|
|
||||||
return "[no fields]";
|
|
||||||
|
|
||||||
var columnSize = fields.Max( x => x.Name.Length ) + 1;
|
|
||||||
|
|
||||||
if ( columnSize < 10 )
|
|
||||||
columnSize = 10;
|
|
||||||
|
|
||||||
foreach ( var field in fields )
|
|
||||||
{
|
|
||||||
var spaces = (columnSize - field.Name.Length);
|
|
||||||
if ( spaces < 0 ) spaces = 0;
|
|
||||||
|
|
||||||
str += $"{new String( ' ', spaces )}{field.Name}: {field.GetValue( strct )}\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return str.Trim( '\n' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A result is a reply to a specific command
|
|
||||||
/// </summary>
|
|
||||||
private static void ProcessResult( CallbackMsg_t msg )
|
|
||||||
{
|
|
||||||
var result = msg.Data.ToType<SteamAPICallCompleted_t>();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do we have an entry added via OnCallComplete
|
|
||||||
//
|
|
||||||
if ( !ResultCallbacks.TryGetValue( result.AsyncCall, out var callbackInfo ) )
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// This can happen if the callback result was immediately available
|
|
||||||
// so we just returned that without actually going through the callback
|
|
||||||
// dance. It's okay for this to fail.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// But still let everyone know that this happened..
|
|
||||||
//
|
|
||||||
OnDebugCallback?.Invoke( (CallbackType)result.Callback, $"[no callback waiting/required]", false );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove it before we do anything, incase the continuation throws exceptions
|
|
||||||
ResultCallbacks.Remove( result.AsyncCall );
|
|
||||||
|
|
||||||
// At this point whatever async routine called this
|
|
||||||
// continues running.
|
|
||||||
callbackInfo.continuation();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pumps the queue in an async loop so we don't
|
|
||||||
/// have to think about it. This has the advantage that
|
|
||||||
/// you can call .Wait() on async shit and it still works.
|
|
||||||
/// </summary>
|
|
||||||
internal static async void LoopClientAsync()
|
|
||||||
{
|
|
||||||
while ( ClientPipe != 0 )
|
|
||||||
{
|
|
||||||
Frame( ClientPipe );
|
|
||||||
await Task.Delay( 16 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pumps the queue in an async loop so we don't
|
|
||||||
/// have to think about it. This has the advantage that
|
|
||||||
/// you can call .Wait() on async shit and it still works.
|
|
||||||
/// </summary>
|
|
||||||
internal static async void LoopServerAsync()
|
|
||||||
{
|
|
||||||
while ( ServerPipe != 0 )
|
|
||||||
{
|
|
||||||
Frame( ServerPipe );
|
|
||||||
await Task.Delay( 32 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ResultCallback
|
|
||||||
{
|
|
||||||
public Action continuation;
|
|
||||||
public bool server;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Dictionary<ulong, ResultCallback> ResultCallbacks = new Dictionary<ulong, ResultCallback>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Watch for a steam api call
|
|
||||||
/// </summary>
|
|
||||||
internal static void OnCallComplete<T>( SteamAPICall_t call, Action continuation, bool server ) where T : struct, ICallbackData
|
|
||||||
{
|
|
||||||
ResultCallbacks[call.Value] = new ResultCallback
|
|
||||||
{
|
|
||||||
continuation = continuation,
|
|
||||||
server = server
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Callback
|
|
||||||
{
|
|
||||||
public Action<IntPtr> action;
|
|
||||||
public bool server;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Dictionary<CallbackType, List<Callback>> Callbacks = new Dictionary<CallbackType, List<Callback>>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Install a global callback. The passed function will get called if it's all good.
|
|
||||||
/// </summary>
|
|
||||||
internal static void Install<T>( Action<T> p, bool server = false ) where T : ICallbackData
|
|
||||||
{
|
|
||||||
var t = default( T );
|
|
||||||
var type = t.CallbackType;
|
|
||||||
|
|
||||||
if ( !Callbacks.TryGetValue( type, out var list ) )
|
|
||||||
{
|
|
||||||
list = new List<Callback>();
|
|
||||||
Callbacks[type] = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add( new Callback
|
|
||||||
{
|
|
||||||
action = x => p( x.ToType<T>() ),
|
|
||||||
server = server
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void ShutdownServer()
|
|
||||||
{
|
|
||||||
ServerPipe = 0;
|
|
||||||
|
|
||||||
foreach ( var callback in Callbacks )
|
|
||||||
{
|
|
||||||
Callbacks[callback.Key].RemoveAll( x => x.server );
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultCallbacks = ResultCallbacks.Where( x => !x.Value.server )
|
|
||||||
.ToDictionary( x => x.Key, x => x.Value );
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void ShutdownClient()
|
|
||||||
{
|
|
||||||
ClientPipe = 0;
|
|
||||||
|
|
||||||
foreach ( var callback in Callbacks )
|
|
||||||
{
|
|
||||||
Callbacks[callback.Key].RemoveAll( x => !x.server );
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultCallbacks = ResultCallbacks.Where( x => x.Value.server )
|
|
||||||
.ToDictionary( x => x.Key, x => x.Value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
internal static class SteamAPI
|
|
||||||
{
|
|
||||||
internal static class Native
|
|
||||||
{
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamInternal_SteamAPI_Init", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
public static extern SteamAPIInitResult SteamInternal_SteamAPI_Init( IntPtr pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg );
|
|
||||||
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_Shutdown", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
public static extern void SteamAPI_Shutdown();
|
|
||||||
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_GetHSteamPipe", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
public static extern HSteamPipe SteamAPI_GetHSteamPipe();
|
|
||||||
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_RestartAppIfNecessary", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
[return: MarshalAs( UnmanagedType.I1 )]
|
|
||||||
public static extern bool SteamAPI_RestartAppIfNecessary( uint unOwnAppID );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static internal SteamAPIInitResult Init( string pszInternalCheckInterfaceVersions, out string pOutErrMsg )
|
|
||||||
{
|
|
||||||
using var interfaceVersionsStr = new Utf8StringToNative( pszInternalCheckInterfaceVersions );
|
|
||||||
using var buffer = Helpers.Memory.Take();
|
|
||||||
var result = Native.SteamInternal_SteamAPI_Init( interfaceVersionsStr.Pointer, buffer.Ptr );
|
|
||||||
pOutErrMsg = Helpers.MemoryToString( buffer.Ptr );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static internal void Shutdown()
|
|
||||||
{
|
|
||||||
Native.SteamAPI_Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
static internal HSteamPipe GetHSteamPipe()
|
|
||||||
{
|
|
||||||
return Native.SteamAPI_GetHSteamPipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
static internal bool RestartAppIfNecessary( uint unOwnAppID )
|
|
||||||
{
|
|
||||||
return Native.SteamAPI_RestartAppIfNecessary( unOwnAppID );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
internal static class SteamGameServer
|
|
||||||
{
|
|
||||||
internal static class Native
|
|
||||||
{
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_RunCallbacks", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
public static extern void SteamGameServer_RunCallbacks();
|
|
||||||
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_Shutdown", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
public static extern void SteamGameServer_Shutdown();
|
|
||||||
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_GetHSteamPipe", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
public static extern HSteamPipe SteamGameServer_GetHSteamPipe();
|
|
||||||
|
|
||||||
}
|
|
||||||
static internal void RunCallbacks()
|
|
||||||
{
|
|
||||||
Native.SteamGameServer_RunCallbacks();
|
|
||||||
}
|
|
||||||
|
|
||||||
static internal void Shutdown()
|
|
||||||
{
|
|
||||||
Native.SteamGameServer_Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
static internal HSteamPipe GetHSteamPipe()
|
|
||||||
{
|
|
||||||
return Native.SteamGameServer_GetHSteamPipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Steamworks.Data;
|
|
||||||
|
|
||||||
|
|
||||||
namespace Steamworks
|
|
||||||
{
|
|
||||||
internal static class SteamInternal
|
|
||||||
{
|
|
||||||
internal static class Native
|
|
||||||
{
|
|
||||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamInternal_GameServer_Init_V2", CallingConvention = CallingConvention.Cdecl )]
|
|
||||||
public static extern SteamAPIInitResult SteamInternal_GameServer_Init_V2( uint unIP, ushort usGamePort, ushort usQueryPort, int eServerMode, IntPtr pchVersionString, IntPtr pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg );
|
|
||||||
}
|
|
||||||
|
|
||||||
static internal SteamAPIInitResult GameServer_Init( uint unIP, ushort usGamePort, ushort usQueryPort, int eServerMode, string pchVersionString, string pszInternalCheckInterfaceVersions, out string pOutErrMsg )
|
|
||||||
{
|
|
||||||
using var versionStr = new Utf8StringToNative( pchVersionString );
|
|
||||||
using var interfaceVersionsStr = new Utf8StringToNative( pszInternalCheckInterfaceVersions );
|
|
||||||
using var buffer = Helpers.Memory.Take();
|
|
||||||
var result = Native.SteamInternal_GameServer_Init_V2( unIP, usGamePort, usQueryPort, eServerMode, versionStr.Pointer, interfaceVersionsStr.Pointer, buffer.Ptr );
|
|
||||||
pOutErrMsg = Helpers.MemoryToString( buffer.Ptr );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
114
Facepunch.Steamworks/Client.cs
Normal file
114
Facepunch.Steamworks/Client.cs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : BaseSteamworks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Current user's Username
|
||||||
|
/// </summary>
|
||||||
|
public string Username { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current user's SteamId
|
||||||
|
/// </summary>
|
||||||
|
public ulong SteamId { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current Beta name, if ser
|
||||||
|
/// </summary>
|
||||||
|
public string BetaName { get; private set; }
|
||||||
|
|
||||||
|
public Voice Voice { get; internal set; }
|
||||||
|
|
||||||
|
public Client( uint appId )
|
||||||
|
{
|
||||||
|
Valve.Steamworks.SteamAPIInterop.SteamAPI_Init();
|
||||||
|
|
||||||
|
native = new Interop.NativeInterface();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get other interfaces
|
||||||
|
//
|
||||||
|
if ( !native.InitClient() )
|
||||||
|
{
|
||||||
|
native.Dispose();
|
||||||
|
native = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set up warning hook callback
|
||||||
|
//
|
||||||
|
SteamAPIWarningMessageHook ptr = InternalOnWarning;
|
||||||
|
native.client.SetWarningMessageHook( Marshal.GetFunctionPointerForDelegate( ptr ) );
|
||||||
|
|
||||||
|
//
|
||||||
|
// Setup interfaces that client and server both have
|
||||||
|
//
|
||||||
|
SetupCommonInterfaces();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Client only interfaces
|
||||||
|
//
|
||||||
|
Voice = new Voice( this );
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cache common, unchanging info
|
||||||
|
//
|
||||||
|
AppId = appId;
|
||||||
|
Username = native.friends.GetPersonaName();
|
||||||
|
SteamId = native.user.GetSteamID();
|
||||||
|
BetaName = native.apps.GetCurrentBetaName();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Run update, first call does some initialization
|
||||||
|
//
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
|
||||||
|
public delegate void SteamAPIWarningMessageHook( int nSeverity, System.Text.StringBuilder pchDebugText );
|
||||||
|
|
||||||
|
private void InternalOnWarning( int nSeverity, System.Text.StringBuilder text )
|
||||||
|
{
|
||||||
|
if ( OnMessage != null )
|
||||||
|
{
|
||||||
|
OnMessage( ( MessageType)nSeverity, text.ToString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should be called at least once every frame
|
||||||
|
/// </summary>
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
if ( !IsValid )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Valve.Steamworks.SteamAPI.RunCallbacks();
|
||||||
|
|
||||||
|
Voice.Update();
|
||||||
|
|
||||||
|
base.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
if ( Voice != null )
|
||||||
|
{
|
||||||
|
Voice.Dispose();
|
||||||
|
Voice = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose();
|
||||||
|
|
||||||
|
Valve.Interop.NativeEntrypoints.Extended.SteamAPI_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
52
Facepunch.Steamworks/Client/App.cs
Normal file
52
Facepunch.Steamworks/Client/App.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : IDisposable
|
||||||
|
{
|
||||||
|
App _app;
|
||||||
|
|
||||||
|
public App App
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _app == null )
|
||||||
|
_app = new App( this );
|
||||||
|
|
||||||
|
return _app;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class App
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
internal App( Client c )
|
||||||
|
{
|
||||||
|
client = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MarkContentCorrupt( bool missingFilesOnly = false )
|
||||||
|
{
|
||||||
|
client.native.apps.MarkContentCorrupt( missingFilesOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current BuildId of the game.
|
||||||
|
/// This is pretty useless, as it isn't guarenteed to return
|
||||||
|
/// the build id you're playing, or the latest build id.
|
||||||
|
/// </summary>
|
||||||
|
public int BuildId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return client.native.apps.GetAppBuildId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
82
Facepunch.Steamworks/Client/Auth.cs
Normal file
82
Facepunch.Steamworks/Client/Auth.cs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : IDisposable
|
||||||
|
{
|
||||||
|
Auth _auth;
|
||||||
|
|
||||||
|
public Auth Auth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _auth == null )
|
||||||
|
_auth = new Auth{ client = this };
|
||||||
|
|
||||||
|
return _auth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Auth
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
public class Ticket : IDisposable
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
public byte[] Data;
|
||||||
|
public uint Handle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancels a ticket.
|
||||||
|
/// You should cancel your ticket when you close the game or leave a server.
|
||||||
|
/// </summary>
|
||||||
|
public void Cancel()
|
||||||
|
{
|
||||||
|
if ( client.IsValid && Handle != 0 )
|
||||||
|
{
|
||||||
|
client.native.user.CancelAuthTicket( Handle );
|
||||||
|
Handle = 0;
|
||||||
|
Data = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an auth ticket.
|
||||||
|
/// Which you can send to a server to authenticate that you are who you say you are.
|
||||||
|
/// </summary>
|
||||||
|
public unsafe Ticket GetAuthSessionTicket()
|
||||||
|
{
|
||||||
|
var data = new byte[1024];
|
||||||
|
|
||||||
|
fixed ( byte* b = data )
|
||||||
|
{
|
||||||
|
uint ticketLength = 0;
|
||||||
|
uint ticket = client.native.user.GetAuthSessionTicket( (IntPtr) b, data.Length, ref ticketLength );
|
||||||
|
|
||||||
|
if ( ticket == 0 )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new Ticket()
|
||||||
|
{
|
||||||
|
client = client,
|
||||||
|
Data = data.Take( (int)ticketLength ).ToArray(),
|
||||||
|
Handle = ticket
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
248
Facepunch.Steamworks/Client/Friends.cs
Normal file
248
Facepunch.Steamworks/Client/Friends.cs
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Valve.Steamworks;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : IDisposable
|
||||||
|
{
|
||||||
|
Friends _friends;
|
||||||
|
|
||||||
|
public Friends Friends
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _friends == null )
|
||||||
|
_friends = new Friends( this );
|
||||||
|
|
||||||
|
return _friends;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SteamFriend
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Steam Id
|
||||||
|
/// </summary>
|
||||||
|
public ulong Id { get; internal set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return true if blocked
|
||||||
|
/// </summary>
|
||||||
|
public bool IsBlocked { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return true if is a friend. Returns false if blocked, request etc.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsFriend { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Their current display name
|
||||||
|
/// </summary>
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this friend is online
|
||||||
|
/// </summary>
|
||||||
|
public bool IsOnline { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this friend is online and playing this game
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPlayingThisGame { get { return CurrentAppId == Client.AppId; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this friend is online and playing this game
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPlaying { get { return CurrentAppId != 0; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The AppId this guy is playing
|
||||||
|
/// </summary>
|
||||||
|
public ulong CurrentAppId { get; internal set; }
|
||||||
|
|
||||||
|
public uint ServerIp { get; internal set; }
|
||||||
|
public int ServerGamePort { get; internal set; }
|
||||||
|
public int ServerQueryPort { get; internal set; }
|
||||||
|
public ulong ServerLobbyId { get; internal set; }
|
||||||
|
|
||||||
|
internal Client Client { get; set; }
|
||||||
|
|
||||||
|
public void Refresh()
|
||||||
|
{
|
||||||
|
Name = Client.native.friends.GetFriendPersonaName( Id );
|
||||||
|
|
||||||
|
EFriendRelationship relationship = (EFriendRelationship) Client.native.friends.GetFriendRelationship( Id );
|
||||||
|
|
||||||
|
IsBlocked = relationship == EFriendRelationship.k_EFriendRelationshipBlocked;
|
||||||
|
IsFriend = relationship == EFriendRelationship.k_EFriendRelationshipFriend;
|
||||||
|
|
||||||
|
CurrentAppId = 0;
|
||||||
|
ServerIp = 0;
|
||||||
|
ServerGamePort = 0;
|
||||||
|
ServerQueryPort = 0;
|
||||||
|
ServerLobbyId = 0;
|
||||||
|
|
||||||
|
FriendGameInfo_t gameInfo = new FriendGameInfo_t();
|
||||||
|
if ( Client.native.friends.GetFriendGamePlayed( Id, out gameInfo ) && gameInfo.m_gameID > 0 )
|
||||||
|
{
|
||||||
|
CurrentAppId = gameInfo.m_gameID;
|
||||||
|
ServerIp = gameInfo.m_unGameIP;
|
||||||
|
ServerGamePort = gameInfo.m_usGamePort;
|
||||||
|
ServerQueryPort = gameInfo.m_usQueryPort;
|
||||||
|
ServerLobbyId = gameInfo.m_steamIDLobby;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Friends
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
internal Friends( Client c )
|
||||||
|
{
|
||||||
|
client = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetName( ulong steamid )
|
||||||
|
{
|
||||||
|
client.native.friends.RequestUserInformation( steamid, true );
|
||||||
|
|
||||||
|
return client.native.friends.GetFriendPersonaName( steamid );
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SteamFriend> _allFriends;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all friends, even blocked, ignored, friend requests etc
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<SteamFriend> All
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _allFriends == null )
|
||||||
|
{
|
||||||
|
_allFriends = new List<SteamFriend>();
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _allFriends;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<SteamFriend> AllFriends
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach ( var friend in All )
|
||||||
|
{
|
||||||
|
if ( !friend.IsFriend ) continue;
|
||||||
|
|
||||||
|
yield return friend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<SteamFriend> AllBlocked
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach ( var friend in All )
|
||||||
|
{
|
||||||
|
if ( !friend.IsBlocked ) continue;
|
||||||
|
|
||||||
|
yield return friend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Refresh()
|
||||||
|
{
|
||||||
|
if ( _allFriends == null )
|
||||||
|
{
|
||||||
|
_allFriends = new List<SteamFriend>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_allFriends.Clear();
|
||||||
|
|
||||||
|
var flags = (int) EFriendFlags.k_EFriendFlagAll;
|
||||||
|
var count = client.native.friends.GetFriendCount( flags );
|
||||||
|
|
||||||
|
for ( int i=0; i<count; i++ )
|
||||||
|
{
|
||||||
|
var steamid = client.native.friends.GetFriendByIndex( i, flags );
|
||||||
|
_allFriends.Add( Get( steamid ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AvatarSize
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Should be 32x32 - but make sure to check!
|
||||||
|
/// </summary>
|
||||||
|
Small,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should be 64x64 - but make sure to check!
|
||||||
|
/// </summary>
|
||||||
|
Medium,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should be 184x184 - but make sure to check!
|
||||||
|
/// </summary>
|
||||||
|
Large
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image GetAvatar( AvatarSize size, ulong steamid )
|
||||||
|
{
|
||||||
|
var imageid = 0;
|
||||||
|
|
||||||
|
switch ( size )
|
||||||
|
{
|
||||||
|
case AvatarSize.Small:
|
||||||
|
imageid = client.native.friends.GetSmallFriendAvatar( steamid );
|
||||||
|
break;
|
||||||
|
case AvatarSize.Medium:
|
||||||
|
imageid = client.native.friends.GetMediumFriendAvatar( steamid );
|
||||||
|
break;
|
||||||
|
case AvatarSize.Large:
|
||||||
|
imageid = client.native.friends.GetLargeFriendAvatar( steamid );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var img = new Image()
|
||||||
|
{
|
||||||
|
Id = imageid
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( imageid == 0 )
|
||||||
|
return img;
|
||||||
|
|
||||||
|
if ( img.TryLoad( client.native.utils ) )
|
||||||
|
return img;
|
||||||
|
|
||||||
|
throw new System.NotImplementedException( "Deferred Avatar Loading Todo" );
|
||||||
|
// Add to image loading list
|
||||||
|
|
||||||
|
//return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SteamFriend Get( ulong steamid )
|
||||||
|
{
|
||||||
|
var f = new SteamFriend()
|
||||||
|
{
|
||||||
|
Id = steamid,
|
||||||
|
Client = client
|
||||||
|
};
|
||||||
|
|
||||||
|
f.Refresh();
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
81
Facepunch.Steamworks/Client/Image.cs
Normal file
81
Facepunch.Steamworks/Client/Image.cs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Valve.Steamworks;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public class Image
|
||||||
|
{
|
||||||
|
public int Id { get; internal set; }
|
||||||
|
public int Width { get; internal set; }
|
||||||
|
public int Height { get; internal set; }
|
||||||
|
|
||||||
|
public byte[] Data { get; internal set; }
|
||||||
|
|
||||||
|
public bool IsLoaded { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return true if this image couldn't be loaded for some reason
|
||||||
|
/// </summary>
|
||||||
|
public bool IsError { get; internal set; }
|
||||||
|
|
||||||
|
unsafe internal bool TryLoad( ISteamUtils utils )
|
||||||
|
{
|
||||||
|
if ( IsLoaded ) return true;
|
||||||
|
|
||||||
|
uint width = 0, height = 0;
|
||||||
|
|
||||||
|
if ( utils.GetImageSize( Id, ref width, ref height ) == false )
|
||||||
|
{
|
||||||
|
IsError = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var buffer = new byte[ width * height * 4 ];
|
||||||
|
|
||||||
|
fixed ( byte* ptr = buffer )
|
||||||
|
{
|
||||||
|
if ( utils.GetImageRGBA( Id, (IntPtr) ptr, buffer.Length ) == false )
|
||||||
|
{
|
||||||
|
IsError = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Width = (int) width;
|
||||||
|
Height = (int) height;
|
||||||
|
Data = buffer;
|
||||||
|
IsLoaded = true;
|
||||||
|
IsError = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color GetPixel( int x, int y )
|
||||||
|
{
|
||||||
|
if ( !IsLoaded ) throw new System.Exception( "Image not loaded" );
|
||||||
|
if ( x < 0 || x >= Width ) throw new System.Exception( "x out of bounds" );
|
||||||
|
if ( y < 0 || y >= Height ) throw new System.Exception( "y out of bounds" );
|
||||||
|
|
||||||
|
Color c = new Color();
|
||||||
|
|
||||||
|
var i = ( y * Width + x ) * 4;
|
||||||
|
|
||||||
|
c.r = Data[i + 0];
|
||||||
|
c.g = Data[i + 1];
|
||||||
|
c.b = Data[i + 2];
|
||||||
|
c.a = Data[i + 3];
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Color
|
||||||
|
{
|
||||||
|
public byte r, g, b, a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
42
Facepunch.Steamworks/Client/Overlay.cs
Normal file
42
Facepunch.Steamworks/Client/Overlay.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : IDisposable
|
||||||
|
{
|
||||||
|
private Overlay _overlay;
|
||||||
|
|
||||||
|
public Overlay Overlay
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _overlay == null )
|
||||||
|
_overlay = new Overlay { client = this };
|
||||||
|
|
||||||
|
return _overlay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Overlay
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
public void OpenUserPage( string name, ulong steamid ) { client.native.friends.ActivateGameOverlayToUser( name, steamid ); }
|
||||||
|
|
||||||
|
public void OpenProfile( ulong steamid ) { OpenUserPage( "steamid", steamid ); }
|
||||||
|
public void OpenChat( ulong steamid ){ OpenUserPage( "chat", steamid ); }
|
||||||
|
public void OpenTrade( ulong steamid ) { OpenUserPage( "jointrade", steamid ); }
|
||||||
|
public void OpenStats( ulong steamid ) { OpenUserPage( "stats", steamid ); }
|
||||||
|
public void OpenAchievements( ulong steamid ) { OpenUserPage( "achievements", steamid ); }
|
||||||
|
public void AddFriend( ulong steamid ) { OpenUserPage( "friendadd", steamid ); }
|
||||||
|
public void RemoveFriend( ulong steamid ) { OpenUserPage( "friendremove", steamid ); }
|
||||||
|
public void AcceptFriendRequest( ulong steamid ) { OpenUserPage( "friendrequestaccept", steamid ); }
|
||||||
|
public void IgnoreFriendRequest( ulong steamid ) { OpenUserPage( "friendrequestignore", steamid ); }
|
||||||
|
|
||||||
|
public void OpenUrl( string url ) { client.native.friends.ActivateGameOverlayToWebPage( url ); }
|
||||||
|
}
|
||||||
|
}
|
39
Facepunch.Steamworks/Client/Screenshots.cs
Normal file
39
Facepunch.Steamworks/Client/Screenshots.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : IDisposable
|
||||||
|
{
|
||||||
|
Screenshots _screenshots;
|
||||||
|
|
||||||
|
public Screenshots Screenshots
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _screenshots == null )
|
||||||
|
_screenshots = new Screenshots( this );
|
||||||
|
|
||||||
|
return _screenshots;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Screenshots
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
internal Screenshots( Client c )
|
||||||
|
{
|
||||||
|
client = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Trigger()
|
||||||
|
{
|
||||||
|
client.native.screenshots.TriggerScreenshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
105
Facepunch.Steamworks/Client/Server.cs
Normal file
105
Facepunch.Steamworks/Client/Server.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using Valve.Steamworks;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public class Server
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
internal Server( Client c )
|
||||||
|
{
|
||||||
|
client = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Ping { get; set; }
|
||||||
|
public string GameDir { get; set; }
|
||||||
|
public string Map { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public uint AppId { get; set; }
|
||||||
|
public int Players { get; set; }
|
||||||
|
public int MaxPlayers { get; set; }
|
||||||
|
public int BotPlayers { get; set; }
|
||||||
|
public bool Passworded { get; set; }
|
||||||
|
public bool Secure { get; set; }
|
||||||
|
public uint LastTimePlayed { get; set; }
|
||||||
|
public int Version { get; set; }
|
||||||
|
public string[] Tags { get; set; }
|
||||||
|
public ulong SteamId { get; set; }
|
||||||
|
|
||||||
|
public uint Address { get; set; }
|
||||||
|
|
||||||
|
public int ConnectionPort { get; set; }
|
||||||
|
|
||||||
|
public int QueryPort { get; set; }
|
||||||
|
|
||||||
|
public string AddressString
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format( "{0}.{1}.{2}.{3}", ( Address >> 24 ) & 0xFFul, ( Address >> 16 ) & 0xFFul, ( Address >> 8 ) & 0xFFul, Address & 0xFFul );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string ConnectionAddress
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format( "{0}.{1}.{2}.{3}:{4}", ( Address >> 24 ) & 0xFFul, ( Address >> 16 ) & 0xFFul, ( Address >> 8 ) & 0xFFul, Address & 0xFFul, ConnectionPort );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Server FromSteam( Client c, gameserveritem_t item )
|
||||||
|
{
|
||||||
|
return new Server( c )
|
||||||
|
{
|
||||||
|
Address = item.m_NetAdr.m_unIP,
|
||||||
|
ConnectionPort = item.m_NetAdr.m_usConnectionPort,
|
||||||
|
QueryPort = item.m_NetAdr.m_usQueryPort,
|
||||||
|
Name = item.m_szServerName,
|
||||||
|
Ping = item.m_nPing,
|
||||||
|
GameDir = item.m_szGameDir,
|
||||||
|
Map = item.m_szMap,
|
||||||
|
Description = item.m_szGameDescription,
|
||||||
|
AppId = item.m_nAppID,
|
||||||
|
Players = item.m_nPlayers,
|
||||||
|
MaxPlayers = item.m_nMaxPlayers,
|
||||||
|
BotPlayers = item.m_nBotPlayers,
|
||||||
|
Passworded = item.m_bPassword,
|
||||||
|
Secure = item.m_bSecure,
|
||||||
|
LastTimePlayed = item.m_ulTimeLastPlayed,
|
||||||
|
Version = item.m_nServerVersion,
|
||||||
|
Tags = item.m_szGameTags == null ? null : item.m_szGameTags.Split( ',' ),
|
||||||
|
SteamId = item.m_steamID
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, string> Rules;
|
||||||
|
public Action OnServerRules;
|
||||||
|
|
||||||
|
public void UpdateRules()
|
||||||
|
{
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// TEMPORARY, WE NEED TO WRITE OUR OWN VERSION OF THIS, DOESN'T WORK ON SPLIT PACKETS ETC
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
using ( var q = new SourceServerQuery( AddressString, ConnectionPort ) )
|
||||||
|
{
|
||||||
|
Rules = q.GetRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( OnServerRules != null && Rules != null )
|
||||||
|
OnServerRules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
215
Facepunch.Steamworks/Client/ServerList.Request.cs
Normal file
215
Facepunch.Steamworks/Client/ServerList.Request.cs
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using Valve.Steamworks;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class ServerList
|
||||||
|
{
|
||||||
|
public class Request : IDisposable
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
internal List<SubRequest> Requests = new List<SubRequest>();
|
||||||
|
|
||||||
|
internal class SubRequest
|
||||||
|
{
|
||||||
|
internal IntPtr Request;
|
||||||
|
internal int Pointer = 0;
|
||||||
|
internal List<int> WatchList = new List<int>();
|
||||||
|
|
||||||
|
internal bool Update( ISteamMatchmakingServers servers, Action<gameserveritem_t> OnServer, Action OnUpdate )
|
||||||
|
{
|
||||||
|
if ( Request == IntPtr.Zero )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool changes = false;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add any servers we're not watching to our watch list
|
||||||
|
//
|
||||||
|
var count = servers.GetServerCount( Request );
|
||||||
|
if ( count != Pointer )
|
||||||
|
{
|
||||||
|
for ( int i = Pointer; i < count; i++ )
|
||||||
|
{
|
||||||
|
WatchList.Add( i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pointer = count;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Remove any servers that respond successfully
|
||||||
|
//
|
||||||
|
WatchList.RemoveAll( x =>
|
||||||
|
{
|
||||||
|
var info = servers.GetServerDetails( Request, x );
|
||||||
|
if ( info.m_bHadSuccessfulResponse )
|
||||||
|
{
|
||||||
|
OnServer( info );
|
||||||
|
changes = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
|
||||||
|
//
|
||||||
|
// If we've finished refreshing
|
||||||
|
//
|
||||||
|
if ( servers.IsRefreshing( Request ) == false )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Put any other servers on the 'no response' list
|
||||||
|
//
|
||||||
|
WatchList.RemoveAll( x =>
|
||||||
|
{
|
||||||
|
var info = servers.GetServerDetails( Request, x );
|
||||||
|
OnServer( info );
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
|
||||||
|
servers.CancelQuery( Request );
|
||||||
|
Request = IntPtr.Zero;
|
||||||
|
changes = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( changes && OnUpdate != null )
|
||||||
|
OnUpdate();
|
||||||
|
|
||||||
|
return Request == IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action OnUpdate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of servers that responded. If you're only interested in servers that responded since you
|
||||||
|
/// last updated, then simply clear this list.
|
||||||
|
/// </summary>
|
||||||
|
public List<Server> Responded = new List<Server>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of servers that were in the master list but didn't respond.
|
||||||
|
/// </summary>
|
||||||
|
public List<Server> Unresponsive = new List<Server>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True when we have finished
|
||||||
|
/// </summary>
|
||||||
|
public bool Finished = false;
|
||||||
|
|
||||||
|
internal Request( Client c )
|
||||||
|
{
|
||||||
|
client = c;
|
||||||
|
|
||||||
|
client.OnUpdate += Update;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Request()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IEnumerable<string> ServerList { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
internal void StartCustomQuery()
|
||||||
|
{
|
||||||
|
if ( ServerList == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int blockSize = 16;
|
||||||
|
int Pointer = 0;
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
var sublist = ServerList.Skip( Pointer ).Take( blockSize );
|
||||||
|
|
||||||
|
if ( sublist.Count() == 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
Pointer += sublist.Count();
|
||||||
|
|
||||||
|
var filter = new Filter();
|
||||||
|
filter.Add( "or", sublist.Count().ToString() );
|
||||||
|
|
||||||
|
foreach ( var server in sublist )
|
||||||
|
{
|
||||||
|
filter.Add( "gameaddr", server );
|
||||||
|
}
|
||||||
|
|
||||||
|
filter.Start();
|
||||||
|
var id = client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, filter.Count, IntPtr.Zero );
|
||||||
|
filter.Free();
|
||||||
|
|
||||||
|
AddRequest( id );
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerList = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddRequest( IntPtr id )
|
||||||
|
{
|
||||||
|
Requests.Add( new SubRequest() { Request = id } );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if ( Requests.Count == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( int i=0; i< Requests.Count(); i++ )
|
||||||
|
{
|
||||||
|
if ( Requests[i].Update( client.native.servers, OnServer, OnUpdate ) )
|
||||||
|
{
|
||||||
|
Requests.RemoveAt( i );
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Requests.Count == 0 )
|
||||||
|
{
|
||||||
|
Finished = true;
|
||||||
|
client.OnUpdate -= Update;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnServer( gameserveritem_t info )
|
||||||
|
{
|
||||||
|
if ( info.m_bHadSuccessfulResponse )
|
||||||
|
{
|
||||||
|
Responded.Add( Server.FromSteam( client, info ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Unresponsive.Add( Server.FromSteam( client, info ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposing will end the query
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
client.OnUpdate -= Update;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cancel the query if it's still running
|
||||||
|
//
|
||||||
|
foreach( var subRequest in Requests )
|
||||||
|
{
|
||||||
|
if ( client.IsValid )
|
||||||
|
client.native.servers.CancelQuery( subRequest.Request );
|
||||||
|
}
|
||||||
|
Requests.Clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
Facepunch.Steamworks/Client/ServerList.Server.cs
Normal file
117
Facepunch.Steamworks/Client/ServerList.Server.cs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using Valve.Steamworks;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class ServerList
|
||||||
|
{
|
||||||
|
public class Server
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Ping { get; set; }
|
||||||
|
public string GameDir { get; set; }
|
||||||
|
public string Map { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public uint AppId { get; set; }
|
||||||
|
public int Players { get; set; }
|
||||||
|
public int MaxPlayers { get; set; }
|
||||||
|
public int BotPlayers { get; set; }
|
||||||
|
public bool Passworded { get; set; }
|
||||||
|
public bool Secure { get; set; }
|
||||||
|
public uint LastTimePlayed { get; set; }
|
||||||
|
public int Version { get; set; }
|
||||||
|
public string[] Tags { get; set; }
|
||||||
|
public ulong SteamId { get; set; }
|
||||||
|
public uint Address { get; set; }
|
||||||
|
public int ConnectionPort { get; set; }
|
||||||
|
public int QueryPort { get; set; }
|
||||||
|
|
||||||
|
internal Client Client;
|
||||||
|
|
||||||
|
public string AddressString
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format( "{0}.{1}.{2}.{3}", ( Address >> 24 ) & 0xFFul, ( Address >> 16 ) & 0xFFul, ( Address >> 8 ) & 0xFFul, Address & 0xFFul );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string ConnectionAddress
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format( "{0}.{1}.{2}.{3}:{4}", ( Address >> 24 ) & 0xFFul, ( Address >> 16 ) & 0xFFul, ( Address >> 8 ) & 0xFFul, Address & 0xFFul, ConnectionPort );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Server FromSteam( Client client, gameserveritem_t item )
|
||||||
|
{
|
||||||
|
return new Server()
|
||||||
|
{
|
||||||
|
Client = client,
|
||||||
|
Address = item.m_NetAdr.m_unIP,
|
||||||
|
ConnectionPort = item.m_NetAdr.m_usConnectionPort,
|
||||||
|
QueryPort = item.m_NetAdr.m_usQueryPort,
|
||||||
|
Name = item.m_szServerName,
|
||||||
|
Ping = item.m_nPing,
|
||||||
|
GameDir = item.m_szGameDir,
|
||||||
|
Map = item.m_szMap,
|
||||||
|
Description = item.m_szGameDescription,
|
||||||
|
AppId = item.m_nAppID,
|
||||||
|
Players = item.m_nPlayers,
|
||||||
|
MaxPlayers = item.m_nMaxPlayers,
|
||||||
|
BotPlayers = item.m_nBotPlayers,
|
||||||
|
Passworded = item.m_bPassword,
|
||||||
|
Secure = item.m_bSecure,
|
||||||
|
LastTimePlayed = item.m_ulTimeLastPlayed,
|
||||||
|
Version = item.m_nServerVersion,
|
||||||
|
Tags = item.m_szGameTags == null ? null : item.m_szGameTags.Split( ',' ),
|
||||||
|
SteamId = item.m_steamID
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback when rules are receieved.
|
||||||
|
/// The bool is true if server responded properly.
|
||||||
|
/// </summary>
|
||||||
|
public Action<bool> OnReceivedRules;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of server rules. Use HasRules to see if this is safe to access.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, string> Rules;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this server has rules
|
||||||
|
/// </summary>
|
||||||
|
public bool HasRules { get { return Rules != null && Rules.Count > 0; } }
|
||||||
|
|
||||||
|
internal Interop.ServerRules RulesRequest;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates Rules for this server
|
||||||
|
/// </summary>
|
||||||
|
public void FetchRules()
|
||||||
|
{
|
||||||
|
if ( RulesRequest != null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Rules = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
RulesRequest = new Interop.ServerRules( this, Address, QueryPort );
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnServerRulesReceiveFinished( bool Success )
|
||||||
|
{
|
||||||
|
RulesRequest.Dispose();
|
||||||
|
RulesRequest = null;
|
||||||
|
|
||||||
|
if ( OnReceivedRules != null )
|
||||||
|
OnReceivedRules( Success );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
157
Facepunch.Steamworks/Client/ServerList.cs
Normal file
157
Facepunch.Steamworks/Client/ServerList.cs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using Valve.Steamworks;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : IDisposable
|
||||||
|
{
|
||||||
|
private ServerList _serverlist;
|
||||||
|
|
||||||
|
public ServerList ServerList
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _serverlist == null )
|
||||||
|
_serverlist = new ServerList { client = this };
|
||||||
|
|
||||||
|
return _serverlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class ServerList
|
||||||
|
{
|
||||||
|
|
||||||
|
public class Filter : List<KeyValuePair<string, string>>
|
||||||
|
{
|
||||||
|
public void Add( string k, string v )
|
||||||
|
{
|
||||||
|
Add( new KeyValuePair<string, string>( k, v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IntPtr NativeArray;
|
||||||
|
private IntPtr m_pArrayEntries;
|
||||||
|
|
||||||
|
internal void Start()
|
||||||
|
{
|
||||||
|
var filters = this.Select( x =>
|
||||||
|
{
|
||||||
|
return new MatchMakingKeyValuePair_t()
|
||||||
|
{
|
||||||
|
m_szKey = x.Key,
|
||||||
|
m_szValue = x.Value
|
||||||
|
};
|
||||||
|
|
||||||
|
} ).ToArray();
|
||||||
|
|
||||||
|
int sizeOfMMKVP = Marshal.SizeOf(typeof(MatchMakingKeyValuePair_t));
|
||||||
|
NativeArray = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( IntPtr ) ) * filters.Length );
|
||||||
|
m_pArrayEntries = Marshal.AllocHGlobal( sizeOfMMKVP * filters.Length );
|
||||||
|
|
||||||
|
for ( int i = 0; i < filters.Length; ++i )
|
||||||
|
{
|
||||||
|
Marshal.StructureToPtr( filters[i], new IntPtr( m_pArrayEntries.ToInt64() + ( i * sizeOfMMKVP ) ), false );
|
||||||
|
}
|
||||||
|
|
||||||
|
Marshal.WriteIntPtr( NativeArray, m_pArrayEntries );
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Free()
|
||||||
|
{
|
||||||
|
if ( m_pArrayEntries != IntPtr.Zero )
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal( m_pArrayEntries );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( NativeArray != IntPtr.Zero )
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal( NativeArray );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
|
private struct MatchPair
|
||||||
|
{
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
|
public string key;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
|
public string value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request Internet( Filter filter )
|
||||||
|
{
|
||||||
|
filter.Start();
|
||||||
|
|
||||||
|
var request = new Request( client );
|
||||||
|
request.AddRequest( client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, filter.Count, IntPtr.Zero ) );
|
||||||
|
|
||||||
|
filter.Free();
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request Custom( IEnumerable<string> serverList )
|
||||||
|
{
|
||||||
|
var request = new Request( client );
|
||||||
|
request.ServerList = serverList;
|
||||||
|
request.StartCustomQuery();
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// History filters don't seem to work, so we don't bother.
|
||||||
|
/// You should apply them post process'dly
|
||||||
|
/// </summary>
|
||||||
|
public Request History()
|
||||||
|
{
|
||||||
|
var request = new Request( client );
|
||||||
|
request.AddRequest( client.native.servers.RequestHistoryServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero ) );
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Favourite filters don't seem to work, so we don't bother.
|
||||||
|
/// You should apply them post process'dly
|
||||||
|
/// </summary>
|
||||||
|
public Request Favourites()
|
||||||
|
{
|
||||||
|
var request = new Request( client );
|
||||||
|
request.AddRequest( client.native.servers.RequestFavoritesServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero ) );
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddToHistory( Server server )
|
||||||
|
{
|
||||||
|
// client.native.matchmaking
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveFromHistory( Server server )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddToFavourite( Server server )
|
||||||
|
{
|
||||||
|
// client.native.matchmaking
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveFromFavourite( Server server )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsFavourite( Server server )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
509
Facepunch.Steamworks/Client/ServerQuery.cs
Normal file
509
Facepunch.Steamworks/Client/ServerQuery.cs
Normal file
@ -0,0 +1,509 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
internal class SourceServerQuery :IDisposable
|
||||||
|
{
|
||||||
|
public class PlayersResponse
|
||||||
|
{
|
||||||
|
public short player_count;
|
||||||
|
public List<Player> players = new List<Player>();
|
||||||
|
|
||||||
|
public class Player
|
||||||
|
{
|
||||||
|
public String name { get; set; }
|
||||||
|
public int score { get; set; }
|
||||||
|
public float playtime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPEndPoint endPoint;
|
||||||
|
|
||||||
|
private Socket socket;
|
||||||
|
private UdpClient client;
|
||||||
|
|
||||||
|
// send & receive timeouts
|
||||||
|
private int send_timeout = 2500;
|
||||||
|
private int receive_timeout = 2500;
|
||||||
|
|
||||||
|
// raw response returned from the server
|
||||||
|
private byte[] raw_data;
|
||||||
|
|
||||||
|
private int offset = 0;
|
||||||
|
|
||||||
|
// constants
|
||||||
|
private readonly byte[] FFFFFFFF = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||||
|
|
||||||
|
public SourceServerQuery( String ip, int port )
|
||||||
|
{
|
||||||
|
this.endPoint = new IPEndPoint( IPAddress.Parse( ip ), port );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a list of currently in-game clients on the specified gameserver.
|
||||||
|
/// <b>Please note:</b> the playtime is stored as a float in <i>seconds</i>, you might want to convert it.
|
||||||
|
///
|
||||||
|
/// See https://developer.valvesoftware.com/wiki/Server_queries#A2S_PLAYER for more Information
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A PLayersResponse Object containing the name, score and playtime of each player</returns>
|
||||||
|
public PlayersResponse GetPlayerList()
|
||||||
|
{
|
||||||
|
// open socket if not already open
|
||||||
|
this.GetSocket();
|
||||||
|
// we don't need the header, so set pointer to where the payload begins
|
||||||
|
this.offset = 5;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PlayersResponse pr = new PlayersResponse();
|
||||||
|
|
||||||
|
// since A2S_PLAYER requests require a valid challenge, get it first
|
||||||
|
byte[] challenge = this.GetChallenge(0x55, true);
|
||||||
|
|
||||||
|
byte[] request = new byte[challenge.Length + this.FFFFFFFF.Length + 1];
|
||||||
|
Array.Copy( this.FFFFFFFF, 0, request, 0, this.FFFFFFFF.Length );
|
||||||
|
request[this.FFFFFFFF.Length] = 0x55;
|
||||||
|
Array.Copy( challenge, 0, request, this.FFFFFFFF.Length + 1, challenge.Length );
|
||||||
|
|
||||||
|
this.socket.Send( request );
|
||||||
|
|
||||||
|
// MODIFIED BY ZACKBOE
|
||||||
|
// Increased byte size from 1024 in order to receive more player data
|
||||||
|
// Previously returned a socket exception at >~ 51 players.
|
||||||
|
this.raw_data = new byte[2048];
|
||||||
|
// END MODIFICATION
|
||||||
|
this.socket.Receive( this.raw_data );
|
||||||
|
|
||||||
|
byte player_count = this.ReadByte();
|
||||||
|
|
||||||
|
// fill up the list of players
|
||||||
|
for ( int i = 0; i < player_count; i++ )
|
||||||
|
{
|
||||||
|
this.ReadByte();
|
||||||
|
|
||||||
|
PlayersResponse.Player p = new PlayersResponse.Player();
|
||||||
|
|
||||||
|
p.name = this.ReadString();
|
||||||
|
p.score = this.ReadInt32();
|
||||||
|
p.playtime = this.ReadFloat();
|
||||||
|
|
||||||
|
pr.players.Add( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
pr.player_count = player_count;
|
||||||
|
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
catch ( SocketException e )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a list of all publically available CVars ("rules") from the server.
|
||||||
|
/// <b>Note:</b> Due to a bug in the Source Engine, it might happen that some CVars/values are cut off.
|
||||||
|
///
|
||||||
|
/// Example: mp_idlemaxtime = [nothing]
|
||||||
|
/// Only Valve can fix that.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A RulesResponse Object containing a Name-Value pair of each CVar</returns>
|
||||||
|
public Dictionary<string, string> GetRules()
|
||||||
|
{
|
||||||
|
// open udpclient if not already open
|
||||||
|
this.GetClient();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var d = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
// similar to A2S_PLAYER requests, A2S_RULES require a valid challenge
|
||||||
|
byte[] challenge = this.GetChallenge(0x56, false);
|
||||||
|
|
||||||
|
byte[] request = new byte[challenge.Length + this.FFFFFFFF.Length + 1];
|
||||||
|
Array.Copy( this.FFFFFFFF, 0, request, 0, this.FFFFFFFF.Length );
|
||||||
|
request[this.FFFFFFFF.Length] = 0x56;
|
||||||
|
Array.Copy( challenge, 0, request, this.FFFFFFFF.Length + 1, challenge.Length );
|
||||||
|
|
||||||
|
this.client.Send( request, request.Length );
|
||||||
|
|
||||||
|
//
|
||||||
|
// Since A2S_RULES responses might be split up into several packages/compressed, we have to do a special handling of them
|
||||||
|
//
|
||||||
|
int bytesRead;
|
||||||
|
|
||||||
|
// this will keep our assembled message
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
|
||||||
|
// send first request
|
||||||
|
|
||||||
|
this.raw_data = this.client.Receive( ref this.endPoint );
|
||||||
|
|
||||||
|
bytesRead = this.raw_data.Length;
|
||||||
|
|
||||||
|
// reset pointer
|
||||||
|
this.offset = 0;
|
||||||
|
|
||||||
|
int is_split = this.ReadInt32();
|
||||||
|
int requestid = this.ReadInt32();
|
||||||
|
|
||||||
|
this.offset = 4;
|
||||||
|
|
||||||
|
// response is split up into several packets
|
||||||
|
if ( this.PacketIsSplit( is_split ) )
|
||||||
|
{
|
||||||
|
bool isCompressed = false;
|
||||||
|
byte[] splitData;
|
||||||
|
int packetCount, packetNumber, requestId;
|
||||||
|
int packetsReceived = 1;
|
||||||
|
int packetChecksum = 0;
|
||||||
|
int packetSplit = 0;
|
||||||
|
short splitSize;
|
||||||
|
int uncompressedSize = 0;
|
||||||
|
List<byte[]> splitPackets = new List<byte[]>();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// unique request id
|
||||||
|
requestId = this.ReverseBytes( this.ReadInt32() );
|
||||||
|
isCompressed = this.PacketIsCompressed( requestId );
|
||||||
|
|
||||||
|
packetCount = this.ReadByte();
|
||||||
|
packetNumber = this.ReadByte() + 1;
|
||||||
|
// so we know how big our byte arrays have to be
|
||||||
|
splitSize = this.ReadInt16();
|
||||||
|
splitSize -= 4; // fix
|
||||||
|
|
||||||
|
if ( packetsReceived == 1 )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < packetCount; i++ )
|
||||||
|
{
|
||||||
|
splitPackets.Add( new byte[] { } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the packets are compressed, get some data to decompress them
|
||||||
|
if ( isCompressed )
|
||||||
|
{
|
||||||
|
uncompressedSize = ReverseBytes( this.ReadInt32() );
|
||||||
|
packetChecksum = ReverseBytes( this.ReadInt32() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ommit header in first packet
|
||||||
|
if ( packetNumber == 1 ) this.ReadInt32();
|
||||||
|
|
||||||
|
splitData = new byte[splitSize];
|
||||||
|
splitPackets[packetNumber - 1] = this.ReadBytes();
|
||||||
|
|
||||||
|
// fixes a case where the returned package might still contain a character after the last \0 terminator (truncated name => value)
|
||||||
|
// please note: this therefore also removes the value of said variable, but atleast the program won't crash
|
||||||
|
if ( splitPackets[packetNumber - 1].Length - 1 > 0 && splitPackets[packetNumber - 1][splitPackets[packetNumber - 1].Length - 1] != 0x00 )
|
||||||
|
{
|
||||||
|
splitPackets[packetNumber - 1][splitPackets[packetNumber - 1].Length - 1] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset pointer again, so we can copy over the contents
|
||||||
|
this.offset = 0;
|
||||||
|
|
||||||
|
if ( packetsReceived < packetCount )
|
||||||
|
{
|
||||||
|
|
||||||
|
this.raw_data = this.client.Receive( ref this.endPoint );
|
||||||
|
bytesRead = this.raw_data.Length;
|
||||||
|
|
||||||
|
// continue with the next packets
|
||||||
|
packetSplit = this.ReadInt32();
|
||||||
|
packetsReceived++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// all packets received
|
||||||
|
bytesRead = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ( packetsReceived <= packetCount && bytesRead > 0 && packetSplit == -2 );
|
||||||
|
|
||||||
|
// decompress
|
||||||
|
if ( isCompressed )
|
||||||
|
{
|
||||||
|
buffer = ReassemblePacket( splitPackets, true, uncompressedSize, packetChecksum );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer = ReassemblePacket( splitPackets, false, 0, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer = this.raw_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// move our final result over to handle it
|
||||||
|
this.raw_data = buffer;
|
||||||
|
|
||||||
|
// omitting header
|
||||||
|
this.offset += 1;
|
||||||
|
var count = this.ReadInt16();
|
||||||
|
|
||||||
|
for ( int i = 0; i < count; i++ )
|
||||||
|
{
|
||||||
|
var k = this.ReadString();
|
||||||
|
var v = this.ReadString();
|
||||||
|
|
||||||
|
if ( !d.ContainsKey( k ) )
|
||||||
|
d.Add( k, v );
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
catch ( SocketException e )
|
||||||
|
{
|
||||||
|
Console.WriteLine( e );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Close all currently open socket/UdpClient connections
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if ( this.socket != null ) this.socket.Close();
|
||||||
|
if ( this.client != null ) this.client.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open up a new Socket-based connection to a server, if not already open.
|
||||||
|
/// </summary>
|
||||||
|
private void GetSocket()
|
||||||
|
{
|
||||||
|
if ( this.socket == null )
|
||||||
|
{
|
||||||
|
this.socket = new Socket(
|
||||||
|
AddressFamily.InterNetwork,
|
||||||
|
SocketType.Dgram,
|
||||||
|
ProtocolType.Udp );
|
||||||
|
|
||||||
|
this.socket.SendTimeout = this.send_timeout;
|
||||||
|
this.socket.ReceiveTimeout = this.receive_timeout;
|
||||||
|
|
||||||
|
this.socket.Connect( this.endPoint );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new UdpClient connection to a server (mostly used for multi-packet answers)
|
||||||
|
/// </summary>
|
||||||
|
private void GetClient()
|
||||||
|
{
|
||||||
|
if ( this.client == null )
|
||||||
|
{
|
||||||
|
this.client = new UdpClient();
|
||||||
|
this.client.Connect( this.endPoint );
|
||||||
|
this.client.DontFragment = true;
|
||||||
|
|
||||||
|
this.client.Client.SendTimeout = this.send_timeout;
|
||||||
|
this.client.Client.ReceiveTimeout = this.receive_timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reassmble a multi-packet response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="splitPackets">The packets to assemble</param>
|
||||||
|
/// <param name="isCompressed">true: packets are compressed; false: not</param>
|
||||||
|
/// <param name="uncompressedSize">The size of the message after decompression (for comparison)</param>
|
||||||
|
/// <param name="packetChecksum">Validation of the result</param>
|
||||||
|
/// <returns>A byte-array containing all packets assembled together/decompressed.</returns>
|
||||||
|
private byte[] ReassemblePacket( List<byte[]> splitPackets, bool isCompressed, int uncompressedSize, int packetChecksum )
|
||||||
|
{
|
||||||
|
byte[] packetData, tmpData;
|
||||||
|
packetData = new byte[0];
|
||||||
|
|
||||||
|
foreach ( byte[] splitPacket in splitPackets )
|
||||||
|
{
|
||||||
|
if ( splitPacket == null )
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpData = packetData;
|
||||||
|
packetData = new byte[tmpData.Length + splitPacket.Length];
|
||||||
|
|
||||||
|
MemoryStream memStream = new MemoryStream(packetData);
|
||||||
|
memStream.Write( tmpData, 0, tmpData.Length );
|
||||||
|
memStream.Write( splitPacket, 0, splitPacket.Length );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isCompressed )
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return packetData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invert the Byte-order Mark of an value, used for compatibility between Little <-> Large BOM
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to invert</param>
|
||||||
|
/// <returns>BOM-inversed value (if needed), otherwise the original value</returns>
|
||||||
|
private int ReverseBytes( int value )
|
||||||
|
{
|
||||||
|
byte[] bytes = BitConverter.GetBytes(value);
|
||||||
|
if ( BitConverter.IsLittleEndian )
|
||||||
|
{
|
||||||
|
Array.Reverse( bytes );
|
||||||
|
}
|
||||||
|
return BitConverter.ToInt32( bytes, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine whetever or not a message is compressed.
|
||||||
|
/// Simply detects if the most significant bit is 1.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to check</param>
|
||||||
|
/// <returns>true, if message is compressed, false otherwise</returns>
|
||||||
|
private bool PacketIsCompressed( int value )
|
||||||
|
{
|
||||||
|
return ( value & 0x8000 ) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine whetever or not a message is split up.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="paket">The value to check</param>
|
||||||
|
/// <returns>true, if message is split up, false otherwise</returns>
|
||||||
|
private bool PacketIsSplit( int paket )
|
||||||
|
{
|
||||||
|
return ( paket == -2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request the 4-byte challenge id from the server, required for A2S_RULES and A2S_PLAYER.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type of message to request the challenge for (see constants)</param>
|
||||||
|
/// <param name="socket">Request method to use (performance reasons)</param>
|
||||||
|
/// <returns>A Byte Array (4-bytes) containing the challenge</returns>
|
||||||
|
private Byte[] GetChallenge( byte type, bool socket = true )
|
||||||
|
{
|
||||||
|
byte[] request = new byte[this.FFFFFFFF.Length + this.FFFFFFFF.Length + 1];
|
||||||
|
Array.Copy( this.FFFFFFFF, 0, request, 0, this.FFFFFFFF.Length );
|
||||||
|
request[FFFFFFFF.Length] = type;
|
||||||
|
Array.Copy( this.FFFFFFFF, 0, request, this.FFFFFFFF.Length + 1, this.FFFFFFFF.Length );
|
||||||
|
|
||||||
|
byte[] raw_response = new byte[24];
|
||||||
|
byte[] challenge = new byte[4];
|
||||||
|
|
||||||
|
// using sockets
|
||||||
|
if ( socket )
|
||||||
|
{
|
||||||
|
this.socket.Send( request );
|
||||||
|
this.socket.Receive( raw_response );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.client.Send( request, request.Length );
|
||||||
|
raw_response = this.client.Receive( ref this.endPoint );
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.Copy( raw_response, 5, challenge, 0, 4 ); // change this valve modifies the protocol!
|
||||||
|
|
||||||
|
return challenge;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a single byte value from our raw data.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A single Byte at the next Offset Address</returns>
|
||||||
|
private Byte ReadByte()
|
||||||
|
{
|
||||||
|
byte[] b = new byte[1];
|
||||||
|
Array.Copy( this.raw_data, this.offset, b, 0, 1 );
|
||||||
|
|
||||||
|
this.offset++;
|
||||||
|
return b[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read all remaining Bytes from our raw data.
|
||||||
|
/// Used for multi-packet responses.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>All remaining data</returns>
|
||||||
|
private Byte[] ReadBytes()
|
||||||
|
{
|
||||||
|
int size = (this.raw_data.Length - this.offset - 4);
|
||||||
|
if ( size < 1 ) return new Byte[] { };
|
||||||
|
|
||||||
|
byte[] b = new byte[size];
|
||||||
|
Array.Copy( this.raw_data, this.offset, b, 0, this.raw_data.Length - this.offset - 4 );
|
||||||
|
|
||||||
|
this.offset += ( this.raw_data.Length - this.offset - 4 );
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a 32-Bit Integer value from the next offset address.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The Int32 Value found at the offset address</returns>
|
||||||
|
private Int32 ReadInt32()
|
||||||
|
{
|
||||||
|
byte[] b = new byte[4];
|
||||||
|
Array.Copy( this.raw_data, this.offset, b, 0, 4 );
|
||||||
|
|
||||||
|
this.offset += 4;
|
||||||
|
return BitConverter.ToInt32( b, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a 16-Bit Integer (also called "short") value from the next offset address.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The Int16 Value found at the offset address</returns>
|
||||||
|
private Int16 ReadInt16()
|
||||||
|
{
|
||||||
|
byte[] b = new byte[2];
|
||||||
|
Array.Copy( this.raw_data, this.offset, b, 0, 2 );
|
||||||
|
|
||||||
|
this.offset += 2;
|
||||||
|
return BitConverter.ToInt16( b, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a Float value from the next offset address.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The Float Value found at the offset address</returns>
|
||||||
|
private float ReadFloat()
|
||||||
|
{
|
||||||
|
byte[] b = new byte[4];
|
||||||
|
Array.Copy( this.raw_data, this.offset, b, 0, 4 );
|
||||||
|
|
||||||
|
this.offset += 4;
|
||||||
|
return BitConverter.ToSingle( b, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a String until its end starting from the next offset address.
|
||||||
|
/// Reading stops once the method detects a 0x00 Character at the next position (\0 terminator)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The String read</returns>
|
||||||
|
private String ReadString()
|
||||||
|
{
|
||||||
|
byte[] cache = new byte[1] { 0x01 };
|
||||||
|
String output = "";
|
||||||
|
|
||||||
|
while ( cache[0] != 0x00 )
|
||||||
|
{
|
||||||
|
if ( this.offset == this.raw_data.Length ) break; // fixes Valve's inability to code a proper query protocol
|
||||||
|
Array.Copy( this.raw_data, this.offset, cache, 0, 1 );
|
||||||
|
this.offset++;
|
||||||
|
|
||||||
|
if ( cache[0] != 0x00)
|
||||||
|
output += Encoding.UTF8.GetString( cache );
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
74
Facepunch.Steamworks/Client/Stats.cs
Normal file
74
Facepunch.Steamworks/Client/Stats.cs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : IDisposable
|
||||||
|
{
|
||||||
|
Stats _stats;
|
||||||
|
|
||||||
|
public Stats Stats
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _stats == null )
|
||||||
|
_stats = new Stats( this );
|
||||||
|
|
||||||
|
return _stats;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Stats
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
internal Stats( Client c )
|
||||||
|
{
|
||||||
|
client = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateStats()
|
||||||
|
{
|
||||||
|
client.native.userstats.RequestCurrentStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGlobalStats( int days = 1 )
|
||||||
|
{
|
||||||
|
client.native.userstats.GetNumberOfCurrentPlayers();
|
||||||
|
client.native.userstats.RequestGlobalAchievementPercentages();
|
||||||
|
client.native.userstats.RequestGlobalStats( days );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetInt( string name )
|
||||||
|
{
|
||||||
|
int data = 0;
|
||||||
|
client.native.userstats.GetStat( name, ref data );
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long GetGlobalInt( string name )
|
||||||
|
{
|
||||||
|
long data = 0;
|
||||||
|
client.native.userstats.GetGlobalStat( name, ref data );
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetFloat( string name )
|
||||||
|
{
|
||||||
|
float data = 0;
|
||||||
|
client.native.userstats.GetStat0( name, ref data );
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetGlobalFloat( string name )
|
||||||
|
{
|
||||||
|
double data = 0;
|
||||||
|
client.native.userstats.GetGlobalStat0( name, ref data );
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
162
Facepunch.Steamworks/Client/Voice.cs
Normal file
162
Facepunch.Steamworks/Client/Voice.cs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public class Voice : IDisposable
|
||||||
|
{
|
||||||
|
const int ReadBufferSize = 1024 * 128;
|
||||||
|
const int UncompressBufferSize = 1024 * 256;
|
||||||
|
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
internal IntPtr ReadCompressedBuffer;
|
||||||
|
internal IntPtr ReadUncompressedBuffer;
|
||||||
|
|
||||||
|
internal IntPtr UncompressBuffer;
|
||||||
|
|
||||||
|
public Action<IntPtr, int> OnCompressedData;
|
||||||
|
public Action<IntPtr, int> OnUncompressedData;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the optimal sample rate for voice - according to Steam
|
||||||
|
/// </summary>
|
||||||
|
public uint OptimalSampleRate
|
||||||
|
{
|
||||||
|
get { return client.native.user.GetVoiceOptimalSampleRate(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _wantsrecording = false;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If set to true we are listening to the mic.
|
||||||
|
/// You should usually toggle this with the press of a key for push to talk.
|
||||||
|
/// </summary>
|
||||||
|
public bool WantsRecording
|
||||||
|
{
|
||||||
|
get { return _wantsrecording; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_wantsrecording = value;
|
||||||
|
|
||||||
|
if ( value )
|
||||||
|
{
|
||||||
|
client.native.user.StartVoiceRecording();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
client.native.user.StopVoiceRecording();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The last time voice was detected, recorded
|
||||||
|
/// </summary>
|
||||||
|
public DateTime LastVoiceRecordTime { get; private set; }
|
||||||
|
|
||||||
|
public TimeSpan TimeSinceLastVoiceRecord { get { return DateTime.Now.Subtract( LastVoiceRecordTime ); } }
|
||||||
|
|
||||||
|
public bool IsRecording = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If set we will capture the audio at this rate. If unset (set to 0) will capture at OptimalSampleRate
|
||||||
|
/// </summary>
|
||||||
|
public uint DesiredSampleRate = 0;
|
||||||
|
|
||||||
|
public Voice( Client client )
|
||||||
|
{
|
||||||
|
this.client = client;
|
||||||
|
|
||||||
|
ReadCompressedBuffer = Marshal.AllocHGlobal( ReadBufferSize );
|
||||||
|
ReadUncompressedBuffer = Marshal.AllocHGlobal( ReadBufferSize );
|
||||||
|
UncompressBuffer = Marshal.AllocHGlobal( UncompressBufferSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal( ReadCompressedBuffer );
|
||||||
|
Marshal.FreeHGlobal( ReadUncompressedBuffer );
|
||||||
|
|
||||||
|
Marshal.FreeHGlobal( UncompressBuffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Update()
|
||||||
|
{
|
||||||
|
if ( OnCompressedData == null && OnUncompressedData == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
uint bufferRegularLastWrite = 0;
|
||||||
|
uint bufferCompressedLastWrite = 0;
|
||||||
|
|
||||||
|
Valve.Steamworks.EVoiceResult result = (Valve.Steamworks.EVoiceResult) client.native.user.GetVoice( OnCompressedData != null, ReadCompressedBuffer, ReadBufferSize, ref bufferCompressedLastWrite,
|
||||||
|
OnUncompressedData != null, (IntPtr) ReadUncompressedBuffer, ReadBufferSize, ref bufferRegularLastWrite,
|
||||||
|
DesiredSampleRate == 0 ? OptimalSampleRate : DesiredSampleRate );
|
||||||
|
|
||||||
|
Console.WriteLine( result );
|
||||||
|
|
||||||
|
IsRecording = true;
|
||||||
|
|
||||||
|
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultOK )
|
||||||
|
{
|
||||||
|
if ( OnCompressedData != null && bufferCompressedLastWrite > 0 )
|
||||||
|
{
|
||||||
|
OnCompressedData( ReadCompressedBuffer, (int)bufferCompressedLastWrite );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( OnUncompressedData != null && bufferRegularLastWrite > 0 )
|
||||||
|
{
|
||||||
|
OnUncompressedData( ReadUncompressedBuffer, (int)bufferRegularLastWrite );
|
||||||
|
}
|
||||||
|
|
||||||
|
LastVoiceRecordTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultNotRecording ||
|
||||||
|
result == Valve.Steamworks.EVoiceResult.k_EVoiceResultNotInitialized )
|
||||||
|
IsRecording = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe bool Decompress( byte[] input, MemoryStream output, uint samepleRate = 0 )
|
||||||
|
{
|
||||||
|
fixed ( byte* p = input )
|
||||||
|
{
|
||||||
|
return Decompress( (IntPtr)p, 0, input.Length, output, samepleRate );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe bool Decompress( IntPtr input, int inputoffset, int inputsize, MemoryStream output, uint samepleRate = 0 )
|
||||||
|
{
|
||||||
|
if ( samepleRate == 0 )
|
||||||
|
samepleRate = OptimalSampleRate;
|
||||||
|
|
||||||
|
uint bytesOut = 0;
|
||||||
|
var result = (Valve.Steamworks.EVoiceResult) client.native.user.DecompressVoice( (IntPtr)( ((byte*)input) + inputoffset ), (uint) inputsize, UncompressBuffer, UncompressBufferSize, ref bytesOut, samepleRate );
|
||||||
|
|
||||||
|
if ( bytesOut > 0 )
|
||||||
|
output.SetLength( bytesOut );
|
||||||
|
|
||||||
|
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultOK )
|
||||||
|
{
|
||||||
|
if ( output.Capacity < bytesOut )
|
||||||
|
output.Capacity = (int) bytesOut;
|
||||||
|
|
||||||
|
output.SetLength( bytesOut );
|
||||||
|
Marshal.Copy( UncompressBuffer, output.GetBuffer(), 0, (int) bytesOut );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
Facepunch.Steamworks/Config.cs
Normal file
37
Facepunch.Steamworks/Config.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public static class Config
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Some platforms allow/need CallingConvention.ThisCall. If you're crashing with argument null
|
||||||
|
/// errors on certain platforms, try flipping this to true.
|
||||||
|
///
|
||||||
|
/// I owe this logic to Riley Labrecque's hard work on Steamworks.net - I don't have the knowledge
|
||||||
|
/// or patience to find this shit on my own, so massive thanks to him. And also massive thanks to him
|
||||||
|
/// for releasing his shit open source under the MIT license so we can all learn and iterate.
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static bool UseThisCall { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set this to true on Linux and OSX
|
||||||
|
/// </summary>
|
||||||
|
public static bool PackSmall { get; set; } = false;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Native dll to look for. This is the steam_api.dll renamed.
|
||||||
|
/// We need to rename the dll anyway because we can't dynamically choose the library
|
||||||
|
/// ie, we can't load steam_api64.dll on windows 64 platforms. So instead we choose to
|
||||||
|
/// keep the library name the same.
|
||||||
|
///
|
||||||
|
/// This is exposed only for the benefit of implementation - and cannot be changed at runtime.
|
||||||
|
/// </summary>
|
||||||
|
public const string LibraryName = "FacepunchSteamworksApi";
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
namespace Steamworks.Data
|
|
||||||
{
|
|
||||||
public enum LeaderboardDisplay : int
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The score is just a simple numerical value
|
|
||||||
/// </summary>
|
|
||||||
Numeric = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The score represents a time, in seconds
|
|
||||||
/// </summary>
|
|
||||||
TimeSeconds = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The score represents a time, in milliseconds
|
|
||||||
/// </summary>
|
|
||||||
TimeMilliSeconds = 3,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
namespace Steamworks.Data
|
|
||||||
{
|
|
||||||
public enum LeaderboardSort : int
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The top-score is the lowest number
|
|
||||||
/// </summary>
|
|
||||||
Ascending = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The top-score is the highest number
|
|
||||||
/// </summary>
|
|
||||||
Descending = 2,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Steamworks.Data
|
|
||||||
{
|
|
||||||
[Flags]
|
|
||||||
public enum SendType : int
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Send the message unreliably. Can be lost. Messages *can* be larger than a
|
|
||||||
/// single MTU (UDP packet), but there is no retransmission, so if any piece
|
|
||||||
/// of the message is lost, the entire message will be dropped.
|
|
||||||
///
|
|
||||||
/// The sending API does have some knowledge of the underlying connection, so
|
|
||||||
/// if there is no NAT-traversal accomplished or there is a recognized adjustment
|
|
||||||
/// happening on the connection, the packet will be batched until the connection
|
|
||||||
/// is open again.
|
|
||||||
/// </summary>
|
|
||||||
Unreliable = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disable Nagle's algorithm.
|
|
||||||
/// By default, Nagle's algorithm is applied to all outbound messages. This means
|
|
||||||
/// that the message will NOT be sent immediately, in case further messages are
|
|
||||||
/// sent soon after you send this, which can be grouped together. Any time there
|
|
||||||
/// is enough buffered data to fill a packet, the packets will be pushed out immediately,
|
|
||||||
/// but partially-full packets not be sent until the Nagle timer expires.
|
|
||||||
/// </summary>
|
|
||||||
NoNagle = 1 << 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If the message cannot be sent very soon (because the connection is still doing some initial
|
|
||||||
/// handshaking, route negotiations, etc), then just drop it. This is only applicable for unreliable
|
|
||||||
/// messages. Using this flag on reliable messages is invalid.
|
|
||||||
/// </summary>
|
|
||||||
NoDelay = 1 << 2,
|
|
||||||
|
|
||||||
/// Reliable message send. Can send up to 0.5mb in a single message.
|
|
||||||
/// Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for
|
|
||||||
/// efficient sends of large chunks of data.
|
|
||||||
Reliable = 1 << 3
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<AssemblyName>Facepunch.Steamworks.Posix</AssemblyName>
|
|
||||||
<DefineConstants>$(DefineConstants);PLATFORM_POSIX</DefineConstants>
|
|
||||||
<TargetFrameworks>netstandard2.1;net6.0;net46</TargetFrameworks>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<LangVersion>10</LangVersion>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
|
||||||
<RootNamespace>Steamworks</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<Import Project="Facepunch.Steamworks.targets" />
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,42 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<AssemblyName>Facepunch.Steamworks.Win32</AssemblyName>
|
|
||||||
<DefineConstants>$(DefineConstants);PLATFORM_WIN32;PLATFORM_WIN</DefineConstants>
|
|
||||||
<TargetFrameworks>netstandard2.1;net6.0;net46</TargetFrameworks>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
|
||||||
<RootNamespace>Steamworks</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<FrameworkPathOverride Condition="'$(TargetFramework)' == 'net40'">C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client</FrameworkPathOverride>
|
|
||||||
<Authors>Garry Newman</Authors>
|
|
||||||
<PackageId>Facepunch.Steamworks.win32</PackageId>
|
|
||||||
<PackageDescription>Steamworks implementation with an emphasis on making things easy. For Windows x86.</PackageDescription>
|
|
||||||
<PackageProjectUrl>https://github.com/Facepunch/Facepunch.Steamworks</PackageProjectUrl>
|
|
||||||
<PackageIcon>Facepunch.Steamworks.jpg</PackageIcon>
|
|
||||||
<PackageTags>facepunch;steam;unity;steamworks;valve</PackageTags>
|
|
||||||
<LangVersion>10</LangVersion>
|
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
|
||||||
<RepositoryUrl>https://github.com/Facepunch/Facepunch.Steamworks.git</RepositoryUrl>
|
|
||||||
<RepositoryType>git</RepositoryType>
|
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Facepunch.Steamworks.jpg">
|
|
||||||
<Pack>true</Pack>
|
|
||||||
<PackagePath>/</PackagePath>
|
|
||||||
</None>
|
|
||||||
<None Include="steam_api.dll">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
<Pack>true</Pack>
|
|
||||||
<PackagePath>content</PackagePath>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Import Project="Facepunch.Steamworks.targets" />
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,55 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<AssemblyName>Facepunch.Steamworks.Win64</AssemblyName>
|
|
||||||
<DefineConstants>$(DefineConstants);PLATFORM_WIN64;PLATFORM_WIN;PLATFORM_64</DefineConstants>
|
|
||||||
<TargetFrameworks>netstandard2.1;net6.0;net46</TargetFrameworks>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
|
||||||
<RootNamespace>Steamworks</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<FrameworkPathOverride Condition="'$(TargetFramework)' == 'net40'">C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client</FrameworkPathOverride>
|
|
||||||
<Authors>Garry Newman</Authors>
|
|
||||||
<PackageId>Facepunch.Steamworks</PackageId>
|
|
||||||
<PackageDescription>Steamworks implementation with an emphasis on making things easy. For Windows x64.</PackageDescription>
|
|
||||||
<PackageProjectUrl>https://github.com/Facepunch/Facepunch.Steamworks</PackageProjectUrl>
|
|
||||||
<PackageIcon>Facepunch.Steamworks.jpg</PackageIcon>
|
|
||||||
<PackageTags>facepunch;steam;unity;steamworks;valve</PackageTags>
|
|
||||||
<LangVersion>10</LangVersion>
|
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
|
||||||
<RepositoryUrl>https://github.com/Facepunch/Facepunch.Steamworks.git</RepositoryUrl>
|
|
||||||
<RepositoryType>git</RepositoryType>
|
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Facepunch.Steamworks.jpg">
|
|
||||||
<Pack>true</Pack>
|
|
||||||
<PackagePath>/</PackagePath>
|
|
||||||
</None>
|
|
||||||
<None Include="steam_api64.dll">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
<Pack>true</Pack>
|
|
||||||
<PackagePath>content</PackagePath>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Import Project="Facepunch.Steamworks.targets" />
|
|
||||||
|
|
||||||
<Target Name="PostBuildHome" AfterTargets="PostBuildEvent" Condition="'$(Computername)'=='GarryBasementPc'">
|
|
||||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Win64.* C:\plastic\RustMain\Assets\Plugins\Facepunch.Steamworks\" />
|
|
||||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Posix.* C:\plastic\RustMain\Assets\Plugins\Facepunch.Steamworks\" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="PostBuildOffice" AfterTargets="PostBuildEvent" Condition="'$(Computername)'=='GARRYSOFFICEPC'">
|
|
||||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Win64.* C:\Plastic\Rust\Assets\Plugins\Facepunch.Steamworks\" />
|
|
||||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Posix.* C:\Plastic\Rust\Assets\Plugins\Facepunch.Steamworks\" />
|
|
||||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Win64.* C:\Git\Facepunch.Steamworks.UnityTest\Assets\Steamworks" />
|
|
||||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Win32.* C:\Git\Facepunch.Steamworks.UnityTest\Assets\Steamworks" />
|
|
||||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Posix.* C:\Git\Facepunch.Steamworks.UnityTest\Assets\Steamworks" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user