Skip to content

Commit 2ee5256

Browse files
committed
Add new SteamFriendList message
1 parent 40c6bce commit 2ee5256

File tree

4 files changed

+103
-16
lines changed

4 files changed

+103
-16
lines changed

ChobbyLauncher/ChobbyLoopbackMessages.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,18 @@ public class SteamOnline
123123
{
124124

125125
public string AuthToken { get; set; }
126-
public List<SteamFriend> Friends { get; set; }
127126
public string FriendSteamID { get; set; }
128127
public string SuggestedName { get; set; }
129128
public List<ulong> Dlc { get; set; }
130129
}
131130

131+
[ChobbyMessage]
132+
public class SteamFriendList
133+
{
134+
135+
public List<SteamFriend> Friends { get; set; }
136+
}
137+
132138
[ChobbyMessage]
133139
public class SteamOffline
134140
{

ChobbyLauncher/Chobbyla.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ private void ClearSdp()
185185
public bool Run(ulong initialConnectLobbyID, TextWriter writer)
186186
{
187187
Status = "Connecting to steam API";
188-
using (var steam = new SteamClientHelper())
188+
using (var steam = new SteamClientHelper(this))
189189
{
190190
steam.ConnectToSteam();
191191

ChobbyLauncher/ChobbylaLocalListener.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public ChobbylaLocalListener(Chobbyla chobbyla, SteamClientHelper steam, ulong i
4848
steam.OverlayActivated += SteamOnOverlayActivated;
4949
steam.SteamOnline += () => { SendSteamOnline(); };
5050
steam.SteamOffline += () => { SendSteamOffline(); };
51+
steam.FriendListUpdate += (freund) => { SendFriendList(); };
5152
discordController = new DiscordController(GlobalConst.ZeroKDiscordID, GlobalConst.SteamAppID.ToString());
5253
discordController.OnJoin += DiscordOnJoinCallback;
5354
discordController.OnDisconnected += DiscordOnDisconnectedCallback;
@@ -723,6 +724,7 @@ private async Task OnConnected()
723724
try
724725
{
725726
await SendSteamOnline();
727+
await SendFriendList();
726728

727729
}
728730
catch (Exception ex)
@@ -763,7 +765,6 @@ private async Task SendSteamOnline()
763765
SendCommand(new SteamOnline()
764766
{
765767
AuthToken = steam.AuthToken,
766-
Friends = steam.Friends,
767768
FriendSteamID = friendId?.ToString(),
768769
SuggestedName = steam.MySteamNameSanitized,
769770
Dlc = steam.GetDlcList()
@@ -773,6 +774,17 @@ private async Task SendSteamOnline()
773774
}
774775
}
775776

777+
private async Task SendFriendList()
778+
{
779+
if (steam.IsOnline)
780+
{
781+
await SendCommand(new SteamFriendList()
782+
{
783+
Friends = steam.Friends.Values.ToList()
784+
});
785+
}
786+
}
787+
776788
private async Task SendSteamOffline()
777789
{
778790
await SendCommand(new SteamOffline());

ChobbyLauncher/SteamClient.cs

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
using ZkData;
1515
using System.Net.NetworkInformation;
1616
using Timer = System.Timers.Timer;
17+
using System.IO;
18+
using System.Drawing;
19+
using System.Runtime.InteropServices;
20+
using System.Drawing.Imaging;
21+
using Newtonsoft.Json;
1722

1823
namespace ChobbyLauncher
1924
{
@@ -36,6 +41,7 @@ public enum OverlayOption
3641

3742
private bool isDisposed;
3843

44+
private Callback<PersonaStateChange_t> friendStateChangeCallback;
3945
private Callback<GameLobbyJoinRequested_t> lobbyJoinRequestCallback;
4046
private Callback<P2PSessionRequest_t> newConnectionCallback;
4147
private Callback<GameOverlayActivated_t> overlayActivatedCallback;
@@ -47,14 +53,20 @@ public enum OverlayOption
4753

4854
public string AuthToken { get; private set; }
4955

50-
public List<SteamFriend> Friends { get; private set; }
56+
public ConcurrentDictionary<ulong, SteamFriend> Friends { get; private set; }
5157
public bool IsOnline { get; private set; }
5258
public ChobbylaLocalListener Listener { get; set; }
5359

5460
public ulong? LobbyID { get; set; }
5561

5662
public string MySteamNameSanitized { get; set; }
5763

64+
private Chobbyla chobbyla;
65+
66+
public SteamClientHelper(Chobbyla chobbyla)
67+
{
68+
this.chobbyla = chobbyla;
69+
}
5870

5971
public void Dispose()
6072
{
@@ -88,8 +100,8 @@ public void ConnectToSteam()
88100
foreach (var f in GetFriendIDs())
89101
{
90102
FriendGameInfo_t gi;
91-
SteamFriends.GetFriendGamePlayed(new CSteamID(f), out gi);
92-
if (gi.m_steamIDLobby.m_SteamID == lobbyID) return f;
103+
SteamFriends.GetFriendGamePlayed(f, out gi);
104+
if (gi.m_steamIDLobby.m_SteamID == lobbyID) return f.m_SteamID;
93105
}
94106
return null;
95107
}
@@ -118,6 +130,9 @@ public void InviteFriendToGame(ulong lobbyID, ulong friendID)
118130
if (IsOnline) SteamMatchmaking.InviteUserToLobby(new CSteamID(lobbyID), new CSteamID(friendID));
119131
}
120132

133+
134+
public event Action<SteamFriend> FriendListUpdate = (freund) => { };
135+
121136
public event Action<ulong> JoinFriendRequest = (steamID) => { };
122137

123138
public void OpenOverlaySection(OverlayOption option)
@@ -241,26 +256,34 @@ private string GetClientAuthTokenHex()
241256
}
242257

243258

244-
private List<SteamFriend> getFriends()
259+
private ConcurrentDictionary<ulong, SteamFriend> GetFriends()
245260
{
246261
if (IsOnline)
247262
{
248-
return GetFriendIDs().Select(x => new SteamFriend()
263+
var dic = new ConcurrentDictionary<ulong, SteamFriend>(GetFriendIDs().ToDictionary(x => x.m_SteamID, x => new SteamFriend()
249264
{
250265
Name = SteamFriends.GetFriendPersonaName(x),
251-
SteamID = x.ToString()
252-
}).ToList();
266+
CSteamID = x
267+
}));
268+
dic.ForEach(freund =>
269+
{
270+
var state = SteamFriends.GetFriendPersonaState(freund.Value.CSteamID);
271+
freund.Value.IsOnline = state.HasFlag(EPersonaState.k_EPersonaStateOnline);
272+
FriendGameInfo_t game;
273+
freund.Value.IsPlaying = SteamFriends.GetFriendGamePlayed(freund.Value.CSteamID, out game) && (game.m_gameID.AppID().m_AppId == GlobalConst.SteamAppID);
274+
});
275+
return dic;
253276
}
254277
return null;
255278
}
256279

257-
private List<ulong> GetFriendIDs()
280+
private List<CSteamID> GetFriendIDs()
258281
{
259282
if (IsOnline)
260283
{
261-
var ret = new List<ulong>();
284+
var ret = new List<CSteamID>();
262285
var cnt = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate);
263-
for (var i = 0; i < cnt; i++) ret.Add(SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate).m_SteamID);
286+
for (var i = 0; i < cnt; i++) ret.Add(SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate));
264287
return ret;
265288
}
266289
return null;
@@ -278,13 +301,52 @@ private ulong GetSteamID()
278301
return 0;
279302
}
280303

304+
private void DownloadAvatars(ICollection<CSteamID> users)
305+
{
306+
using (var wc = new WebClient())
307+
{
308+
var targetDir = Path.Combine(chobbyla.paths.WritableDirectory, "LuaUI", "Configs", "SteamAvatars");
309+
if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir);
310+
foreach (var user in users)
311+
{
312+
//download image via steamfriends
313+
int handle = SteamFriends.GetMediumFriendAvatar(user);
314+
uint imgW, imgH;
315+
SteamUtils.GetImageSize(handle, out imgW, out imgH);
316+
byte[] imgBuffer = new byte[4 * imgW * imgH];
317+
GCHandle pinnedArray = GCHandle.Alloc(imgBuffer, GCHandleType.Pinned); //please make a better implementation of this
318+
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
319+
SteamUtils.GetImageRGBA(handle, imgBuffer, imgBuffer.Length);
320+
var bitmap = new Bitmap((int)imgW, (int)imgH, 4 * (int)imgW, PixelFormat.Format32bppArgb, pointer);
321+
322+
var path = Path.Combine(targetDir, string.Format("{0}.png", user.m_SteamID));
323+
if (File.Exists(path)) File.Delete(path);
324+
bitmap.Save(path, ImageFormat.Png);
325+
326+
pinnedArray.Free();
327+
}
328+
}
329+
}
330+
331+
private void OnFriendStateUpdate(PersonaStateChange_t u)
332+
{
333+
if (!Friends.ContainsKey(u.m_ulSteamID)) return; //Needed because this method is called for the player himself (not part of friend list)
334+
var freund = Friends[u.m_ulSteamID];
335+
if (u.m_nChangeFlags.HasFlag(EPersonaChange.k_EPersonaChangeComeOnline)) freund.IsOnline = true;
336+
if (u.m_nChangeFlags.HasFlag(EPersonaChange.k_EPersonaChangeGoneOffline)) freund.IsOnline = false;
337+
FriendGameInfo_t game;
338+
freund.IsPlaying = SteamFriends.GetFriendGamePlayed(new CSteamID(u.m_ulSteamID), out game) && (game.m_gameID.AppID().m_AppId == GlobalConst.SteamAppID);
339+
FriendListUpdate?.Invoke(freund);
340+
}
341+
281342
private void OnSteamOnline()
282343
{
283344
Trace.TraceInformation("Steam online");
284345

285346
lobbyJoinRequestCallback = new Callback<GameLobbyJoinRequested_t>(t => { JoinFriendRequest(t.m_steamIDFriend.m_SteamID); });
286347
overlayActivatedCallback = new Callback<GameOverlayActivated_t>(t => { OverlayActivated(t.m_bActive != 0); });
287348
newConnectionCallback = Callback<P2PSessionRequest_t>.Create(t => SteamNetworking.AcceptP2PSessionWithUser(t.m_steamIDRemote));
349+
friendStateChangeCallback = new Callback<PersonaStateChange_t>(t => OnFriendStateUpdate(t));
288350
MySteamNameSanitized = Utils.StripInvalidLobbyNameChars(GetMyName());
289351

290352

@@ -296,9 +358,11 @@ private void OnSteamOnline()
296358
ev.Set();
297359
});
298360
SteamNetworking.AllowP2PPacketRelay(true);
299-
Friends = GetFriendIDs();
361+
Friends = GetFriends();
362+
Task.Factory.StartNew(() => DownloadAvatars(Friends.Values.Select(x => x.CSteamID).ToList()));
300363
ev.WaitOne(2000);
301364
SteamOnline?.Invoke();
365+
FriendListUpdate?.Invoke(null);
302366
}
303367

304368
private void ProcessMessage(ulong remoteUser, Dummy cmd)
@@ -439,10 +503,15 @@ private void TimerOnElapsed(object sender)
439503
}
440504
}
441505

442-
class SteamFriend
506+
public class SteamFriend
443507
{
508+
private CSteamID _cSteamID;
444509

445-
public string SteamID;
510+
[JsonIgnore]
511+
public CSteamID CSteamID { get { return _cSteamID; } set { _cSteamID = value; SteamID = value.m_SteamID; } }
512+
public ulong SteamID { get; private set; }
446513
public string Name;
514+
public bool IsOnline;
515+
public bool IsPlaying; //whether friend is playing zk right now
447516
}
448517
}

0 commit comments

Comments
 (0)