Skip to content

Commit 4871c37

Browse files
committed
Add new SteamFriendList message
1 parent 40c6bce commit 4871c37

4 files changed

Lines changed: 101 additions & 16 deletions

File tree

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: 80 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,33 @@ 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+
freund.Value.IsPlaying = SteamFriends.GetFriendGamePlayed(freund.Value.CSteamID, out var game) && (game.m_gameID.AppID().m_AppId == GlobalConst.SteamAppID);
273+
});
274+
return dic;
253275
}
254276
return null;
255277
}
256278

257-
private List<ulong> GetFriendIDs()
279+
private List<CSteamID> GetFriendIDs()
258280
{
259281
if (IsOnline)
260282
{
261-
var ret = new List<ulong>();
283+
var ret = new List<CSteamID>();
262284
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);
285+
for (var i = 0; i < cnt; i++) ret.Add(SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate));
264286
return ret;
265287
}
266288
return null;
@@ -278,13 +300,51 @@ private ulong GetSteamID()
278300
return 0;
279301
}
280302

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

285344
lobbyJoinRequestCallback = new Callback<GameLobbyJoinRequested_t>(t => { JoinFriendRequest(t.m_steamIDFriend.m_SteamID); });
286345
overlayActivatedCallback = new Callback<GameOverlayActivated_t>(t => { OverlayActivated(t.m_bActive != 0); });
287346
newConnectionCallback = Callback<P2PSessionRequest_t>.Create(t => SteamNetworking.AcceptP2PSessionWithUser(t.m_steamIDRemote));
347+
friendStateChangeCallback = new Callback<PersonaStateChange_t>(t => OnFriendStateUpdate(t));
288348
MySteamNameSanitized = Utils.StripInvalidLobbyNameChars(GetMyName());
289349

290350

@@ -296,9 +356,11 @@ private void OnSteamOnline()
296356
ev.Set();
297357
});
298358
SteamNetworking.AllowP2PPacketRelay(true);
299-
Friends = GetFriendIDs();
359+
Friends = GetFriends();
360+
Task.Factory.StartNew(() => DownloadAvatars(Friends.Values.Select(x => x.CSteamID).ToList()));
300361
ev.WaitOne(2000);
301362
SteamOnline?.Invoke();
363+
FriendListUpdate?.Invoke(null);
302364
}
303365

304366
private void ProcessMessage(ulong remoteUser, Dummy cmd)
@@ -439,10 +501,15 @@ private void TimerOnElapsed(object sender)
439501
}
440502
}
441503

442-
class SteamFriend
504+
public class SteamFriend
443505
{
506+
private CSteamID _cSteamID;
444507

445-
public string SteamID;
508+
[JsonIgnore]
509+
public CSteamID CSteamID { get { return _cSteamID; } set { _cSteamID = value; SteamID = value.m_SteamID; } }
510+
public ulong SteamID { get; private set; }
446511
public string Name;
512+
public bool IsOnline;
513+
public bool IsPlaying; //whether friend is playing zk right now
447514
}
448515
}

0 commit comments

Comments
 (0)