diff --git a/Facepunch.Steamworks/SteamClient.cs b/Facepunch.Steamworks/SteamClient.cs
index 742f8f5..018235f 100644
--- a/Facepunch.Steamworks/SteamClient.cs
+++ b/Facepunch.Steamworks/SteamClient.cs
@@ -42,6 +42,7 @@ namespace Steamworks
SteamInventory.InstallEvents();
SteamNetworking.InstallEvents();
SteamMatchmaking.InstallEvents();
+ SteamParties.InstallEvents();
RunCallbacksAsync();
}
@@ -82,6 +83,7 @@ namespace Steamworks
SteamInventory.Shutdown();
SteamNetworking.Shutdown();
SteamMatchmaking.Shutdown();
+ SteamParties.Shutdown();
SteamAPI.Shutdown();
}
diff --git a/Facepunch.Steamworks/SteamParties.cs b/Facepunch.Steamworks/SteamParties.cs
new file mode 100644
index 0000000..b961f19
--- /dev/null
+++ b/Facepunch.Steamworks/SteamParties.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Steamworks.Data;
+
+namespace Steamworks
+{
+ public static class SteamParties
+ {
+ static ISteamParties _internal;
+ internal static ISteamParties Internal
+ {
+ get
+ {
+ if ( _internal == null )
+ _internal = new ISteamParties();
+
+ return _internal;
+ }
+ }
+ internal static void Shutdown()
+ {
+ _internal = null;
+ }
+
+ internal static void InstallEvents()
+ {
+ AvailableBeaconLocationsUpdated_t.Install( x => OnBeaconLocationsUpdated?.Invoke() );
+ ActiveBeaconsUpdated_t.Install( x => OnBeaconLocationsUpdated?.Invoke() );
+ }
+
+ ///
+ /// The list of possible Party beacon locations has changed
+ ///
+ public static event Action OnBeaconLocationsUpdated;
+
+ ///
+ /// The list of active beacons may have changed
+ ///
+ public static event Action OnActiveBeaconsUpdated;
+
+
+ public static int ActiveBeaconCount => (int) Internal.GetNumActiveBeacons();
+
+ public static IEnumerable ActiveBeacons
+ {
+ get
+ {
+ for ( uint i = 0; i < ActiveBeaconCount; i++ )
+ {
+ yield return new PartyBeacon
+ {
+ Id = Internal.GetBeaconByIndex( i )
+ };
+ }
+ }
+ }
+
+ ///
+ /// Create a new party beacon and activate it in the selected location.
+ /// When people begin responding to your beacon, Steam will send you
+ /// OnPartyReservation callbacks to let you know who is on the way.
+ ///
+ //public async Task CreateBeacon( int slots, string connectString, string meta )
+ //{
+ // var result = await Internal.CreateBeacon( (uint)slots, null, connectString, meta );
+ // if ( !result.HasValue ) return null;
+ //}
+
+ // TODO - is this useful to anyone, or is it a load of shit?
+ }
+}
\ No newline at end of file
diff --git a/Facepunch.Steamworks/Structs/PartyBeacon.cs b/Facepunch.Steamworks/Structs/PartyBeacon.cs
new file mode 100644
index 0000000..98905e9
--- /dev/null
+++ b/Facepunch.Steamworks/Structs/PartyBeacon.cs
@@ -0,0 +1,82 @@
+using System.Threading.Tasks;
+using Steamworks.Data;
+
+namespace Steamworks
+{
+ public struct PartyBeacon
+ {
+ static ISteamParties Internal => SteamParties.Internal;
+
+ internal PartyBeaconID_t Id;
+
+ ///
+ /// Creator of the beacon
+ ///
+ public SteamId Owner
+ {
+ get
+ {
+ var owner = default( SteamId );
+ var location = default( SteamPartyBeaconLocation_t );
+ var sb = Helpers.TakeStringBuilder();
+ Internal.GetBeaconDetails( Id, ref owner, ref location, sb, sb.Capacity );
+ return owner;
+ }
+ }
+
+ ///
+ /// Creator of the beacon
+ ///
+ public string MetaData
+ {
+ get
+ {
+ var owner = default( SteamId );
+ var location = default( SteamPartyBeaconLocation_t );
+ var sb = Helpers.TakeStringBuilder();
+ Internal.GetBeaconDetails( Id, ref owner, ref location, sb, sb.Capacity );
+ return sb.ToString();
+ }
+ }
+
+ ///
+ /// Will attempt to join the party. If successful will return a connection string.
+ /// If failed, will return null
+ ///
+ public async Task JoinAsync()
+ {
+ var result = await Internal.JoinParty( Id );
+ if ( !result.HasValue || result.Value.Result != Result.OK )
+ return null;
+
+ return result.Value.ConnectString;
+ }
+
+ ///
+ /// When a user follows your beacon, Steam will reserve one of the open party slots for them, and send your game a ReservationNotification callback.
+ /// When that user joins your party, call OnReservationCompleted to notify Steam that the user has joined successfully
+ ///
+ public void OnReservationCompleted( SteamId steamid )
+ {
+ Internal.OnReservationCompleted( Id, steamid );
+ }
+
+ ///
+ /// To cancel a reservation (due to timeout or user input), call this.
+ /// Steam will open a new reservation slot.
+ /// Note: The user may already be in-flight to your game, so it's possible they will still connect and try to join your party.
+ ///
+ public void CancelReservation( SteamId steamid )
+ {
+ Internal.CancelReservation( Id, steamid );
+ }
+
+ ///
+ /// Turn off the beacon
+ ///
+ public bool Destroy()
+ {
+ return Internal.DestroyBeacon( Id );
+ }
+ }
+}
\ No newline at end of file