Skip to content

Commit

Permalink
Add new SteamFriendList message
Browse files Browse the repository at this point in the history
  • Loading branch information
DeinFreund committed Nov 22, 2018
1 parent 40c6bce commit 4871c37
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 16 deletions.
8 changes: 7 additions & 1 deletion ChobbyLauncher/ChobbyLoopbackMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,18 @@ public class SteamOnline
{

public string AuthToken { get; set; }
public List<SteamFriend> Friends { get; set; }
public string FriendSteamID { get; set; }
public string SuggestedName { get; set; }
public List<ulong> Dlc { get; set; }
}

[ChobbyMessage]
public class SteamFriendList
{

public List<SteamFriend> Friends { get; set; }
}

[ChobbyMessage]
public class SteamOffline
{
Expand Down
2 changes: 1 addition & 1 deletion ChobbyLauncher/Chobbyla.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ private void ClearSdp()
public bool Run(ulong initialConnectLobbyID, TextWriter writer)
{
Status = "Connecting to steam API";
using (var steam = new SteamClientHelper())
using (var steam = new SteamClientHelper(this))
{
steam.ConnectToSteam();

Expand Down
14 changes: 13 additions & 1 deletion ChobbyLauncher/ChobbylaLocalListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public ChobbylaLocalListener(Chobbyla chobbyla, SteamClientHelper steam, ulong i
steam.OverlayActivated += SteamOnOverlayActivated;
steam.SteamOnline += () => { SendSteamOnline(); };
steam.SteamOffline += () => { SendSteamOffline(); };
steam.FriendListUpdate += (freund) => { SendFriendList(); };
discordController = new DiscordController(GlobalConst.ZeroKDiscordID, GlobalConst.SteamAppID.ToString());
discordController.OnJoin += DiscordOnJoinCallback;
discordController.OnDisconnected += DiscordOnDisconnectedCallback;
Expand Down Expand Up @@ -723,6 +724,7 @@ private async Task OnConnected()
try
{
await SendSteamOnline();
await SendFriendList();

}
catch (Exception ex)
Expand Down Expand Up @@ -763,7 +765,6 @@ private async Task SendSteamOnline()
SendCommand(new SteamOnline()
{
AuthToken = steam.AuthToken,
Friends = steam.Friends,
FriendSteamID = friendId?.ToString(),
SuggestedName = steam.MySteamNameSanitized,
Dlc = steam.GetDlcList()
Expand All @@ -773,6 +774,17 @@ private async Task SendSteamOnline()
}
}

private async Task SendFriendList()
{
if (steam.IsOnline)
{
await SendCommand(new SteamFriendList()
{
Friends = steam.Friends.Values.ToList()
});
}
}

private async Task SendSteamOffline()
{
await SendCommand(new SteamOffline());
Expand Down
93 changes: 80 additions & 13 deletions ChobbyLauncher/SteamClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
using ZkData;
using System.Net.NetworkInformation;
using Timer = System.Timers.Timer;
using System.IO;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using Newtonsoft.Json;

namespace ChobbyLauncher
{
Expand All @@ -36,6 +41,7 @@ public enum OverlayOption

private bool isDisposed;

private Callback<PersonaStateChange_t> friendStateChangeCallback;
private Callback<GameLobbyJoinRequested_t> lobbyJoinRequestCallback;
private Callback<P2PSessionRequest_t> newConnectionCallback;
private Callback<GameOverlayActivated_t> overlayActivatedCallback;
Expand All @@ -47,14 +53,20 @@ public enum OverlayOption

public string AuthToken { get; private set; }

public List<SteamFriend> Friends { get; private set; }
public ConcurrentDictionary<ulong, SteamFriend> Friends { get; private set; }
public bool IsOnline { get; private set; }
public ChobbylaLocalListener Listener { get; set; }

public ulong? LobbyID { get; set; }

public string MySteamNameSanitized { get; set; }

private Chobbyla chobbyla;

public SteamClientHelper(Chobbyla chobbyla)
{
this.chobbyla = chobbyla;
}

public void Dispose()
{
Expand Down Expand Up @@ -88,8 +100,8 @@ public void ConnectToSteam()
foreach (var f in GetFriendIDs())
{
FriendGameInfo_t gi;
SteamFriends.GetFriendGamePlayed(new CSteamID(f), out gi);
if (gi.m_steamIDLobby.m_SteamID == lobbyID) return f;
SteamFriends.GetFriendGamePlayed(f, out gi);
if (gi.m_steamIDLobby.m_SteamID == lobbyID) return f.m_SteamID;
}
return null;
}
Expand Down Expand Up @@ -118,6 +130,9 @@ public void InviteFriendToGame(ulong lobbyID, ulong friendID)
if (IsOnline) SteamMatchmaking.InviteUserToLobby(new CSteamID(lobbyID), new CSteamID(friendID));
}


public event Action<SteamFriend> FriendListUpdate = (freund) => { };

public event Action<ulong> JoinFriendRequest = (steamID) => { };

public void OpenOverlaySection(OverlayOption option)
Expand Down Expand Up @@ -241,26 +256,33 @@ private string GetClientAuthTokenHex()
}


private List<SteamFriend> getFriends()
private ConcurrentDictionary<ulong, SteamFriend> GetFriends()
{
if (IsOnline)
{
return GetFriendIDs().Select(x => new SteamFriend()
var dic = new ConcurrentDictionary<ulong, SteamFriend>(GetFriendIDs().ToDictionary(x => x.m_SteamID, x => new SteamFriend()
{
Name = SteamFriends.GetFriendPersonaName(x),
SteamID = x.ToString()
}).ToList();
CSteamID = x
}));
dic.ForEach(freund =>
{
var state = SteamFriends.GetFriendPersonaState(freund.Value.CSteamID);
freund.Value.IsOnline = state.HasFlag(EPersonaState.k_EPersonaStateOnline);
freund.Value.IsPlaying = SteamFriends.GetFriendGamePlayed(freund.Value.CSteamID, out var game) && (game.m_gameID.AppID().m_AppId == GlobalConst.SteamAppID);
});
return dic;
}
return null;
}

private List<ulong> GetFriendIDs()
private List<CSteamID> GetFriendIDs()
{
if (IsOnline)
{
var ret = new List<ulong>();
var ret = new List<CSteamID>();
var cnt = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate);
for (var i = 0; i < cnt; i++) ret.Add(SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate).m_SteamID);
for (var i = 0; i < cnt; i++) ret.Add(SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate));
return ret;
}
return null;
Expand All @@ -278,13 +300,51 @@ private ulong GetSteamID()
return 0;
}

private void DownloadAvatars(ICollection<CSteamID> users)
{
using (var wc = new WebClient())
{
var targetDir = Path.Combine(chobbyla.paths.WritableDirectory, "LuaUI", "Configs", "SteamAvatars");
if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir);
foreach (var user in users)
{
//download image via steamfriends
int handle = SteamFriends.GetMediumFriendAvatar(user);
uint imgW, imgH;
SteamUtils.GetImageSize(handle, out imgW, out imgH);
byte[] imgBuffer = new byte[4 * imgW * imgH];
GCHandle pinnedArray = GCHandle.Alloc(imgBuffer, GCHandleType.Pinned); //please make a better implementation of this
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
SteamUtils.GetImageRGBA(handle, imgBuffer, imgBuffer.Length);
var bitmap = new Bitmap((int)imgW, (int)imgH, 4 * (int)imgW, PixelFormat.Format32bppArgb, pointer);

var path = Path.Combine(targetDir, string.Format("{0}.png", user.m_SteamID));
if (File.Exists(path)) File.Delete(path);
bitmap.Save(path, ImageFormat.Png);

pinnedArray.Free();
}
}
}

private void OnFriendStateUpdate(PersonaStateChange_t u)
{
if (!Friends.ContainsKey(u.m_ulSteamID)) return; //Needed because this method is called for the player himself (not part of friend list)
var freund = Friends[u.m_ulSteamID];
if (u.m_nChangeFlags.HasFlag(EPersonaChange.k_EPersonaChangeComeOnline)) freund.IsOnline = true;
if (u.m_nChangeFlags.HasFlag(EPersonaChange.k_EPersonaChangeGoneOffline)) freund.IsOnline = false;
freund.IsPlaying = SteamFriends.GetFriendGamePlayed(new CSteamID(u.m_ulSteamID), out var game) && (game.m_gameID.AppID().m_AppId == GlobalConst.SteamAppID);
FriendListUpdate?.Invoke(freund);
}

private void OnSteamOnline()
{
Trace.TraceInformation("Steam online");

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


Expand All @@ -296,9 +356,11 @@ private void OnSteamOnline()
ev.Set();
});
SteamNetworking.AllowP2PPacketRelay(true);
Friends = GetFriendIDs();
Friends = GetFriends();
Task.Factory.StartNew(() => DownloadAvatars(Friends.Values.Select(x => x.CSteamID).ToList()));
ev.WaitOne(2000);
SteamOnline?.Invoke();
FriendListUpdate?.Invoke(null);
}

private void ProcessMessage(ulong remoteUser, Dummy cmd)
Expand Down Expand Up @@ -439,10 +501,15 @@ private void TimerOnElapsed(object sender)
}
}

class SteamFriend
public class SteamFriend
{
private CSteamID _cSteamID;

public string SteamID;
[JsonIgnore]
public CSteamID CSteamID { get { return _cSteamID; } set { _cSteamID = value; SteamID = value.m_SteamID; } }
public ulong SteamID { get; private set; }
public string Name;
public bool IsOnline;
public bool IsPlaying; //whether friend is playing zk right now
}
}

0 comments on commit 4871c37

Please sign in to comment.