Skip to content

Commit a7a1f1b

Browse files
committed
Simplify access to Mumble context
1 parent 831f327 commit a7a1f1b

File tree

5 files changed

+30
-54
lines changed

5 files changed

+30
-54
lines changed

GW2SDK.Tests/Features/Mumble/GameLinkTest.cs

+6-4
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,15 @@ public void The_link_provides_context()
5050
{
5151
using var sut = GameLink.Open();
5252

53-
var snapshot = sut.GetSnapshot();
54-
Assert.True(snapshot.TryGetContext(out var actual));
55-
Assert.True(actual.BuildId > 100_000, "Game build should be over 100,000");
53+
var gameTick = sut.GetSnapshot();
54+
Assert.True(gameTick.Context.BuildId > 100_000, "Game build should be over 100,000");
5655

57-
var server = actual.GetServerAddress();
56+
var server = gameTick.Context.GetServerAddress();
5857
Assert.NotEmpty(server.ToString());
5958

59+
var address = gameTick.Context.GetServerAddress();
60+
Assert.NotNull(address.Address);
61+
6062
// Port is not specified
6163
Assert.Equal(0, server.Port);
6264
}

GW2SDK/Features/Mumble/Context.cs

+2
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ public struct Context
6363

6464
public bool IsMounted => MountIndex != 0;
6565

66+
[Pure]
6667
public IPEndPoint GetServerAddress() =>
6768
new(ServerAddress.sin_addr.s_un.s_addr, ServerAddress.sin_port);
6869

70+
[Pure]
6971
public MountName GetMount() =>
7072
MountIndex switch
7173
{

GW2SDK/Features/Mumble/GameTick.cs

+4-27
Original file line numberDiff line numberDiff line change
@@ -34,38 +34,15 @@ public struct GameTick
3434
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
3535
public readonly string Identity;
3636

37-
/// <summary>Despite the actual context containing more data, this value is always 48. This field tells Mumble to use the
38-
/// first 48 bytes to uniquely identify people on the same server shards. The remaining 208 bytes are purely informational.</summary>
39-
public readonly uint ContextLength;
37+
/// <summary>This field tells Mumble to use the first 48 bytes of the Context to uniquely identify people on the same
38+
/// server shards. It is internal because I don't expect anyone to find it useful.</summary>
39+
internal readonly uint ContextLength;
4040

41-
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
42-
internal readonly byte[] Context;
41+
public readonly Context Context;
4342

4443
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2048)]
4544
public readonly string Description;
4645

47-
public bool TryGetContext(out Context context)
48-
{
49-
context = default;
50-
if (Name != "Guild Wars 2")
51-
{
52-
return false;
53-
}
54-
55-
var handle = GCHandle.Alloc(Context, GCHandleType.Pinned);
56-
try
57-
{
58-
var addr = handle.AddrOfPinnedObject();
59-
context = Marshal.PtrToStructure<Context>(addr);
60-
}
61-
finally
62-
{
63-
handle.Free();
64-
}
65-
66-
return true;
67-
}
68-
6946
public bool TryGetIdentity(
7047
[NotNullWhen(true)] out Identity? identity,
7148
MissingMemberBehavior missingMemberBehavior

samples/Mumble/GameReporter.cs

+16-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.ComponentModel.DataAnnotations;
32
using System.Linq;
43
using System.Threading;
54
using System.Threading.Tasks;
@@ -48,15 +47,10 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
4847
// Subscribe to the GameLink observable
4948
// I recommend using Rx (System.Reactive) instead of implementing IObserver<T> yourself
5049
gameLink.Subscribe(
51-
snapshot =>
50+
tick =>
5251
{
5352
// This callback is executed whenever the game client updates the shared memory
54-
if (!snapshot.TryGetIdentity(out var identity, MissingMemberBehavior.Error))
55-
{
56-
return;
57-
}
58-
59-
if (!snapshot.TryGetContext(out var context))
53+
if (!tick.TryGetIdentity(out var identity, MissingMemberBehavior.Error))
6054
{
6155
return;
6256
}
@@ -70,41 +64,41 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
7064
var map = mapsDictionary[identity.MapId];
7165

7266
var title = $"the {identity.Race} {identity.Profession}";
73-
if (!context.UiState.HasFlag(UiState.GameHasFocus))
67+
if (!tick.Context.UiState.HasFlag(UiState.GameHasFocus))
7468
{
7569
logger.LogInformation(
7670
"[{UiTick}] {Name}, {Title} ({Specialization}) is afk",
77-
snapshot.UiTick,
71+
tick.UiTick,
7872
identity.Name,
7973
title,
8074
specialization
8175
);
8276
}
83-
else if (context.UiState.HasFlag(UiState.TextboxHasFocus))
77+
else if (tick.Context.UiState.HasFlag(UiState.TextboxHasFocus))
8478
{
8579
logger.LogInformation(
8680
"[{UiTick}] {Name}, {Title} ({Specialization}) is typing",
87-
snapshot.UiTick,
81+
tick.UiTick,
8882
identity.Name,
8983
title,
9084
specialization
9185
);
9286
}
93-
else if (context.UiState.HasFlag(UiState.IsMapOpen))
87+
else if (tick.Context.UiState.HasFlag(UiState.IsMapOpen))
9488
{
9589
logger.LogInformation(
9690
"[{UiTick}] {Name}, {Title} ({Specialization}) is looking at the map",
97-
snapshot.UiTick,
91+
tick.UiTick,
9892
identity.Name,
9993
title,
10094
specialization
10195
);
10296
}
103-
else if (context.UiState.HasFlag(UiState.IsInCombat))
97+
else if (tick.Context.UiState.HasFlag(UiState.IsInCombat))
10498
{
10599
logger.LogInformation(
106100
"[{UiTick}] {Name}, {Title} ({Specialization}) is in combat",
107-
snapshot.UiTick,
101+
tick.UiTick,
108102
identity.Name,
109103
title,
110104
specialization
@@ -113,22 +107,22 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
113107
else
114108
{
115109
var transport = "foot";
116-
if (context.IsMounted)
110+
if (tick.Context.IsMounted)
117111
{
118-
transport = context.GetMount( ).ToString();
112+
transport = tick.Context.GetMount().ToString();
119113
}
120114

121115
logger.LogInformation(
122116
"[{UiTick}] {Name}, {Title} ({Specialization}) is on {Transport} in {Map}, Position: {{ Latitude = {X}, Longitude = {Z}, Elevation = {Y} }}",
123-
snapshot.UiTick,
117+
tick.UiTick,
124118
identity.Name,
125119
title,
126120
specialization,
127121
transport,
128122
map.Name,
129-
snapshot.AvatarPosition.X,
130-
snapshot.AvatarPosition.Z,
131-
snapshot.AvatarPosition.Y
123+
tick.AvatarPosition.X,
124+
tick.AvatarPosition.Z,
125+
tick.AvatarPosition.Y
132126
);
133127
}
134128
},

samples/Mumble/Program.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
options.SingleLine = true;
2828
options.TimestampFormat = "HH:mm:ss.fff ";
2929
options.UseUtcTimestamp = true;
30-
});
30+
}
31+
);
3132

3233
var app = builder.Build();
3334

0 commit comments

Comments
 (0)