Skip to content

Commit d61adc5

Browse files
committed
Game advertisement improvements
1 parent f492072 commit d61adc5

4 files changed

Lines changed: 53 additions & 28 deletions

File tree

src/Atlasd/Battlenet/Protocols/Game/Messages/SID_ENTERCHAT.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public SID_ENTERCHAT(byte[] buffer)
2424

2525
public override bool Invoke(MessageContext context)
2626
{
27+
if (context == null || context.Client == null || !context.Client.Connected) return false;
2728
var gameState = context.Client.GameState;
2829

2930
switch (context.Direction)
@@ -33,14 +34,10 @@ public override bool Invoke(MessageContext context)
3334
Logging.WriteLine(Logging.LogLevel.Debug, Logging.LogType.Client_Game, context.Client.RemoteEndPoint, $"[{Common.DirectionToString(context.Direction)}] {MessageName(Id)} ({4 + Buffer.Length} bytes)");
3435

3536
if (Buffer.Length < 2)
36-
{
3737
throw new GameProtocolViolationException(context.Client, $"{MessageName(Id)} buffer must be at least 2 bytes");
38-
}
3938

4039
if (gameState.ActiveAccount == null || string.IsNullOrEmpty(gameState.OnlineName))
41-
{
4240
throw new GameProtocolViolationException(context.Client, $"{MessageName(Id)} received before logon");
43-
}
4441

4542
/**
4643
* (STRING) Username
@@ -49,7 +46,6 @@ public override bool Invoke(MessageContext context)
4946

5047
using var m = new MemoryStream(Buffer);
5148
using var r = new BinaryReader(m);
52-
5349
var username = r.ReadByteString(); // Defunct
5450
var statstring = r.ReadByteString();
5551

@@ -59,14 +55,10 @@ public override bool Invoke(MessageContext context)
5955
if (statstring.Length != 0 && (statstring.Length < 4 || statstring.Length > 128))
6056
throw new GameProtocolViolationException(context.Client, $"Client sent invalid statstring size in {MessageName(Id)}");
6157

62-
if (statstring.Length < 4)
63-
{
64-
statstring = new byte[4];
65-
}
58+
if (statstring.Length < 4) statstring = new byte[4];
6659

6760
using var _m = new MemoryStream(statstring);
6861
using var _w = new BinaryWriter(_m);
69-
7062
_w.BaseStream.Position = 0;
7163
_w.Write(productId); // ensure first 4 bytes of statstring always matches their agreed upon productId
7264

@@ -107,6 +99,13 @@ public override bool Invoke(MessageContext context)
10799
var newPing = gameState.Ping;
108100
if (Product.IsChat(gameState.Product)) newPing = 0;
109101

102+
if (gameState.GameAd != null)
103+
{
104+
var gameAd = gameState.GameAd;
105+
if (gameAd.RemoveClient(gameState)) gameState.GameAd = null;
106+
if (gameAd.Clients.Count == 0) lock (Battlenet.Common.ActiveGameAds) Battlenet.Common.ActiveGameAds.Remove(gameAd);
107+
}
108+
110109
if (gameState.ActiveChannel == null)
111110
{
112111
Logging.WriteLine(Logging.LogLevel.Info, Logging.LogType.Client_Game, context.Client.RemoteEndPoint, $"Entering chat as [{uniqueName}]");

src/Atlasd/Battlenet/Protocols/Game/Messages/SID_LEAVEGAME.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,10 @@ public override bool Invoke(MessageContext context)
3131
if (Buffer.Length != 0)
3232
throw new GameProtocolViolationException(context.Client, $"{MessageName(Id)} buffer must be 0 bytes, got {Buffer.Length}");
3333

34-
GameState gs = context.Client.GameState;
34+
if (!Product.IsDiabloII(context.Client.GameState.Product))
35+
throw new GameProtocolViolationException(context.Client, $"{MessageName(Id)} received but client not identified as Diablo II");
3536

36-
if (gs == null)
37-
throw new GameProtocolViolationException(context.Client, $"{MessageName(Id)} was received without an active GameState");
38-
39-
if (gs.GameAd == null)
40-
return true; // No game advertisement to stop. No action to do.
41-
42-
bool gameAdOwner = gs.GameAd != null && gs.GameAd.Owner == gs;
43-
if (gameAdOwner && gs.GameAd.Clients.Count == 1) Battlenet.Common.ActiveGameAds.Remove(gs.GameAd);
44-
45-
if (gs.GameAd != null && gs.GameAd.RemoveClient(gs)) gs.GameAd = null;
37+
// TODO: Implement action to take from receiving SID_LEAVEGAME.
4638
return true;
4739
}
4840
}

src/Atlasd/Battlenet/Protocols/Game/Messages/SID_NOTIFYJOIN.cs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using Atlasd.Battlenet.Exceptions;
22
using Atlasd.Daemon;
3+
using Atlasd.Localization;
34
using System;
5+
using System.Collections.Generic;
6+
using System.Globalization;
47
using System.IO;
58
using System.Linq;
69
using System.Text;
@@ -24,11 +27,17 @@ public SID_NOTIFYJOIN(byte[] buffer)
2427

2528
public override bool Invoke(MessageContext context)
2629
{
30+
if (context == null || context.Client == null || !context.Client.Connected) return false;
31+
var gameState = context.Client.GameState;
32+
2733
Logging.WriteLine(Logging.LogLevel.Debug, Logging.LogType.Client_Game, context.Client.RemoteEndPoint, $"[{Common.DirectionToString(context.Direction)}] {MessageName(Id)} ({4 + Buffer.Length} bytes)");
2834

2935
if (context.Direction != MessageDirection.ClientToServer)
3036
throw new GameProtocolViolationException(context.Client, $"{MessageName(Id)} must be sent from client to server");
3137

38+
if (gameState == null || gameState.ActiveAccount == null)
39+
throw new GameProtocolViolationException(context.Client, $"{MessageName(Id)} received but client not logged into an account");
40+
3241
if (Buffer.Length < 10)
3342
throw new GameProtocolViolationException(context.Client, $"{MessageName(Id)} buffer must be at least 10 bytes");
3443

@@ -40,22 +49,50 @@ public override bool Invoke(MessageContext context)
4049
var gameName = r.ReadByteString();
4150
var gamePassword = r.ReadByteString();
4251

43-
if (context.Client.GameState.ActiveChannel != null)
44-
context.Client.GameState.ActiveChannel.RemoveUser(context.Client.GameState);
52+
if (gameState.ActiveChannel != null)
53+
gameState.ActiveChannel.RemoveUser(gameState);
4554

4655
lock (Battlenet.Common.ActiveGameAds)
4756
{
4857
foreach (var gameAd in Battlenet.Common.ActiveGameAds)
4958
{
5059
if (gameAd.Name.SequenceEqual(gameName))
5160
{
52-
if (gameAd.HasClient(context.Client.GameState) || gameAd.AddClient(context.Client.GameState))
53-
context.Client.GameState.GameAd = gameAd;
61+
if (gameAd.HasClient(gameState) || gameAd.AddClient(gameState))
62+
gameState.GameAd = gameAd;
5463
break;
5564
}
5665
}
5766
}
5867

68+
var mutualFriend = false;
69+
var friendByteStrings = (List<byte[]>)gameState.ActiveAccount.Get(Account.FriendsKey, new List<byte[]>());
70+
foreach (var friendByteString in friendByteStrings)
71+
{
72+
if (Battlenet.Common.GetClientByOnlineName(Encoding.UTF8.GetString(friendByteString), out var friendGameState) && friendGameState != null && friendGameState.ActiveAccount != null)
73+
{
74+
mutualFriend = false;
75+
var subfriendByteStrings = (List<byte[]>)friendGameState.ActiveAccount.Get(Account.FriendsKey, new List<byte[]>());
76+
foreach (var subfriendByteString in subfriendByteStrings)
77+
{
78+
if (Battlenet.Common.GetClientByOnlineName(Encoding.UTF8.GetString(subfriendByteString), out var subfriendGameState) && subfriendGameState != null)
79+
{
80+
mutualFriend = (subfriendGameState == gameState);
81+
if (mutualFriend) break;
82+
}
83+
}
84+
if (mutualFriend)
85+
{
86+
var buffer = Resources.YourFriendEnteredGame;
87+
buffer = buffer.Replace("{friend}", gameState.Username, true, CultureInfo.InvariantCulture);
88+
buffer = buffer.Replace("{game}", Product.ProductName(gameState.Product, true), true, CultureInfo.InvariantCulture);
89+
buffer = buffer.Replace("{gameAd}", Encoding.UTF8.GetString(gameState.GameAd.Name), true, CultureInfo.InvariantCulture);
90+
foreach (var line in buffer.Split(Battlenet.Common.NewLine))
91+
new ChatEvent(ChatEvent.EventIds.EID_WHISPERFROM, gameState.ChannelFlags, gameState.Ping, Channel.RenderOnlineName(friendGameState, gameState), buffer).WriteTo(friendGameState.Client);
92+
}
93+
}
94+
}
95+
5996
return true;
6097
}
6198
}

src/Atlasd/Battlenet/Protocols/Game/Messages/SID_STOPADV.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@ public override bool Invoke(MessageContext context)
3939
return true; // No game advertisement to stop. No action to do.
4040

4141
bool gameAdOwner = gs.GameAd != null && gs.GameAd.Owner == gs;
42-
43-
if (gs.GameAd != null && gs.GameAd.RemoveClient(gs)) gs.GameAd = null;
44-
4542
if (!gameAdOwner)
4643
Logging.WriteLine(Logging.LogLevel.Info, Logging.LogType.Client_Game, context.Client.RemoteEndPoint, $"{MessageName(Id)} was received but they are not the owner of the game advertisement");
4744
else

0 commit comments

Comments
 (0)