Skip to content

Commit

Permalink
Improve the Mumble example
Browse files Browse the repository at this point in the history
  • Loading branch information
sliekens committed Sep 16, 2023
1 parent 60d137c commit 26ea81a
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 91 deletions.
146 changes: 89 additions & 57 deletions samples/Mumble/GameReporter.cs
Original file line number Diff line number Diff line change
@@ -1,76 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using GuildWars2;
using GuildWars2.Exploration.Maps;
using GuildWars2.Mumble;
using GuildWars2.Specializations;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class GameReporter : IObserver<Snapshot>
namespace Mumble;

public class GameReporter : BackgroundService
{
public Dictionary<int, Map> Maps { get; } = new();
private readonly Gw2Client gw2;

public Dictionary<int, Specialization> Specializations { get; } = new();
private readonly ILogger<GameReporter> logger;

public void OnNext(Snapshot snapshot)
public GameReporter(ILogger<GameReporter> logger, Gw2Client gw2)
{
var pos = snapshot.AvatarPosition;
this.logger = logger;
this.gw2 = gw2;
}

if (!snapshot.TryGetIdentity(out var identity, MissingMemberBehavior.Error))
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
if (!GameLink.IsSupported())
{
return;
throw new NotSupportedException();
}

if (!snapshot.TryGetContext(out var context))
{
return;
}
// BackgroundService starts synchronously, i.e. app startup is delayed until the first await
await Task.Yield();

var specialization = "no specialization";
if (Specializations.TryGetValue(identity.SpecializationId, out var found))
{
specialization = found.Name;
}
// Initialize the shared memory link
using var gameLink = GameLink.Open();

var map = Maps[identity.MapId];
var activity = "traveling";
if (!context.UiState.HasFlag(UiState.GameHasFocus))
{
activity = "afk-ing";
}
else if (context.UiState.HasFlag(UiState.TextboxHasFocus))
{
activity = "typing";
}
else if (context.UiState.HasFlag(UiState.IsMapOpen))
{
activity = "looking at the map";
}
else if (context.UiState.HasFlag(UiState.IsInCombat))
{
activity = "in combat";
}
// The game link emits the current player's map ID and specialization ID
// Additional information about those can be retrieved from the API
var maps = await gw2.Maps.GetMaps(cancellationToken: stoppingToken);
var mapsDictionary = maps.Value.ToDictionary(map => map.Id);

Console.WriteLine(
"[{0}] {1}, the {2} {3} ({4}) is {5} on {6} in {7}, Position: {{ Right = {8}, Up = {9}, Front = {10} }}",
snapshot.UiTick,
identity.Name,
identity.Race,
identity.Profession,
specialization,
activity,
context.IsMounted ? context.GetMount() : "foot",
map.Name,
pos[0],
pos[1],
pos[2]
);
}
var specializations =
await gw2.Specializations.GetSpecializations(cancellationToken: stoppingToken);
var specializationsDictionary =
specializations.Value.ToDictionary(specialization => specialization.Id);

public void OnError(Exception error)
{
}
gameLink.Subscribe(
snapshot =>
{
var pos = snapshot.AvatarPosition;

public void OnCompleted()
{
if (!snapshot.TryGetIdentity(out var identity, MissingMemberBehavior.Error))
{
return;
}

if (!snapshot.TryGetContext(out var context))
{
return;
}

var specialization = "no specialization";
if (specializationsDictionary.TryGetValue(identity.SpecializationId, out var found))
{
specialization = found.Name;
}

var map = mapsDictionary[identity.MapId];
var activity = "traveling";
if (!context.UiState.HasFlag(UiState.GameHasFocus))
{
activity = "afk-ing";
}
else if (context.UiState.HasFlag(UiState.TextboxHasFocus))
{
activity = "typing";
}
else if (context.UiState.HasFlag(UiState.IsMapOpen))
{
activity = "looking at the map";
}
else if (context.UiState.HasFlag(UiState.IsInCombat))
{
activity = "in combat";
}

logger.LogInformation(
"[{UiTick}] {Name}, the {Race} {Profession} ({Specialization}) is {Activity} on {Transport} in {Map}, Position: {{ Right = {Pos0}, Up = {Pos1}, Front = {Pos2} }}",
snapshot.UiTick,
identity.Name,
identity.Race,
identity.Profession,
specialization,
activity,
context.IsMounted ? context.GetMount() : "foot",
map.Name,
pos[0],
pos[1],
pos[2]
);
},
stoppingToken
);

// Wait indefinitely until the application is stopped
await Task.Delay(Timeout.InfiniteTimeSpan, stoppingToken);
}
}
6 changes: 6 additions & 0 deletions samples/Mumble/Mumble.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="System.Reactive" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\GW2SDK\GW2SDK.csproj" />
</ItemGroup>
Expand Down
50 changes: 16 additions & 34 deletions samples/Mumble/Program.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GuildWars2;
using GuildWars2.Exploration.Maps;
using GuildWars2.Specializations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Mumble;

Console.OutputEncoding = Encoding.UTF8;
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en");
Expand All @@ -19,34 +17,18 @@
return;
}

var cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, args) =>
{
cts.Cancel();
args.Cancel = true; // don't terminate the app
};
var builder = Host.CreateApplicationBuilder(args);

using var httpClient = new HttpClient();
var gw2 = new Gw2Client(httpClient);
HashSet<Map> maps = await gw2.Maps.GetMaps(cancellationToken: cts.Token);
HashSet<Specialization> specializations =
await gw2.Specializations.GetSpecializations(cancellationToken: cts.Token);
builder.Services.AddHttpClient<Gw2Client>();
builder.Services.AddHostedService<GameReporter>();
builder.Logging.AddSimpleConsole(
options =>
{
options.SingleLine = true;
options.TimestampFormat = "HH:mm:ss.fff ";
options.UseUtcTimestamp = true;
});

var gameObserver = new GameReporter();
foreach (var map in maps)
{
gameObserver.Maps[map.Id] = map;
}
var app = builder.Build();

foreach (var specialization in specializations)
{
gameObserver.Specializations[specialization.Id] = specialization;
}

using var gameLink = GameLink.Open();
using var subscription = gameLink.Subscribe(gameObserver);

while (!cts.IsCancellationRequested)
{
await Task.Delay(100);
}
app.Run();

0 comments on commit 26ea81a

Please sign in to comment.