From 90b3f81fba9331a3c9852b83f2a210d6f8724d2d Mon Sep 17 00:00:00 2001 From: Archomeda Date: Sun, 29 Mar 2020 19:56:32 +0200 Subject: [PATCH] Catch JsonException in Mumble Link and expose RawIdentity --- CHANGELOG.md | 9 ++- Gw2Sharp.Tests/Mumble/Gw2MumbleClientTests.cs | 1 + Gw2Sharp/Mumble/Gw2MumbleClient.cs | 67 +++++++++++++------ Gw2Sharp/Mumble/IGw2MumbleClient.cs | 5 ++ MumbleLinkReader/Form1.Designer.cs | 44 +++++++++--- MumbleLinkReader/Form1.cs | 1 + MumbleLinkReader/Form1.resx | 3 +- 7 files changed, 96 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 005bef286..47c821190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,15 @@ # Gw2Sharp History +## 0.9.3 +### Services +- Exposed the raw JSON Mumble Link identity as `IGw2MumbleClient.RawIdentity` + +### Fixes +- When the Mumble Link identity contains an invalid JSON, it will no longer cause Gw2Sharp to throw a JsonException (this can happen when running multiple instances of Guild Wars 2 at the same time) + ## 0.9.2 ### Fixes -- Setting a custom user agent now properly sets a space inbetween the that and the one set by Gw2Sharp +- Setting a custom user agent now properly sets a space inbetween that and the one set by Gw2Sharp ## 0.9.1 ### Endpoints diff --git a/Gw2Sharp.Tests/Mumble/Gw2MumbleClientTests.cs b/Gw2Sharp.Tests/Mumble/Gw2MumbleClientTests.cs index 7666b1e5b..e228a0af6 100644 --- a/Gw2Sharp.Tests/Mumble/Gw2MumbleClientTests.cs +++ b/Gw2Sharp.Tests/Mumble/Gw2MumbleClientTests.cs @@ -44,6 +44,7 @@ public void ReadStructCorrectlyTest() Assert.Equal(0.8136908, client.CameraFront.X, 7); Assert.Equal(-0.3139677, client.CameraFront.Y, 7); Assert.Equal(-0.4892152, client.CameraFront.Z, 7); + Assert.Equal(@"{""name"":""Reiga Fiercecrusher"",""profession"":2,""spec"":18,""race"":1,""map_id"":1206,""world_id"":268435460,""team_color_id"":0,""commander"":false,""map"":1206,""fov"":0.960,""uisz"":1}", client.RawIdentity); Assert.Equal("Reiga Fiercecrusher", client.CharacterName); Assert.Equal(ProfessionType.Warrior, client.Profession); Assert.Equal(RaceType.Charr, client.Race); diff --git a/Gw2Sharp/Mumble/Gw2MumbleClient.cs b/Gw2Sharp/Mumble/Gw2MumbleClient.cs index 22a3dc71e..b77eff21c 100644 --- a/Gw2Sharp/Mumble/Gw2MumbleClient.cs +++ b/Gw2Sharp/Mumble/Gw2MumbleClient.cs @@ -27,6 +27,7 @@ public class Gw2MumbleClient : BaseClient, IGw2MumbleClient internal static readonly char[] mumbleLinkGameName = new[] { 'G', 'u', 'i', 'l', 'd', ' ', 'W', 'a', 'r', 's', ' ', '2', '\0' }; private const string EMPTY_IDENTITY = "{}"; + private string rawIdentity = EMPTY_IDENTITY; private readonly object identityLock = new object(); private readonly object serverAddressLock = new object(); @@ -54,37 +55,48 @@ protected internal Gw2MumbleClient(IConnection connection, IGw2Client gw2Client) () => this.memoryMappedFile.Value.CreateViewAccessor(), true); } - private string identityCache = EMPTY_IDENTITY; - private CharacterIdentity? identity; - private unsafe CharacterIdentity? Identity + private unsafe void UpdateIdentityIfNeeded() { - get - { - // Check if we're in the same frame update - if (this.linkedMem.identity[0] == '\0') - return this.identity; + // Check if we're in the same frame update + if (this.linkedMem.identity[0] == '\0') + return; - // Thread-safety - lock (this.identityLock) + // Thread-safety + lock (this.identityLock) + { + // Check again + if (this.linkedMem.identity[0] != '\0') { - // Check again - if (this.linkedMem.identity[0] != '\0') + var cacheSpan = this.rawIdentity.AsSpan(); + fixed (char* ptr = this.linkedMem.identity) { - var cacheSpan = this.identityCache.AsSpan(); - fixed (char* ptr = this.linkedMem.identity) + // Check if the identity is different from last update + var span = new ReadOnlySpan(ptr, this.rawIdentity.Length); + if (!span.SequenceEqual(cacheSpan)) { - // Check if the identity is different from last update - var span = new ReadOnlySpan(ptr, this.identityCache.Length); - if (!span.SequenceEqual(cacheSpan)) + // Update cache + this.rawIdentity = new string(ptr); + try + { + this.identity = JsonSerializer.Deserialize(this.rawIdentity, deserializerSettings); + } + catch (JsonException) { - // Update and parse JSON - this.identityCache = new string(ptr); - this.identity = JsonSerializer.Deserialize(this.identityCache, deserializerSettings); + this.identity = null; } } - this.linkedMem.identity[0] = '\0'; } + this.linkedMem.identity[0] = '\0'; } + } + } + + private CharacterIdentity? identity; + private unsafe CharacterIdentity? Identity + { + get + { + this.UpdateIdentityIfNeeded(); return this.identity; } } @@ -242,6 +254,19 @@ public unsafe string ServerAddress public uint Instance => this.IsAvailable ? this.linkedMem.context.instance : default; + /// + public unsafe string RawIdentity + { + get + { + if (!this.IsAvailable) + return string.Empty; + + this.UpdateIdentityIfNeeded(); + return this.rawIdentity; + } + } + /// public string CharacterName => this.IsAvailable && this.Identity != null ? this.Identity.Name : string.Empty; diff --git a/Gw2Sharp/Mumble/IGw2MumbleClient.cs b/Gw2Sharp/Mumble/IGw2MumbleClient.cs index 17f2e7a5e..90e24408b 100644 --- a/Gw2Sharp/Mumble/IGw2MumbleClient.cs +++ b/Gw2Sharp/Mumble/IGw2MumbleClient.cs @@ -165,6 +165,11 @@ public interface IGw2MumbleClient : IClient, IDisposable /// uint Instance { get; } + /// + /// The raw identity in JSON. + /// + string RawIdentity { get; } + /// /// The character name. /// diff --git a/MumbleLinkReader/Form1.Designer.cs b/MumbleLinkReader/Form1.Designer.cs index cc5a96420..644fe3f6b 100644 --- a/MumbleLinkReader/Form1.Designer.cs +++ b/MumbleLinkReader/Form1.Designer.cs @@ -118,8 +118,10 @@ private void InitializeComponent() this.textBoxFieldOfView = new System.Windows.Forms.TextBox(); this.labelFieldOfView = new System.Windows.Forms.Label(); this.checkBoxCommander = new System.Windows.Forms.CheckBox(); - this.label1 = new System.Windows.Forms.Label(); + this.labelUiSize = new System.Windows.Forms.Label(); this.textBoxUiSize = new System.Windows.Forms.TextBox(); + this.labelRawIdentity = new System.Windows.Forms.Label(); + this.textBoxRawIdentity = new System.Windows.Forms.TextBox(); this.SuspendLayout(); // // labelVersion @@ -894,14 +896,14 @@ private void InitializeComponent() this.checkBoxCommander.Text = "IsCommander"; this.checkBoxCommander.UseVisualStyleBackColor = true; // - // label1 + // labelUiSize // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(12, 432); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(38, 13); - this.label1.TabIndex = 0; - this.label1.Text = "UiSize"; + this.labelUiSize.AutoSize = true; + this.labelUiSize.Location = new System.Drawing.Point(12, 432); + this.labelUiSize.Name = "labelUiSize"; + this.labelUiSize.Size = new System.Drawing.Size(38, 13); + this.labelUiSize.TabIndex = 0; + this.labelUiSize.Text = "UiSize"; // // textBoxUiSize // @@ -911,12 +913,32 @@ private void InitializeComponent() this.textBoxUiSize.Size = new System.Drawing.Size(206, 22); this.textBoxUiSize.TabIndex = 1; // + // labelRawIdentity + // + this.labelRawIdentity.AutoSize = true; + this.labelRawIdentity.Location = new System.Drawing.Point(672, 269); + this.labelRawIdentity.Name = "labelRawIdentity"; + this.labelRawIdentity.Size = new System.Drawing.Size(46, 13); + this.labelRawIdentity.TabIndex = 16; + this.labelRawIdentity.Text = "Identity"; + // + // textBoxRawIdentity + // + this.textBoxRawIdentity.Location = new System.Drawing.Point(778, 266); + this.textBoxRawIdentity.Multiline = true; + this.textBoxRawIdentity.Name = "textBoxRawIdentity"; + this.textBoxRawIdentity.ReadOnly = true; + this.textBoxRawIdentity.Size = new System.Drawing.Size(312, 73); + this.textBoxRawIdentity.TabIndex = 17; + // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1109, 460); - this.Controls.Add(this.label1); + this.Controls.Add(this.textBoxRawIdentity); + this.Controls.Add(this.labelRawIdentity); + this.Controls.Add(this.labelUiSize); this.Controls.Add(this.textBoxUiSize); this.Controls.Add(this.textBoxFieldOfView); this.Controls.Add(this.labelFieldOfView); @@ -1112,8 +1134,10 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBoxFieldOfView; private System.Windows.Forms.Label labelFieldOfView; private System.Windows.Forms.CheckBox checkBoxCommander; - private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label labelUiSize; private System.Windows.Forms.TextBox textBoxUiSize; + private System.Windows.Forms.Label labelRawIdentity; + private System.Windows.Forms.TextBox textBoxRawIdentity; } } diff --git a/MumbleLinkReader/Form1.cs b/MumbleLinkReader/Form1.cs index cf0cd38b8..00bad1d50 100644 --- a/MumbleLinkReader/Form1.cs +++ b/MumbleLinkReader/Form1.cs @@ -125,6 +125,7 @@ private void MumbleLoop() this.textBoxCameraFront2.Text = m.CameraFront.Y.ToString(); this.textBoxCameraFront3.Text = m.CameraFront.Z.ToString(); + this.textBoxRawIdentity.Text = m.RawIdentity; this.textBoxCharacterName.Text = m.CharacterName; this.textBoxRace.Text = m.Race.ToString(); this.textBoxSpecialization.Text = m.Specialization.ToString(); diff --git a/MumbleLinkReader/Form1.resx b/MumbleLinkReader/Form1.resx index e8ae276d9..f298a7be8 100644 --- a/MumbleLinkReader/Form1.resx +++ b/MumbleLinkReader/Form1.resx @@ -1,5 +1,4 @@ - - +