mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-26 14:45:51 +03:00
Merge branch 'master' into workshop
This commit is contained in:
commit
26580df11d
4
.gitignore
vendored
4
.gitignore
vendored
@ -55,11 +55,14 @@ 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,3 +73,4 @@ mscorlib.dll
|
|||||||
packages
|
packages
|
||||||
Generator/bin
|
Generator/bin
|
||||||
*.XML
|
*.XML
|
||||||
|
.vs
|
330
Facepunch.Steamworks.Test/Client/Lobby.cs
Normal file
330
Facepunch.Steamworks.Test/Client/Lobby.cs
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Facepunch.Steamworks;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks.Test
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[DeploymentItem("steam_api.dll")]
|
||||||
|
[DeploymentItem("steam_api64.dll")]
|
||||||
|
[DeploymentItem("steam_appid.txt")]
|
||||||
|
public class Lobby
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateLobby()
|
||||||
|
{
|
||||||
|
using (var client = new Facepunch.Steamworks.Client(252490))
|
||||||
|
{
|
||||||
|
Assert.IsTrue(client.IsValid);
|
||||||
|
|
||||||
|
client.Lobby.Create(Steamworks.Lobby.Type.Public, 10);
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyCreated = (success) =>
|
||||||
|
{
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(client.Lobby.IsValid);
|
||||||
|
Console.WriteLine("lobby created: " + client.Lobby.CurrentLobby);
|
||||||
|
Console.WriteLine($"Owner: {client.Lobby.Owner}");
|
||||||
|
Console.WriteLine($"Max Members: {client.Lobby.MaxMembers}");
|
||||||
|
Console.WriteLine($"Num Members: {client.Lobby.NumMembers}");
|
||||||
|
client.Lobby.Leave();
|
||||||
|
};
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while (sw.Elapsed.TotalSeconds < 3)
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetCreatedLobbyData()
|
||||||
|
{
|
||||||
|
using (var client = new Facepunch.Steamworks.Client(252490))
|
||||||
|
{
|
||||||
|
Assert.IsTrue(client.IsValid);
|
||||||
|
|
||||||
|
client.Lobby.Create(Steamworks.Lobby.Type.Public, 10);
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyCreated = (success) =>
|
||||||
|
{
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(client.Lobby.IsValid);
|
||||||
|
Console.WriteLine("lobby created: " + client.Lobby.CurrentLobby);
|
||||||
|
foreach (KeyValuePair<string, string> data in client.Lobby.CurrentLobbyData.GetAllData())
|
||||||
|
{
|
||||||
|
if (data.Key == "appid")
|
||||||
|
{
|
||||||
|
Assert.IsTrue(data.Value == "252490");
|
||||||
|
}
|
||||||
|
Console.WriteLine($"{data.Key} {data.Value}");
|
||||||
|
}
|
||||||
|
client.Lobby.Leave();
|
||||||
|
};
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while (sw.Elapsed.TotalSeconds < 3)
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UpdateLobbyData()
|
||||||
|
{
|
||||||
|
using (var client = new Facepunch.Steamworks.Client(252490))
|
||||||
|
{
|
||||||
|
Assert.IsTrue(client.IsValid);
|
||||||
|
|
||||||
|
client.Lobby.Create(Steamworks.Lobby.Type.Public, 10);
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyCreated = (success) =>
|
||||||
|
{
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(client.Lobby.IsValid);
|
||||||
|
Console.WriteLine("lobby created: " + client.Lobby.CurrentLobby);
|
||||||
|
|
||||||
|
client.Lobby.Name = "My Updated Lobby Name";
|
||||||
|
client.Lobby.CurrentLobbyData.SetData("testkey", "testvalue");
|
||||||
|
client.Lobby.LobbyType = Steamworks.Lobby.Type.Private;
|
||||||
|
client.Lobby.MaxMembers = 5;
|
||||||
|
client.Lobby.Joinable = false;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, string> data in client.Lobby.CurrentLobbyData.GetAllData())
|
||||||
|
{
|
||||||
|
if (data.Key == "appid")
|
||||||
|
{
|
||||||
|
Assert.IsTrue(data.Value == "252490");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.Key == "testkey")
|
||||||
|
{
|
||||||
|
Assert.IsTrue(data.Value == "testvalue");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.Key == "lobbytype")
|
||||||
|
{
|
||||||
|
Assert.IsTrue(data.Value == Steamworks.Lobby.Type.Private.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"{data.Key} {data.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyDataUpdated = () =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("lobby data updated");
|
||||||
|
Console.WriteLine(client.Lobby.MaxMembers);
|
||||||
|
Console.WriteLine(client.Lobby.Joinable);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while (sw.Elapsed.TotalSeconds < 3)
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Lobby.Leave();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void RefreshLobbyList()
|
||||||
|
{
|
||||||
|
using (var client = new Facepunch.Steamworks.Client(252490))
|
||||||
|
{
|
||||||
|
Assert.IsTrue(client.IsValid);
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyCreated = (success) =>
|
||||||
|
{
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(client.Lobby.IsValid);
|
||||||
|
Console.WriteLine("lobby created: " + client.Lobby.CurrentLobby);
|
||||||
|
client.LobbyList.Refresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
client.LobbyList.OnLobbiesUpdated = () =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("lobbies updating");
|
||||||
|
if (client.LobbyList.Finished)
|
||||||
|
{
|
||||||
|
Console.WriteLine("lobbies finished updating");
|
||||||
|
Console.WriteLine($"found {client.LobbyList.Lobbies.Count} lobbies");
|
||||||
|
|
||||||
|
foreach (LobbyList.Lobby lobby in client.LobbyList.Lobbies)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Found Lobby: {lobby.Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Lobby.Leave();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Lobby.Create(Steamworks.Lobby.Type.Public, 10);
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while (sw.Elapsed.TotalSeconds < 3)
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void RefreshLobbyListWithFilter()
|
||||||
|
{
|
||||||
|
using (var client = new Facepunch.Steamworks.Client(252490))
|
||||||
|
{
|
||||||
|
Assert.IsTrue(client.IsValid);
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyCreated = (success) =>
|
||||||
|
{
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(client.Lobby.IsValid);
|
||||||
|
Console.WriteLine("lobby created: " + client.Lobby.CurrentLobby);
|
||||||
|
client.Lobby.CurrentLobbyData.SetData("testkey", "testvalue");
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyDataUpdated = () =>
|
||||||
|
{
|
||||||
|
var filter = new LobbyList.Filter();
|
||||||
|
filter.StringFilters.Add("testkey", "testvalue");
|
||||||
|
client.LobbyList.Refresh(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
client.LobbyList.OnLobbiesUpdated = () =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("lobbies updating");
|
||||||
|
if (client.LobbyList.Finished)
|
||||||
|
{
|
||||||
|
Console.WriteLine("lobbies finished updating");
|
||||||
|
Console.WriteLine($"found {client.LobbyList.Lobbies.Count} lobbies");
|
||||||
|
|
||||||
|
foreach (LobbyList.Lobby lobby in client.LobbyList.Lobbies)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Found Lobby: {lobby.Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Lobby.Create(Steamworks.Lobby.Type.Public, 10);
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while (sw.Elapsed.TotalSeconds < 5)
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Lobby.Leave();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void SendChatMessage()
|
||||||
|
{
|
||||||
|
using (var client = new Facepunch.Steamworks.Client(252490))
|
||||||
|
{
|
||||||
|
Assert.IsTrue(client.IsValid);
|
||||||
|
string testString = "Hello, World";
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyCreated = (success) =>
|
||||||
|
{
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(client.Lobby.IsValid);
|
||||||
|
Console.WriteLine("lobby created: " + client.Lobby.CurrentLobby);
|
||||||
|
client.Lobby.CurrentLobbyData.SetData("testkey", "testvalue");
|
||||||
|
client.Lobby.SendChatMessage(testString);
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Lobby.OnChatMessageRecieved = (steamID, bytes, length) =>
|
||||||
|
{
|
||||||
|
string message = Encoding.UTF8.GetString(bytes, 0, length);
|
||||||
|
Console.WriteLine("message recieved");
|
||||||
|
Assert.IsTrue(message == testString);
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Lobby.Create(Steamworks.Lobby.Type.Public, 10);
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while (sw.Elapsed.TotalSeconds < 5)
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Lobby.Leave();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void SetGetUserMetadata()
|
||||||
|
{
|
||||||
|
using (var client = new Facepunch.Steamworks.Client(252490))
|
||||||
|
{
|
||||||
|
Assert.IsTrue(client.IsValid);
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyCreated = (success) =>
|
||||||
|
{
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(client.Lobby.IsValid);
|
||||||
|
Console.WriteLine("lobby created: " + client.Lobby.CurrentLobby);
|
||||||
|
client.Lobby.SetMemberData("testkey", "testvalue");
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Lobby.OnLobbyMemberDataUpdated = (steamID) =>
|
||||||
|
{
|
||||||
|
string name = client.Friends.GetName(steamID);
|
||||||
|
Console.WriteLine(name + " updated data");
|
||||||
|
Assert.IsTrue(client.Lobby.GetMemberData(steamID, "testkey") == "testvalue");
|
||||||
|
Console.WriteLine("testkey is now: " + client.Lobby.GetMemberData(steamID, "testkey"));
|
||||||
|
};
|
||||||
|
|
||||||
|
client.Lobby.Create(Steamworks.Lobby.Type.Public, 10);
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
while (sw.Elapsed.TotalSeconds < 5)
|
||||||
|
{
|
||||||
|
client.Update();
|
||||||
|
System.Threading.Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Lobby.Leave();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -47,7 +47,7 @@ public void InternetList()
|
|||||||
|
|
||||||
foreach ( var server in query.Responded.Take( 20 ) )
|
foreach ( var server in query.Responded.Take( 20 ) )
|
||||||
{
|
{
|
||||||
Console.WriteLine( "{0} {1}", server.AddressString, server.Name );
|
Console.WriteLine( "{0} {1}", server.Address, server.Name );
|
||||||
}
|
}
|
||||||
|
|
||||||
query.Dispose();
|
query.Dispose();
|
||||||
@ -370,7 +370,9 @@ public void CustomList()
|
|||||||
|
|
||||||
foreach ( var s in query.Responded )
|
foreach ( var s in query.Responded )
|
||||||
{
|
{
|
||||||
Console.WriteLine( "{0} - {1}", s.AddressString, s.Name );
|
Console.WriteLine( "{0} - {1}", s.Address, s.Name );
|
||||||
|
|
||||||
|
Assert.IsTrue( servers.Contains( $"{s.Address}:{s.QueryPort}" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
query.Dispose();
|
query.Dispose();
|
||||||
|
@ -94,6 +94,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Client\Achievements.cs" />
|
<Compile Include="Client\Achievements.cs" />
|
||||||
<Compile Include="Client\Client.cs" />
|
<Compile Include="Client\Client.cs" />
|
||||||
|
<Compile Include="Client\Lobby.cs" />
|
||||||
<Compile Include="Client\RichPresence.cs" />
|
<Compile Include="Client\RichPresence.cs" />
|
||||||
<Compile Include="Client\Leaderboard.cs" />
|
<Compile Include="Client\Leaderboard.cs" />
|
||||||
<Compile Include="Client\App.cs" />
|
<Compile Include="Client\App.cs" />
|
||||||
@ -107,12 +108,6 @@
|
|||||||
<Compile Include="Server\Server.cs" />
|
<Compile Include="Server\Server.cs" />
|
||||||
<Compile Include="Server\Stats.cs" />
|
<Compile Include="Server\Stats.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.csproj">
|
|
||||||
<Project>{dc2d9fa9-f005-468f-8581-85c79f4e0034}</Project>
|
|
||||||
<Name>Facepunch.Steamworks</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Client\Serverlist.cs" />
|
<Compile Include="Client\Serverlist.cs" />
|
||||||
<Compile Include="Client\Stats.cs" />
|
<Compile Include="Client\Stats.cs" />
|
||||||
@ -120,6 +115,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.csproj">
|
||||||
|
<Project>{91962664-eb42-472a-94c8-c4ffeb44cc4b}</Project>
|
||||||
|
<Name>Facepunch.Steamworks</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
<Choose>
|
<Choose>
|
||||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
BIN
Facepunch.Steamworks.Test/bin/Debug/Newtonsoft.Json.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/Newtonsoft.Json.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Release/Newtonsoft.Json.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Release/Newtonsoft.Json.dll
Normal file
Binary file not shown.
@ -1,11 +1,9 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26228.4
|
VisualStudioVersion = 15.0.26730.12
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.NetCore", "Facepunch.Steamworks\Facepunch.Steamworks.NetCore.csproj", "{91962664-EB42-472A-94C8-C4FFEB44CC4B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks", "Facepunch.Steamworks\Facepunch.Steamworks.csproj", "{91962664-EB42-472A-94C8-C4FFEB44CC4B}"
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks", "Facepunch.Steamworks\Facepunch.Steamworks.csproj", "{DC2D9FA9-F005-468F-8581-85C79F4E0034}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks.Test", "Facepunch.Steamworks.Test\Facepunch.Steamworks.Test.csproj", "{3F6183AD-D966-44F2-A6EB-42E61E591B49}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks.Test", "Facepunch.Steamworks.Test\Facepunch.Steamworks.Test.csproj", "{3F6183AD-D966-44F2-A6EB-42E61E591B49}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -21,10 +19,6 @@ Global
|
|||||||
{91962664-EB42-472A-94C8-C4FFEB44CC4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{91962664-EB42-472A-94C8-C4FFEB44CC4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{91962664-EB42-472A-94C8-C4FFEB44CC4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{91962664-EB42-472A-94C8-C4FFEB44CC4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{91962664-EB42-472A-94C8-C4FFEB44CC4B}.Release|Any CPU.Build.0 = Release|Any CPU
|
{91962664-EB42-472A-94C8-C4FFEB44CC4B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Release|Any CPU.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}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@ -37,4 +31,7 @@ Global
|
|||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {506FC2EC-38D1-45E2-BAE8-D61584162F7D}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -111,7 +111,13 @@ public void UpdateWhile( Func<bool> func )
|
|||||||
while ( func() )
|
while ( func() )
|
||||||
{
|
{
|
||||||
Update();
|
Update();
|
||||||
System.Threading.Thread.Sleep( 1 );
|
|
||||||
|
const int waitPeriodMillis = 1;
|
||||||
|
#if NETCORE
|
||||||
|
System.Threading.Tasks.Task.Delay( waitPeriodMillis ).Wait();
|
||||||
|
#else
|
||||||
|
System.Threading.Thread.Sleep( waitPeriodMillis );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ public partial class Client : BaseSteamworks
|
|||||||
|
|
||||||
public Voice Voice { get; private set; }
|
public Voice Voice { get; private set; }
|
||||||
public ServerList ServerList { get; private set; }
|
public ServerList ServerList { get; private set; }
|
||||||
|
public LobbyList LobbyList { get; private set; }
|
||||||
public App App { get; private set; }
|
public App App { get; private set; }
|
||||||
public Achievements Achievements { get; private set; }
|
public Achievements Achievements { get; private set; }
|
||||||
public Stats Stats { get; private set; }
|
public Stats Stats { get; private set; }
|
||||||
@ -64,6 +65,11 @@ public partial class Client : BaseSteamworks
|
|||||||
|
|
||||||
public Client( uint appId )
|
public Client( uint appId )
|
||||||
{
|
{
|
||||||
|
if ( Instance != null )
|
||||||
|
{
|
||||||
|
throw new System.Exception( "Only one Facepunch.Steamworks.Client can exist - dispose the old one before trying to create a new one." );
|
||||||
|
}
|
||||||
|
|
||||||
Instance = this;
|
Instance = this;
|
||||||
native = new Interop.NativeInterface();
|
native = new Interop.NativeInterface();
|
||||||
|
|
||||||
@ -88,6 +94,7 @@ public Client( uint appId )
|
|||||||
//
|
//
|
||||||
Voice = new Voice( this );
|
Voice = new Voice( this );
|
||||||
ServerList = new ServerList( this );
|
ServerList = new ServerList( this );
|
||||||
|
LobbyList = new LobbyList(this);
|
||||||
App = new App( this );
|
App = new App( this );
|
||||||
Stats = new Stats( this );
|
Stats = new Stats( this );
|
||||||
Achievements = new Achievements( this );
|
Achievements = new Achievements( this );
|
||||||
@ -159,6 +166,12 @@ public override void Dispose()
|
|||||||
ServerList = null;
|
ServerList = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LobbyList != null)
|
||||||
|
{
|
||||||
|
LobbyList.Dispose();
|
||||||
|
LobbyList = null;
|
||||||
|
}
|
||||||
|
|
||||||
if ( App != null )
|
if ( App != null )
|
||||||
{
|
{
|
||||||
App.Dispose();
|
App.Dispose();
|
||||||
|
586
Facepunch.Steamworks/Client/Lobby.cs
Normal file
586
Facepunch.Steamworks/Client/Lobby.cs
Normal file
@ -0,0 +1,586 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class Client : IDisposable
|
||||||
|
{
|
||||||
|
Lobby _lobby;
|
||||||
|
|
||||||
|
public Lobby Lobby
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_lobby == null)
|
||||||
|
_lobby = new Steamworks.Lobby(this);
|
||||||
|
return _lobby;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class Lobby : IDisposable
|
||||||
|
{
|
||||||
|
//The type of lobby you are creating
|
||||||
|
public enum Type : int
|
||||||
|
{
|
||||||
|
Private = SteamNative.LobbyType.Private,
|
||||||
|
FriendsOnly = SteamNative.LobbyType.FriendsOnly,
|
||||||
|
Public = SteamNative.LobbyType.Public,
|
||||||
|
Invisible = SteamNative.LobbyType.Invisible,
|
||||||
|
Error //happens if you try to get this when you aren't in a valid lobby
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
public Lobby(Client c)
|
||||||
|
{
|
||||||
|
client = c;
|
||||||
|
SteamNative.LobbyDataUpdate_t.RegisterCallback(client, OnLobbyDataUpdatedAPI);
|
||||||
|
SteamNative.LobbyChatMsg_t.RegisterCallback(client, OnLobbyChatMessageRecievedAPI);
|
||||||
|
SteamNative.LobbyChatUpdate_t.RegisterCallback(client, OnLobbyStateUpdatedAPI);
|
||||||
|
SteamNative.GameLobbyJoinRequested_t.RegisterCallback(client, OnLobbyJoinRequestedAPI);
|
||||||
|
SteamNative.LobbyInvite_t.RegisterCallback(client, OnUserInvitedToLobbyAPI);
|
||||||
|
SteamNative.PersonaStateChange_t.RegisterCallback(client, OnLobbyMemberPersonaChangeAPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The CSteamID of the lobby we're currently in.
|
||||||
|
/// </summary>
|
||||||
|
public ulong CurrentLobby { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The LobbyData of the CurrentLobby. Note this is the global data for the lobby. Use SetMemberData to set specific member data.
|
||||||
|
/// </summary>
|
||||||
|
public LobbyData CurrentLobbyData { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this lobby is valid, ie, we've succesffuly created and/or joined a lobby.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsValid => CurrentLobby != 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Join a Lobby through its LobbyID. OnLobbyJoined is called with the result of the Join attempt.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lobbyID">CSteamID of lobby to join</param>
|
||||||
|
public void Join(ulong lobbyID)
|
||||||
|
{
|
||||||
|
Leave();
|
||||||
|
client.native.matchmaking.JoinLobby(lobbyID, OnLobbyJoinedAPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLobbyJoinedAPI(LobbyEnter_t callback, bool error)
|
||||||
|
{
|
||||||
|
if (error || (callback.EChatRoomEnterResponse != (uint)(SteamNative.ChatRoomEnterResponse.Success)))
|
||||||
|
{
|
||||||
|
if (OnLobbyJoined != null) { OnLobbyJoined(false); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentLobby = callback.SteamIDLobby;
|
||||||
|
UpdateLobbyData();
|
||||||
|
if (OnLobbyJoined != null) { OnLobbyJoined(true); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when a lobby has been attempted joined. Returns true if lobby was successfuly joined, false if not.
|
||||||
|
/// </summary>
|
||||||
|
public Action<bool> OnLobbyJoined;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a lobby and returns the created lobby. You auto join the created lobby. The lobby is stored in Client.CurrentLobby if successful.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lobbyType">The Lobby.Type of Lobby to be created</param>
|
||||||
|
/// <param name="maxMembers">The maximum amount of people you want to be able to be in this lobby, including yourself</param>
|
||||||
|
public void Create(Lobby.Type lobbyType, int maxMembers)
|
||||||
|
{
|
||||||
|
client.native.matchmaking.CreateLobby((SteamNative.LobbyType)lobbyType, maxMembers, OnLobbyCreatedAPI);
|
||||||
|
createdLobbyType = lobbyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Type createdLobbyType;
|
||||||
|
|
||||||
|
internal void OnLobbyCreatedAPI(LobbyCreated_t callback, bool error)
|
||||||
|
{
|
||||||
|
//from SpaceWarClient.cpp 793
|
||||||
|
if (error || (callback.Result != Result.OK))
|
||||||
|
{
|
||||||
|
if ( OnLobbyCreated != null) { OnLobbyCreated(false); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//set owner specific properties
|
||||||
|
Owner = client.SteamId;
|
||||||
|
CurrentLobby = callback.SteamIDLobby;
|
||||||
|
CurrentLobbyData = new LobbyData(client, CurrentLobby);
|
||||||
|
Name = client.Username + "'s Lobby";
|
||||||
|
CurrentLobbyData.SetData("appid", client.AppId.ToString());
|
||||||
|
LobbyType = createdLobbyType;
|
||||||
|
CurrentLobbyData.SetData("lobbytype", LobbyType.ToString());
|
||||||
|
Joinable = true;
|
||||||
|
if (OnLobbyCreated != null) { OnLobbyCreated(true); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback for when lobby is created. Parameter resolves true when the Lobby was successfully created
|
||||||
|
/// </summary>
|
||||||
|
public Action<bool> OnLobbyCreated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class to hold global lobby data. This is stuff like maps/modes/etc. Data set here can be filtered by LobbyList.
|
||||||
|
/// </summary>
|
||||||
|
public class LobbyData
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
internal ulong lobby;
|
||||||
|
internal Dictionary<string, string> data;
|
||||||
|
|
||||||
|
public LobbyData(Client c, ulong l)
|
||||||
|
{
|
||||||
|
client = c;
|
||||||
|
lobby = l;
|
||||||
|
data = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the lobby value for the specific key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="k">The key to find</param>
|
||||||
|
/// <returns>The value at key</returns>
|
||||||
|
public string GetData(string k)
|
||||||
|
{
|
||||||
|
if (data.ContainsKey(k))
|
||||||
|
{
|
||||||
|
return data[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "ERROR: key not found";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a list of all the data in the Lobby
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Dictionary of all the key/value pairs in the data</returns>
|
||||||
|
public Dictionary<string,string> GetAllData()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> returnData = new Dictionary<string, string>();
|
||||||
|
foreach(KeyValuePair<string, string> item in data)
|
||||||
|
{
|
||||||
|
returnData.Add(item.Key, item.Value);
|
||||||
|
}
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the value for specified Key. Note that the keys "joinable", "appid", "name", and "lobbytype" are reserved for internal library use.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="k">The key to set the value for</param>
|
||||||
|
/// <param name="v">The value of the Key</param>
|
||||||
|
/// <returns>True if data successfully set</returns>
|
||||||
|
public bool SetData(string k, string v)
|
||||||
|
{
|
||||||
|
if (data.ContainsKey(k))
|
||||||
|
{
|
||||||
|
if (data[k] == v) { return true; }
|
||||||
|
if (client.native.matchmaking.SetLobbyData(lobby, k, v))
|
||||||
|
{
|
||||||
|
data[k] = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (client.native.matchmaking.SetLobbyData(lobby, k, v))
|
||||||
|
{
|
||||||
|
data.Add(k, v);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the key from the LobbyData. Note that the keys "joinable", "appid", "name", and "lobbytype" are reserved for internal library use.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="k">The key to remove</param>
|
||||||
|
/// <returns>True if Key successfully removed</returns>
|
||||||
|
public bool RemoveData(string k)
|
||||||
|
{
|
||||||
|
if (data.ContainsKey(k))
|
||||||
|
{
|
||||||
|
if (client.native.matchmaking.DeleteLobbyData(lobby, k))
|
||||||
|
{
|
||||||
|
data.Remove(k);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets user data for the Lobby. Things like Character, Skin, Ready, etc. Can only set your own member data
|
||||||
|
/// </summary>
|
||||||
|
public void SetMemberData(string key, string value)
|
||||||
|
{
|
||||||
|
if(CurrentLobby == 0) { return; }
|
||||||
|
client.native.matchmaking.SetLobbyMemberData(CurrentLobby, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the per-user metadata from this lobby. Can get data from any user
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="steamID">ulong SteamID of the user you want to get data from</param>
|
||||||
|
/// <param name="key">String key of the type of data you want to get</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string GetMemberData(ulong steamID, string key)
|
||||||
|
{
|
||||||
|
if (CurrentLobby == 0) { return "ERROR: NOT IN ANY LOBBY"; }
|
||||||
|
return client.native.matchmaking.GetLobbyMemberData(CurrentLobby, steamID, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnLobbyDataUpdatedAPI(LobbyDataUpdate_t callback, bool error)
|
||||||
|
{
|
||||||
|
if(error || (callback.SteamIDLobby != CurrentLobby)) { return; }
|
||||||
|
if(callback.SteamIDLobby == CurrentLobby) //actual lobby data was updated by owner
|
||||||
|
{
|
||||||
|
UpdateLobbyData();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(UserIsInCurrentLobby(callback.SteamIDMember)) //some member of this lobby updated their information
|
||||||
|
{
|
||||||
|
if (OnLobbyMemberDataUpdated != null) { OnLobbyMemberDataUpdated(callback.SteamIDMember); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the LobbyData property to have the data for the current lobby, if any
|
||||||
|
/// </summary>
|
||||||
|
internal void UpdateLobbyData()
|
||||||
|
{
|
||||||
|
int dataCount = client.native.matchmaking.GetLobbyDataCount(CurrentLobby);
|
||||||
|
CurrentLobbyData = new LobbyData(client, CurrentLobby);
|
||||||
|
for (int i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
if (client.native.matchmaking.GetLobbyDataByIndex(CurrentLobby, i, out string key, out string value))
|
||||||
|
{
|
||||||
|
CurrentLobbyData.SetData(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(OnLobbyDataUpdated != null) { OnLobbyDataUpdated(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the lobby data itself has been updated. Called when someone has joined/left, Owner has updated data, etc.
|
||||||
|
/// </summary>
|
||||||
|
public Action OnLobbyDataUpdated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when a member of the lobby has updated either their personal Lobby metadata or someone's global steam state has changed (like a display name). Parameter is the user who changed.
|
||||||
|
/// </summary>
|
||||||
|
public Action<ulong> OnLobbyMemberDataUpdated;
|
||||||
|
|
||||||
|
|
||||||
|
public Type LobbyType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsValid) { return Type.Error; } //if we're currently in a valid server
|
||||||
|
|
||||||
|
//we know that we've set the lobby type via the lobbydata in the creation function
|
||||||
|
//ps this is important because steam doesn't have an easy way to get lobby type (why idk)
|
||||||
|
string lobbyType = CurrentLobbyData.GetData("lobbytype");
|
||||||
|
switch (lobbyType)
|
||||||
|
{
|
||||||
|
case "Private":
|
||||||
|
return Type.Private;
|
||||||
|
case "FriendsOnly":
|
||||||
|
return Type.FriendsOnly;
|
||||||
|
case "Invisible":
|
||||||
|
return Type.Invisible;
|
||||||
|
case "Public":
|
||||||
|
return Type.Public;
|
||||||
|
default:
|
||||||
|
return Type.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(!IsValid) { return; }
|
||||||
|
if(client.native.matchmaking.SetLobbyType(CurrentLobby, (SteamNative.LobbyType)value))
|
||||||
|
{
|
||||||
|
CurrentLobbyData.SetData("lobbytype", value.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void OnLobbyChatMessageRecievedAPI(LobbyChatMsg_t callback, bool error)
|
||||||
|
{
|
||||||
|
//from Client.Networking
|
||||||
|
if(error || callback.SteamIDLobby != CurrentLobby) { return; }
|
||||||
|
|
||||||
|
byte[] ReceiveBuffer = new byte[1024];
|
||||||
|
SteamNative.CSteamID steamid = 1;
|
||||||
|
ChatEntryType chatEntryType; //not used
|
||||||
|
int readData = 0;
|
||||||
|
fixed (byte* p = ReceiveBuffer)
|
||||||
|
{
|
||||||
|
readData = client.native.matchmaking.GetLobbyChatEntry(CurrentLobby, (int)callback.ChatID, out steamid, (IntPtr)p, ReceiveBuffer.Length, out chatEntryType);
|
||||||
|
while (ReceiveBuffer.Length < readData)
|
||||||
|
{
|
||||||
|
ReceiveBuffer = new byte[readData + 1024];
|
||||||
|
readData = client.native.matchmaking.GetLobbyChatEntry(CurrentLobby, (int)callback.ChatID, out steamid, (IntPtr)p, ReceiveBuffer.Length, out chatEntryType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OnChatMessageRecieved != null) { OnChatMessageRecieved(steamid, ReceiveBuffer, readData); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback to get chat messages. Use Encoding.UTF8.GetString to retrive the message.
|
||||||
|
/// </summary>
|
||||||
|
public Action<ulong, byte[], int> OnChatMessageRecieved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Broadcasts a chat message to the all the users in the lobby users in the lobby (including the local user) will receive a LobbyChatMsg_t callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if message successfully sent</returns>
|
||||||
|
public unsafe bool SendChatMessage(string message)
|
||||||
|
{
|
||||||
|
var data = Encoding.UTF8.GetBytes(message);
|
||||||
|
fixed (byte* p = data)
|
||||||
|
{
|
||||||
|
// pvMsgBody can be binary or text data, up to 4k
|
||||||
|
// if pvMsgBody is text, cubMsgBody should be strlen( text ) + 1, to include the null terminator
|
||||||
|
return client.native.matchmaking.SendLobbyChatMsg(CurrentLobby, (IntPtr)p, data.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enums to catch the state of a user when their state has changed
|
||||||
|
/// </summary>
|
||||||
|
public enum MemberStateChange
|
||||||
|
{
|
||||||
|
Entered = ChatMemberStateChange.Entered,
|
||||||
|
Left = ChatMemberStateChange.Left,
|
||||||
|
Disconnected = ChatMemberStateChange.Disconnected,
|
||||||
|
Kicked = ChatMemberStateChange.Kicked,
|
||||||
|
Banned = ChatMemberStateChange.Banned,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnLobbyStateUpdatedAPI(LobbyChatUpdate_t callback, bool error)
|
||||||
|
{
|
||||||
|
if (error || callback.SteamIDLobby != CurrentLobby) { return; }
|
||||||
|
MemberStateChange change = (MemberStateChange)callback.GfChatMemberStateChange;
|
||||||
|
ulong initiator = callback.SteamIDMakingChange;
|
||||||
|
ulong affected = callback.SteamIDUserChanged;
|
||||||
|
|
||||||
|
if (OnLobbyStateChanged != null) { OnLobbyStateChanged(change, initiator, affected); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the state of the Lobby is somehow shifted. Usually when someone joins or leaves the lobby.
|
||||||
|
/// The first ulong is the SteamID of the user that initiated the change.
|
||||||
|
/// The second ulong is the person that was affected
|
||||||
|
/// </summary>
|
||||||
|
public Action<MemberStateChange, ulong, ulong> OnLobbyStateChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the lobby as a property for easy getting/setting. Note that this is setting LobbyData, which you cannot do unless you are the Owner of the lobby
|
||||||
|
/// </summary>
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsValid) { return ""; }
|
||||||
|
return CurrentLobbyData.GetData("name");
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!IsValid) { return; }
|
||||||
|
CurrentLobbyData.SetData("name", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Owner of the current lobby. Returns 0 if you are not in a valid lobby.
|
||||||
|
/// </summary>
|
||||||
|
public ulong Owner
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IsValid)
|
||||||
|
{
|
||||||
|
return client.native.matchmaking.GetLobbyOwner(CurrentLobby);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Owner == value) return;
|
||||||
|
client.native.matchmaking.SetLobbyOwner(CurrentLobby, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is the Lobby joinable by other people? Defaults to true;
|
||||||
|
/// </summary>
|
||||||
|
public bool Joinable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsValid) { return false; }
|
||||||
|
string joinable = CurrentLobbyData.GetData("joinable");
|
||||||
|
switch (joinable)
|
||||||
|
{
|
||||||
|
case "true":
|
||||||
|
return true;
|
||||||
|
case "false":
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!IsValid) { return; }
|
||||||
|
if (client.native.matchmaking.SetLobbyJoinable(CurrentLobby, value))
|
||||||
|
{
|
||||||
|
CurrentLobbyData.SetData("joinable", value.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How many people can be in the Lobby
|
||||||
|
/// </summary>
|
||||||
|
public int MaxMembers
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsValid) { return 0; } //0 is default, but value is inited when lobby is created.
|
||||||
|
return client.native.matchmaking.GetLobbyMemberLimit(CurrentLobby);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!IsValid) { return; }
|
||||||
|
client.native.matchmaking.SetLobbyMemberLimit(CurrentLobby, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How many people are currently in the Lobby
|
||||||
|
/// </summary>
|
||||||
|
public int NumMembers
|
||||||
|
{
|
||||||
|
get { return client.native.matchmaking.GetNumLobbyMembers(CurrentLobby);}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Leave the CurrentLobby.
|
||||||
|
/// </summary>
|
||||||
|
public void Leave()
|
||||||
|
{
|
||||||
|
if (CurrentLobby != 0) { client.native.matchmaking.LeaveLobby(CurrentLobby); }
|
||||||
|
CurrentLobby = 0;
|
||||||
|
CurrentLobbyData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
client = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an array of all the CSteamIDs in the CurrentLobby.
|
||||||
|
/// Note that you must be in the Lobby you are trying to request the MemberIDs from.
|
||||||
|
/// Returns an empty array if you aren't in a lobby.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Array of member SteamIDs</returns>
|
||||||
|
public ulong[] GetMemberIDs()
|
||||||
|
{
|
||||||
|
|
||||||
|
ulong[] memIDs = new ulong[NumMembers];
|
||||||
|
for (int i = 0; i < NumMembers; i++)
|
||||||
|
{
|
||||||
|
memIDs[i] = client.native.matchmaking.GetLobbyMemberByIndex(CurrentLobby, i);
|
||||||
|
}
|
||||||
|
return memIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check to see if a user is in your CurrentLobby
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="steamID">SteamID of the user to check for</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool UserIsInCurrentLobby(ulong steamID)
|
||||||
|
{
|
||||||
|
if(CurrentLobby == 0) { return false; }
|
||||||
|
ulong[] mems = GetMemberIDs();
|
||||||
|
for (int i = 0; i < mems.Length; i++)
|
||||||
|
{
|
||||||
|
if(mems[i] == steamID)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invites the specified user to the CurrentLobby the user is in.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="friendID">ulong ID of person to invite</param>
|
||||||
|
public bool InviteUserToLobby(ulong friendID)
|
||||||
|
{
|
||||||
|
return client.native.matchmaking.InviteUserToLobby(CurrentLobby, friendID);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnUserInvitedToLobbyAPI(LobbyInvite_t callback, bool error)
|
||||||
|
{
|
||||||
|
if (error || (callback.GameID != client.AppId)) { return; }
|
||||||
|
if (OnUserInvitedToLobby != null) { OnUserInvitedToLobby(callback.SteamIDLobby, callback.SteamIDUser); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when a user invites the current user to a lobby. The first parameter is the lobby the user was invited to, the second is the CSteamID of the person who invited this user
|
||||||
|
/// </summary>
|
||||||
|
public Action<ulong, ulong> OnUserInvitedToLobby;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Joins a lobby if a request was made to join the lobby through the friends list or an invite
|
||||||
|
/// </summary>
|
||||||
|
internal void OnLobbyJoinRequestedAPI(GameLobbyJoinRequested_t callback, bool error)
|
||||||
|
{
|
||||||
|
if (error) { return; }
|
||||||
|
Join(callback.SteamIDLobby);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes sure we send an update callback if a Lobby user updates their information
|
||||||
|
/// </summary>
|
||||||
|
internal void OnLobbyMemberPersonaChangeAPI(PersonaStateChange_t callback, bool error)
|
||||||
|
{
|
||||||
|
if (error || !UserIsInCurrentLobby(callback.SteamID)) { return; }
|
||||||
|
if (OnLobbyMemberDataUpdated != null) { OnLobbyMemberDataUpdated(callback.SteamID); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*not implemented
|
||||||
|
|
||||||
|
//set the game server of the lobby
|
||||||
|
client.native.matchmaking.GetLobbyGameServer;
|
||||||
|
client.native.matchmaking.SetLobbyGameServer;
|
||||||
|
|
||||||
|
//used with game server stuff
|
||||||
|
SteamNative.LobbyGameCreated_t
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
33
Facepunch.Steamworks/Client/LobbyList.Lobby.cs
Normal file
33
Facepunch.Steamworks/Client/LobbyList.Lobby.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class LobbyList
|
||||||
|
{
|
||||||
|
public class Lobby
|
||||||
|
{
|
||||||
|
internal Client Client;
|
||||||
|
public string Name { get; private set; }
|
||||||
|
public ulong LobbyID { get; private set; }
|
||||||
|
public ulong Owner { get; private set; }
|
||||||
|
public int MemberLimit{ get; private set; }
|
||||||
|
public int NumMembers{ get; private set; }
|
||||||
|
|
||||||
|
internal static Lobby FromSteam(Client client, ulong lobby)
|
||||||
|
{
|
||||||
|
return new Lobby()
|
||||||
|
{
|
||||||
|
Client = client,
|
||||||
|
LobbyID = lobby,
|
||||||
|
Name = client.native.matchmaking.GetLobbyData(lobby, "name"),
|
||||||
|
MemberLimit = client.native.matchmaking.GetLobbyMemberLimit(lobby),
|
||||||
|
Owner = client.native.matchmaking.GetLobbyOwner(lobby),
|
||||||
|
NumMembers = client.native.matchmaking.GetNumLobbyMembers(lobby)
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
183
Facepunch.Steamworks/Client/LobbyList.cs
Normal file
183
Facepunch.Steamworks/Client/LobbyList.cs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Facepunch.Steamworks
|
||||||
|
{
|
||||||
|
public partial class LobbyList : IDisposable
|
||||||
|
{
|
||||||
|
internal Client client;
|
||||||
|
|
||||||
|
//The list of retrieved lobbies
|
||||||
|
public List<Lobby> Lobbies { get; private set; }
|
||||||
|
|
||||||
|
//True when all the possible lobbies have had their data updated
|
||||||
|
//if the number of lobbies is now equal to the initial request number, we've found all lobbies
|
||||||
|
public bool Finished { get; private set; }
|
||||||
|
|
||||||
|
//The number of possible lobbies we can get data from
|
||||||
|
internal List<ulong> requests;
|
||||||
|
|
||||||
|
internal LobbyList(Client client)
|
||||||
|
{
|
||||||
|
this.client = client;
|
||||||
|
Lobbies = new List<Lobby>();
|
||||||
|
requests = new List<ulong>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Refresh the List of Lobbies. If no filter is passed in, a default one is created that filters based on AppId ("appid").
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filter"></param>
|
||||||
|
public void Refresh ( Filter filter = null)
|
||||||
|
{
|
||||||
|
//init out values
|
||||||
|
Lobbies.Clear();
|
||||||
|
requests.Clear();
|
||||||
|
Finished = false;
|
||||||
|
|
||||||
|
if (filter == null)
|
||||||
|
{
|
||||||
|
filter = new Filter();
|
||||||
|
filter.StringFilters.Add("appid", client.AppId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
client.native.matchmaking.AddRequestLobbyListDistanceFilter((SteamNative.LobbyDistanceFilter)filter.DistanceFilter);
|
||||||
|
|
||||||
|
if (filter.SlotsAvailable != null)
|
||||||
|
{
|
||||||
|
client.native.matchmaking.AddRequestLobbyListFilterSlotsAvailable((int)filter.SlotsAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.MaxResults != null)
|
||||||
|
{
|
||||||
|
client.native.matchmaking.AddRequestLobbyListResultCountFilter((int)filter.MaxResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, string> fil in filter.StringFilters)
|
||||||
|
{
|
||||||
|
client.native.matchmaking.AddRequestLobbyListStringFilter(fil.Key, fil.Value, SteamNative.LobbyComparison.Equal);
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<string, int> fil in filter.NearFilters)
|
||||||
|
{
|
||||||
|
client.native.matchmaking.AddRequestLobbyListNearValueFilter(fil.Key, fil.Value);
|
||||||
|
}
|
||||||
|
//foreach (KeyValuePair<string, KeyValuePair<Filter.Comparison, int>> fil in filter.NumericalFilters)
|
||||||
|
//{
|
||||||
|
// client.native.matchmaking.AddRequestLobbyListNumericalFilter(fil.Key, fil.Value.Value, (SteamNative.LobbyComparison)fil.Value.Key);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
// this will never return lobbies that are full (via the actual api)
|
||||||
|
client.native.matchmaking.RequestLobbyList(OnLobbyList);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OnLobbyList(LobbyMatchList_t callback, bool error)
|
||||||
|
{
|
||||||
|
if (error) return;
|
||||||
|
|
||||||
|
//how many lobbies matched
|
||||||
|
uint lobbiesMatching = callback.LobbiesMatching;
|
||||||
|
|
||||||
|
// lobbies are returned in order of closeness to the user, so add them to the list in that order
|
||||||
|
for (int i = 0; i < lobbiesMatching; i++)
|
||||||
|
{
|
||||||
|
//add the lobby to the list of requests
|
||||||
|
ulong lobby = client.native.matchmaking.GetLobbyByIndex(i);
|
||||||
|
requests.Add(lobby);
|
||||||
|
|
||||||
|
//cast to a LobbyList.Lobby
|
||||||
|
Lobby newLobby = Lobby.FromSteam(client, lobby);
|
||||||
|
if (newLobby.Name != "")
|
||||||
|
{
|
||||||
|
//if the lobby is valid add it to the valid return lobbies
|
||||||
|
Lobbies.Add(newLobby);
|
||||||
|
checkFinished();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//else we need to get the info for the missing lobby
|
||||||
|
client.native.matchmaking.RequestLobbyData(lobby);
|
||||||
|
SteamNative.LobbyDataUpdate_t.RegisterCallback(client, OnLobbyDataUpdated);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
checkFinished();
|
||||||
|
|
||||||
|
if (OnLobbiesUpdated != null) { OnLobbiesUpdated(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkFinished()
|
||||||
|
{
|
||||||
|
if (Lobbies.Count == requests.Count)
|
||||||
|
{
|
||||||
|
Finished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Finished = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLobbyDataUpdated(LobbyDataUpdate_t callback, bool error)
|
||||||
|
{
|
||||||
|
if (callback.Success == 1) //1 if success, 0 if failure
|
||||||
|
{
|
||||||
|
//find the lobby that has been updated
|
||||||
|
Lobby lobby = Lobbies.Find(x => x.LobbyID == callback.SteamIDLobby);
|
||||||
|
|
||||||
|
//if this lobby isn't yet in the list of lobbies, we know that we should add it
|
||||||
|
if (lobby == null)
|
||||||
|
{
|
||||||
|
Lobbies.Add(lobby);
|
||||||
|
checkFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
//otherwise lobby data in general was updated and you should listen to see what changed
|
||||||
|
if (OnLobbiesUpdated != null) { OnLobbiesUpdated(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action OnLobbiesUpdated;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
client = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Filter
|
||||||
|
{
|
||||||
|
// Filters that match actual metadata keys exactly
|
||||||
|
public Dictionary<string, string> StringFilters = new Dictionary<string, string>();
|
||||||
|
// Filters that are of string key and int value for that key to be close to
|
||||||
|
public Dictionary<string, int> NearFilters = new Dictionary<string, int>();
|
||||||
|
//Filters that are of string key and int value, with a comparison filter to say how we should relate to the value
|
||||||
|
//public Dictionary<string, KeyValuePair<Comparison, int>> NumericalFilters = new Dictionary<string, KeyValuePair<Comparison, int>>();
|
||||||
|
public Distance DistanceFilter = Distance.Worldwide;
|
||||||
|
public int? SlotsAvailable { get; set; }
|
||||||
|
public int? MaxResults { get; set; }
|
||||||
|
|
||||||
|
public enum Distance : int
|
||||||
|
{
|
||||||
|
Close = SteamNative.LobbyDistanceFilter.Close,
|
||||||
|
Default = SteamNative.LobbyDistanceFilter.Default,
|
||||||
|
Far = SteamNative.LobbyDistanceFilter.Far,
|
||||||
|
Worldwide = SteamNative.LobbyDistanceFilter.Worldwide
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Comparison : int
|
||||||
|
{
|
||||||
|
EqualToOrLessThan = SteamNative.LobbyComparison.EqualToOrLessThan,
|
||||||
|
LessThan = SteamNative.LobbyComparison.LessThan,
|
||||||
|
Equal = SteamNative.LobbyComparison.Equal,
|
||||||
|
GreaterThan = SteamNative.LobbyComparison.GreaterThan,
|
||||||
|
EqualToOrGreaterThan = SteamNative.LobbyComparison.EqualToOrGreaterThan,
|
||||||
|
NotEqual = SteamNative.LobbyComparison.NotEqual
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -91,6 +91,8 @@ internal bool Update( SteamNative.SteamMatchmakingServers servers, Action<SteamN
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Action OnUpdate;
|
public Action OnUpdate;
|
||||||
|
public Action<Server> OnServerResponded;
|
||||||
|
public Action OnFinished;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of servers that responded. If you're only interested in servers that responded since you
|
/// A list of servers that responded. If you're only interested in servers that responded since you
|
||||||
@ -181,6 +183,8 @@ private void Update()
|
|||||||
{
|
{
|
||||||
Finished = true;
|
Finished = true;
|
||||||
client.OnUpdate -= Update;
|
client.OnUpdate -= Update;
|
||||||
|
|
||||||
|
OnFinished?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +195,10 @@ private void OnServer( SteamNative.gameserveritem_t info )
|
|||||||
if ( Filter != null && !Filter.Test( info ) )
|
if ( Filter != null && !Filter.Test( info ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Responded.Add( Server.FromSteam( client, info ) );
|
var s = Server.FromSteam( client, info );
|
||||||
|
Responded.Add( s );
|
||||||
|
|
||||||
|
OnServerResponded?.Invoke( s );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ public class Server
|
|||||||
public int Version { get; set; }
|
public int Version { get; set; }
|
||||||
public string[] Tags { get; set; }
|
public string[] Tags { get; set; }
|
||||||
public ulong SteamId { get; set; }
|
public ulong SteamId { get; set; }
|
||||||
public uint Address { get; set; }
|
public IPAddress Address { get; set; }
|
||||||
public int ConnectionPort { get; set; }
|
public int ConnectionPort { get; set; }
|
||||||
public int QueryPort { get; set; }
|
public int QueryPort { get; set; }
|
||||||
|
|
||||||
@ -42,27 +43,13 @@ public bool Favourite
|
|||||||
|
|
||||||
internal Client Client;
|
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, SteamNative.gameserveritem_t item )
|
internal static Server FromSteam( Client client, SteamNative.gameserveritem_t item )
|
||||||
{
|
{
|
||||||
return new Server()
|
return new Server()
|
||||||
{
|
{
|
||||||
Client = client,
|
Client = client,
|
||||||
Address = item.NetAdr.IP,
|
Address = Utility.Int32ToIp( item.NetAdr.IP ),
|
||||||
ConnectionPort = item.NetAdr.ConnectionPort,
|
ConnectionPort = item.NetAdr.ConnectionPort,
|
||||||
QueryPort = item.NetAdr.QueryPort,
|
QueryPort = item.NetAdr.QueryPort,
|
||||||
Name = item.ServerName,
|
Name = item.ServerName,
|
||||||
@ -133,7 +120,7 @@ internal void OnServerRulesReceiveFinished( bool Success )
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddToHistory()
|
public void AddToHistory()
|
||||||
{
|
{
|
||||||
Client.native.matchmaking.AddFavoriteGame( AppId, Address, (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagHistory, (uint)Utility.Epoch.Current );
|
Client.native.matchmaking.AddFavoriteGame( AppId, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagHistory, (uint)Utility.Epoch.Current );
|
||||||
Client.ServerList.UpdateFavouriteList();
|
Client.ServerList.UpdateFavouriteList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +129,7 @@ public void AddToHistory()
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RemoveFromHistory()
|
public void RemoveFromHistory()
|
||||||
{
|
{
|
||||||
Client.native.matchmaking.RemoveFavoriteGame( AppId, Address, (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagHistory );
|
Client.native.matchmaking.RemoveFavoriteGame( AppId, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagHistory );
|
||||||
Client.ServerList.UpdateFavouriteList();
|
Client.ServerList.UpdateFavouriteList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +138,7 @@ public void RemoveFromHistory()
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddToFavourites()
|
public void AddToFavourites()
|
||||||
{
|
{
|
||||||
Client.native.matchmaking.AddFavoriteGame( AppId, Address, (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite, (uint)Utility.Epoch.Current );
|
Client.native.matchmaking.AddFavoriteGame( AppId, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite, (uint)Utility.Epoch.Current );
|
||||||
Client.ServerList.UpdateFavouriteList();
|
Client.ServerList.UpdateFavouriteList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +147,7 @@ public void AddToFavourites()
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RemoveFromFavourites()
|
public void RemoveFromFavourites()
|
||||||
{
|
{
|
||||||
Client.native.matchmaking.RemoveFavoriteGame( AppId, Address, (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite );
|
Client.native.matchmaking.RemoveFavoriteGame( AppId, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite );
|
||||||
Client.ServerList.UpdateFavouriteList();
|
Client.ServerList.UpdateFavouriteList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ public Request Local( Filter filter = null )
|
|||||||
|
|
||||||
internal bool IsFavourite( Server server )
|
internal bool IsFavourite( Server server )
|
||||||
{
|
{
|
||||||
ulong encoded = server.Address;
|
ulong encoded = Utility.IpToInt32( server.Address );
|
||||||
encoded = encoded << 32;
|
encoded = encoded << 32;
|
||||||
encoded = encoded | (uint)server.ConnectionPort;
|
encoded = encoded | (uint)server.ConnectionPort;
|
||||||
|
|
||||||
@ -257,7 +257,7 @@ internal bool IsFavourite( Server server )
|
|||||||
|
|
||||||
internal bool IsHistory( Server server )
|
internal bool IsHistory( Server server )
|
||||||
{
|
{
|
||||||
ulong encoded = server.Address;
|
ulong encoded = Utility.IpToInt32( server.Address );
|
||||||
encoded = encoded << 32;
|
encoded = encoded << 32;
|
||||||
encoded = encoded | (uint)server.ConnectionPort;
|
encoded = encoded | (uint)server.ConnectionPort;
|
||||||
|
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netstandard1.6</TargetFramework>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<AssemblyName>Facepunch.Steamworks</AssemblyName>
|
|
||||||
<PackageId>Facepunch.Steamworks</PackageId>
|
|
||||||
<NetStandardImplicitPackageVersion>1.6.0</NetStandardImplicitPackageVersion>
|
|
||||||
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
|
|
||||||
<RootNamespace>Facepunch.Steamworks</RootNamespace>
|
|
||||||
<Description />
|
|
||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
|
||||||
<DefineConstants>TRACE;DEBUG;NETSTANDARD1_6;NETCORE</DefineConstants>
|
|
||||||
<NoWarn>1701;1702;1705;618;1591</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
|
||||||
<DefineConstants>TRACE;RELEASE;NETSTANDARD1_6;NETCORE</DefineConstants>
|
|
||||||
<NoWarn>1701;1702;1705;618;1591</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,23 +1,40 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net3.5</TargetFramework>
|
|
||||||
|
<TargetFrameworks>netstandard2.0;net45;net35;net40</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<AssemblyName>Facepunch.Steamworks</AssemblyName>
|
<AssemblyName>Facepunch.Steamworks</AssemblyName>
|
||||||
<PackageId>Facepunch.Steamworks</PackageId>
|
|
||||||
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<RootNamespace>Facepunch.Steamworks</RootNamespace>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DefineConstants>TRACE;DEBUG;NETSTANDARD1_6;NETCORE</DefineConstants>
|
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||||
<NoWarn>1701;1702;1705;618;1591</NoWarn>
|
<NoWarn>1701;1702;1705;618;1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DefineConstants>TRACE;RELEASE;NETSTANDARD1_6;NETCORE</DefineConstants>
|
<DefineConstants>TRACE;RELEASE</DefineConstants>
|
||||||
<NoWarn>1701;1702;1705;618;1591</NoWarn>
|
<NoWarn>1701;1702;1705;618;1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
||||||
|
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="*AssemblyInfo.cs"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<FrameworkPathOverride Condition="'$(TargetFramework)' == 'net35'">C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client</FrameworkPathOverride>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<FrameworkPathOverride Condition="'$(TargetFramework)' == 'net40'">C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client</FrameworkPathOverride>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -25,6 +25,7 @@ public class Editor
|
|||||||
public ItemType? Type { get; set; }
|
public ItemType? Type { get; set; }
|
||||||
public string Error { get; internal set; } = null;
|
public string Error { get; internal set; } = null;
|
||||||
public string ChangeNote { get; set; } = "";
|
public string ChangeNote { get; set; } = "";
|
||||||
|
public uint WorkshopUploadAppId { get; set; }
|
||||||
|
|
||||||
public enum VisibilityType : int
|
public enum VisibilityType : int
|
||||||
{
|
{
|
||||||
@ -113,8 +114,7 @@ private void StartCreatingItem()
|
|||||||
if ( !Type.HasValue )
|
if ( !Type.HasValue )
|
||||||
throw new System.Exception( "Editor.Type must be set when creating a new item!" );
|
throw new System.Exception( "Editor.Type must be set when creating a new item!" );
|
||||||
|
|
||||||
System.Diagnostics.Debug.WriteLine( "StartCreatingItem()" );
|
CreateItem = workshop.ugc.CreateItem( WorkshopUploadAppId, (SteamNative.WorkshopFileType)(uint)Type, OnItemCreated );
|
||||||
CreateItem = workshop.ugc.CreateItem( workshop.steamworks.AppId, (SteamNative.WorkshopFileType)(uint)Type, OnItemCreated );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnItemCreated( SteamNative.CreateItemResult_t obj, bool Failed )
|
private void OnItemCreated( SteamNative.CreateItemResult_t obj, bool Failed )
|
||||||
@ -140,7 +140,7 @@ private void OnItemCreated( SteamNative.CreateItemResult_t obj, bool Failed )
|
|||||||
|
|
||||||
private void PublishChanges()
|
private void PublishChanges()
|
||||||
{
|
{
|
||||||
UpdateHandle = workshop.ugc.StartItemUpdate( workshop.steamworks.AppId, Id );
|
UpdateHandle = workshop.ugc.StartItemUpdate(WorkshopUploadAppId, Id );
|
||||||
|
|
||||||
if ( Title != null )
|
if ( Title != null )
|
||||||
workshop.ugc.SetItemTitle( UpdateHandle, Title );
|
workshop.ugc.SetItemTitle( UpdateHandle, Title );
|
||||||
|
@ -267,7 +267,12 @@ public void Block()
|
|||||||
|
|
||||||
while ( IsRunning )
|
while ( IsRunning )
|
||||||
{
|
{
|
||||||
System.Threading.Thread.Sleep( 10 );
|
const int waitPeriodMillis = 10;
|
||||||
|
#if NETCORE
|
||||||
|
System.Threading.Tasks.Task.Delay( waitPeriodMillis ).Wait();
|
||||||
|
#else
|
||||||
|
System.Threading.Thread.Sleep( waitPeriodMillis );
|
||||||
|
#endif
|
||||||
workshop.steamworks.Update();
|
workshop.steamworks.Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,18 @@ public Query CreateQuery()
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Editor CreateItem( ItemType type )
|
public Editor CreateItem( ItemType type )
|
||||||
{
|
{
|
||||||
return new Editor() { workshop = this, Type = type };
|
return CreateItem(this.steamworks.AppId, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new Editor object with the intention of creating a new item.
|
||||||
|
/// Your item won't actually be created until you call Publish() on the object.
|
||||||
|
/// Your item will be published to the provided appId.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>You need to add app publish permissions for cross app uploading to work.</remarks>
|
||||||
|
public Editor CreateItem( uint workshopUploadAppId, ItemType type )
|
||||||
|
{
|
||||||
|
return new Editor() { workshop = this, WorkshopUploadAppId = workshopUploadAppId, Type = type };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -39,22 +39,34 @@ internal bool InitClient( BaseSteamworks steamworks )
|
|||||||
api = new SteamNative.SteamApi();
|
api = new SteamNative.SteamApi();
|
||||||
|
|
||||||
if ( !api.SteamAPI_Init() )
|
if ( !api.SteamAPI_Init() )
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine( "InitClient: SteamAPI_Init returned false" );
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
hUser = api.SteamAPI_GetHSteamUser();
|
hUser = api.SteamAPI_GetHSteamUser();
|
||||||
hPipe = api.SteamAPI_GetHSteamPipe();
|
hPipe = api.SteamAPI_GetHSteamPipe();
|
||||||
if ( hPipe == 0 )
|
if ( hPipe == 0 )
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine( "InitClient: hPipe == 0" );
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FillInterfaces( steamworks, hUser, hPipe );
|
FillInterfaces( steamworks, hUser, hPipe );
|
||||||
|
|
||||||
if ( !user.IsValid )
|
if ( !user.IsValid )
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine( "InitClient: ISteamUser is null" );
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that the user has logged into Steam. This will always return true if the game is launched
|
// Ensure that the user has logged into Steam. This will always return true if the game is launched
|
||||||
// from Steam, but if Steam is at the login prompt when you run your game it will return false.
|
// from Steam, but if Steam is at the login prompt when you run your game it will return false.
|
||||||
if ( !user.BLoggedOn() )
|
if ( !user.BLoggedOn() )
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine( "InitClient: Not Logged On" );
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -67,13 +79,17 @@ internal bool InitServer( BaseSteamworks steamworks, uint IpAddress /*uint32*/,
|
|||||||
|
|
||||||
if ( !api.SteamInternal_GameServer_Init( IpAddress, usPort, GamePort, QueryPort, eServerMode, pchVersionString ) )
|
if ( !api.SteamInternal_GameServer_Init( IpAddress, usPort, GamePort, QueryPort, eServerMode, pchVersionString ) )
|
||||||
{
|
{
|
||||||
|
Console.Error.WriteLine( "InitServer: GameServer_Init returned false" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hUser = api.SteamGameServer_GetHSteamUser();
|
hUser = api.SteamGameServer_GetHSteamUser();
|
||||||
hPipe = api.SteamGameServer_GetHSteamPipe();
|
hPipe = api.SteamGameServer_GetHSteamPipe();
|
||||||
if ( hPipe == 0 )
|
if ( hPipe == 0 )
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine( "InitServer: hPipe == 0" );
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FillInterfaces( steamworks, hPipe, hUser );
|
FillInterfaces( steamworks, hPipe, hUser );
|
||||||
|
|
||||||
@ -116,27 +132,6 @@ public void FillInterfaces( BaseSteamworks steamworks, int hpipe, int huser )
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if ( client != null )
|
|
||||||
{
|
|
||||||
if ( hPipe != 0 )
|
|
||||||
{
|
|
||||||
if ( hUser != 0 )
|
|
||||||
{
|
|
||||||
client.ReleaseUser( hPipe, hUser );
|
|
||||||
hUser = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.BReleaseSteamPipe( hPipe );
|
|
||||||
hPipe = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !client.BShutdownIfAllPipesClosed() )
|
|
||||||
Console.WriteLine( "BShutdownIfAllPipesClosed returned false" );
|
|
||||||
|
|
||||||
client.Dispose();
|
|
||||||
client = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( user != null )
|
if ( user != null )
|
||||||
{
|
{
|
||||||
user.Dispose();
|
user.Dispose();
|
||||||
@ -187,11 +182,6 @@ public void Dispose()
|
|||||||
|
|
||||||
if ( gameServer != null )
|
if ( gameServer != null )
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// Calling this can cause the process to hang
|
|
||||||
//
|
|
||||||
//gameServer.LogOff();
|
|
||||||
|
|
||||||
gameServer.Dispose();
|
gameServer.Dispose();
|
||||||
gameServer = null;
|
gameServer = null;
|
||||||
}
|
}
|
||||||
@ -232,6 +222,12 @@ public void Dispose()
|
|||||||
applist = null;
|
applist = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( client != null )
|
||||||
|
{
|
||||||
|
client.Dispose();
|
||||||
|
client = null;
|
||||||
|
}
|
||||||
|
|
||||||
if ( api != null )
|
if ( api != null )
|
||||||
{
|
{
|
||||||
if ( isServer )
|
if ( isServer )
|
||||||
@ -239,6 +235,16 @@ public void Dispose()
|
|||||||
else
|
else
|
||||||
api.SteamAPI_Shutdown();
|
api.SteamAPI_Shutdown();
|
||||||
|
|
||||||
|
//
|
||||||
|
// The functions above destroy the pipeline handles
|
||||||
|
// and all of the classes. Trying to call a steam function
|
||||||
|
// at this point will result in a crash - because any
|
||||||
|
// pointers we stored are not invalid.
|
||||||
|
//
|
||||||
|
|
||||||
|
hPipe = 0;
|
||||||
|
hUser = 0;
|
||||||
|
|
||||||
api.Dispose();
|
api.Dispose();
|
||||||
api = null;
|
api = null;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ class ServerRules : IDisposable
|
|||||||
// The server that called us
|
// The server that called us
|
||||||
private ServerList.Server Server;
|
private ServerList.Server Server;
|
||||||
|
|
||||||
public ServerRules( ServerList.Server server, uint address, int queryPort )
|
public ServerRules( ServerList.Server server, IPAddress address, int queryPort )
|
||||||
{
|
{
|
||||||
Server = server;
|
Server = server;
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ public ServerRules( ServerList.Server server, uint address, int queryPort )
|
|||||||
//
|
//
|
||||||
// Ask Steam to get the server rules, respond to our fake vtable
|
// Ask Steam to get the server rules, respond to our fake vtable
|
||||||
//
|
//
|
||||||
Server.Client.native.servers.ServerRules( address, (ushort)queryPort, GetPtr() );
|
Server.Client.native.servers.ServerRules( Utility.IpToInt32( address ), (ushort)queryPort, GetPtr() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -26,6 +26,11 @@ public partial class Server : BaseSteamworks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Server( uint appId, ServerInit init )
|
public Server( uint appId, ServerInit init )
|
||||||
{
|
{
|
||||||
|
if ( Instance != null )
|
||||||
|
{
|
||||||
|
throw new System.Exception( "Only one Facepunch.Steamworks.Server can exist - dispose the old one before trying to create a new one." );
|
||||||
|
}
|
||||||
|
|
||||||
Instance = this;
|
Instance = this;
|
||||||
native = new Interop.NativeInterface();
|
native = new Interop.NativeInterface();
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Facepunch.Steamworks
|
namespace Facepunch.Steamworks
|
||||||
@ -15,6 +16,17 @@ static internal uint SwapBytes( uint x )
|
|||||||
( ( x & 0xff000000 ) >> 24 );
|
( ( x & 0xff000000 ) >> 24 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static internal uint IpToInt32( this IPAddress ipAddress )
|
||||||
|
{
|
||||||
|
return BitConverter.ToUInt32( ipAddress.GetAddressBytes().Reverse().ToArray(), 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static internal IPAddress Int32ToIp( uint ipAddress )
|
||||||
|
{
|
||||||
|
return new IPAddress( BitConverter.GetBytes( ipAddress ).Reverse().ToArray() );
|
||||||
|
}
|
||||||
|
|
||||||
static internal int NextPowerOf2( int x )
|
static internal int NextPowerOf2( int x )
|
||||||
{
|
{
|
||||||
var po2 = 1;
|
var po2 = 1;
|
||||||
|
15
Jenkinsfile
vendored
15
Jenkinsfile
vendored
@ -4,22 +4,13 @@ node ( 'vs2017' )
|
|||||||
checkout scm
|
checkout scm
|
||||||
|
|
||||||
stage 'Restore'
|
stage 'Restore'
|
||||||
bat 'nuget restore Facepunch.Steamworks.sln'
|
bat "dotnet restore Facepunch.Steamworks/Facepunch.Steamworks.csproj"
|
||||||
|
|
||||||
stage 'Build Release'
|
stage 'Build Release'
|
||||||
bat "\"${tool 'MSBuild'}\" Facepunch.Steamworks/Facepunch.Steamworks.csproj /p:Configuration=Release /p:ProductVersion=1.0.0.${env.BUILD_NUMBER}"
|
bat "dotnet build Facepunch.Steamworks/Facepunch.Steamworks.csproj --configuration Release"
|
||||||
|
|
||||||
stage 'Build Debug'
|
stage 'Build Debug'
|
||||||
bat "\"${tool 'MSBuild'}\" Facepunch.Steamworks/Facepunch.Steamworks.csproj /p:Configuration=Debug /p:ProductVersion=1.0.0.${env.BUILD_NUMBER}"
|
bat "dotnet build Facepunch.Steamworks/Facepunch.Steamworks.csproj --configuration Debug"
|
||||||
|
|
||||||
stage 'Build Release NetCore'
|
|
||||||
bat "dotnet restore Facepunch.Steamworks/Facepunch.Steamworks.NetCore.csproj"
|
|
||||||
|
|
||||||
stage 'Build Release NetCore'
|
|
||||||
bat "dotnet build Facepunch.Steamworks/Facepunch.Steamworks.NetCore.csproj --configuration Release"
|
|
||||||
|
|
||||||
stage 'Build Debug NetCore'
|
|
||||||
bat "dotnet build Facepunch.Steamworks/Facepunch.Steamworks.NetCore.csproj --configuration Debug"
|
|
||||||
|
|
||||||
stage 'Archive'
|
stage 'Archive'
|
||||||
archiveArtifacts artifacts: 'Facepunch.Steamworks/bin/**/*'
|
archiveArtifacts artifacts: 'Facepunch.Steamworks/bin/**/*'
|
||||||
|
30
README.md
30
README.md
@ -41,7 +41,7 @@ You can view examples of everything in the Facepunch.Steamworks.Test project.
|
|||||||
|
|
||||||
## Client
|
## Client
|
||||||
|
|
||||||
Compile and add the library to your project. To create a client you can do this.
|
Compile the Facepunch.Steamworks project and add the library to your Unity project. To create a client you can do this.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var client = new Facepunch.Steamworks.Client( 252490 );
|
var client = new Facepunch.Steamworks.Client( 252490 );
|
||||||
@ -68,6 +68,34 @@ var server = new Facepunch.Steamworks.Server( 252490, 0, 28015, true, "MyGame453
|
|||||||
|
|
||||||
This will register a secure server for game 252490, any ip, port 28015. Again, more usage in the Facepunch.Steamworks.Test project.
|
This will register a secure server for game 252490, any ip, port 28015. Again, more usage in the Facepunch.Steamworks.Test project.
|
||||||
|
|
||||||
|
## Lobby
|
||||||
|
|
||||||
|
To create a Lobby do this.
|
||||||
|
```csharp
|
||||||
|
client.Lobby.Create(Steamworks.Lobby.Type.Public, 10);
|
||||||
|
```
|
||||||
|
|
||||||
|
Created lobbies are auto-joined, but if you want to find a friend's lobby, you'd call
|
||||||
|
```csharp
|
||||||
|
client.LobbyList.Refresh();
|
||||||
|
//wait for the callback
|
||||||
|
client.LobbyList.OnLobbiesUpdated = () =>
|
||||||
|
{
|
||||||
|
if (client.LobbyList.Finished)
|
||||||
|
{
|
||||||
|
foreach (LobbyList.Lobby lobby in client.LobbyList.Lobbies)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Found Lobby: {lobby.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//join a lobby you found
|
||||||
|
client.Lobby.Join(LobbyList.Lobbies[0]);
|
||||||
|
```
|
||||||
|
|
||||||
|
Your can find more examples of Lobby functionality in the Lobby.cs file in the test project. Sending chat messages, assinging lobby data and member data, etc.
|
||||||
|
|
||||||
|
|
||||||
# Unity
|
# Unity
|
||||||
|
|
||||||
Yeah this works under Unity. That's half the point of it.
|
Yeah this works under Unity. That's half the point of it.
|
||||||
|
Loading…
Reference in New Issue
Block a user