Skip to content

Commit

Permalink
Add detailed multiplayer features, add settings to control metadata i…
Browse files Browse the repository at this point in the history
…mport (#18)
  • Loading branch information
sharkusmanch authored Mar 20, 2022
1 parent e553739 commit 1ff2eee
Show file tree
Hide file tree
Showing 20 changed files with 1,385 additions and 36 deletions.
2 changes: 1 addition & 1 deletion extension.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Id: PCGamingWikiMetadata_c038558e-427b-4551-be4c-be7009ce5a8d
Name: PCGamingWiki Metadata Provider
Author: sharkusmanch
Version: 0.4.0
Version: 0.5.0
Module: PCGamingWikiMetadata.dll
Type: MetadataProvider
Icon: icon.png
8 changes: 8 additions & 0 deletions manifest.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
AddonId: PCGamingWikiMetadata_c038558e-427b-4551-be4c-be7009ce5a8d
Packages:
- Version: 0.5.0
RequiredApiVersion: 6.2.2
ReleaseDate: 2022-03-20
PackageUrl: https://github.com/sharkusmanch/playnite-pcgamingwiki-metadata-provider/releases/download/v0.5.0/PCGamingWiki_Metadata_Provider_v0.5.0.pext
Changelog:
- Add Controller Support feature.
- Add detailed multiplayer features (LAN, Local, Online, etc)
- Add settings to enable/disable importing of multiplayer features, xbox play anywhere tag, and engine tag
- Version: 0.4.0
RequiredApiVersion: 6.2.2
ReleaseDate: 2022-03-01
Expand Down
8 changes: 8 additions & 0 deletions src/Localization/en_US.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib">

<sys:String x:Key="LOCPCGWSettingsImportXboxPlayAnywhere">Add Xbox Play Anywhere tag to supported titles</sys:String>
<sys:String x:Key="LOCPCGWSettingsImportEngineTags">Add game engine tags</sys:String>
<sys:String x:Key="LOCPCGWSettingsImportMultiplayerTypes">Add detailed multiplayer features</sys:String>

</ResourceDictionary>
8 changes: 5 additions & 3 deletions src/PCGWClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ public class PCGWClient
private readonly string baseUrl = @"https://www.pcgamingwiki.com/w/api.php";
private RestClient client;
protected MetadataRequestOptions options;
protected PCGamingWikiMetadataSettings settings;

public PCGWClient(MetadataRequestOptions options)
public PCGWClient(MetadataRequestOptions options, PCGamingWikiMetadataSettings settings)
{
client = new RestClient(baseUrl);
this.options = options;
this.settings = settings;
}

public JObject ExecuteRequest(RestRequest request)
Expand Down Expand Up @@ -107,8 +109,8 @@ public virtual void FetchGamePageContent(PCGWGame game)
logger.Error($"Encountered API error: {error.ToString()}");
}

PCGamingWikiJSONParser jsonParser = new PCGamingWikiJSONParser(content, game);
PCGamingWikiHTMLParser parser = new PCGamingWikiHTMLParser(jsonParser.PageHTMLText(), game);
PCGamingWikiJSONParser jsonParser = new PCGamingWikiJSONParser(content, game, this.settings);
PCGamingWikiHTMLParser parser = new PCGamingWikiHTMLParser(jsonParser.PageHTMLText(), game, this.settings);

jsonParser.ParseGameDataJson();
parser.ApplyGameMetadata();
Expand Down
45 changes: 44 additions & 1 deletion src/PCGWGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,22 @@ protected bool GetReception(string aggregator, out int? score)
return this.reception.TryGetValue(aggregator, out score);
}

public void AddControllerSupport(string description)
public void AddFullControllerSupport(string description)
{
if (description == PCGamingWikiType.Rating.NativeSupport)
{
this.AddFeature("Full Controller Support");
}
}

public void AddControllerSupport(string description)
{
if (description == PCGamingWikiType.Rating.NativeSupport)
{
this.AddFeature("Controller Support");
}
}

public void AddCloudSaves(string launcher, string description)
{
BuiltinExtension? extension = LauncherNameToPluginID(launcher);
Expand All @@ -115,6 +123,41 @@ public void AddCloudSaves(string launcher, string description)
}
}

private void AddMultiplayerFeatures(string featureBaseName, IList<string> types)
{
foreach (string type in types)
{
this.AddFeature($"{featureBaseName}: {type}");
}
}

public void AddMultiplayerLocal(string rating, IList<string> types)
{
if (rating == PCGamingWikiType.Rating.NativeSupport)
{
this.AddFeature("Local Multiplayer");
AddMultiplayerFeatures("Local Multiplayer", types);
}
}

public void AddMultiplayerLAN(string rating, IList<string> types)
{
if (rating == PCGamingWikiType.Rating.NativeSupport)
{
this.AddFeature("LAN Multiplayer");
AddMultiplayerFeatures("LAN Multiplayer", types);
}
}

public void AddMultiplayerOnline(string rating, IList<string> types)
{
if (rating == PCGamingWikiType.Rating.NativeSupport)
{
this.AddFeature("Online Multiplayer");
AddMultiplayerFeatures("Online Multiplayer", types);
}
}

private BuiltinExtension? LauncherNameToPluginID(string launcher)
{
switch (launcher)
Expand Down
105 changes: 89 additions & 16 deletions src/PCGamingWikiHTMLParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,26 @@ public class PCGamingWikiHTMLParser
private readonly ILogger logger = LogManager.GetLogger();
private HtmlDocument doc;
private PCGWGame game;
private PCGamingWikiMetadataSettings settings;

public PCGamingWikiHTMLParser(string html, PCGWGame game)
public PCGamingWikiHTMLParser(string html, PCGWGame game, PCGamingWikiMetadataSettings settings)
{
this.doc = new HtmlDocument();
this.doc.LoadHtml(html);
this.game = game;
this.settings = settings;
}

public void ApplyGameMetadata()
{
ParseInput();
ParseCloudSync();
ParseInfobox();

if (this.settings.ImportMultiplayerTypes)
{
ParseMultiplayer();
}
}

private void RemoveCitationsFromHTMLNode(HtmlNode node)
Expand All @@ -39,17 +46,85 @@ private void RemoveCitationsFromHTMLNode(HtmlNode node)
}
}

private void ParseInput()
private IList<HtmlNode> SelectTableRowsByClass(string tableId, string rowClass)
{
var table = this.doc.DocumentNode.SelectSingleNode("//table[@id='table-settings-input']");
var table = this.doc.DocumentNode.SelectSingleNode($"//table[@id='{tableId}']");

if (table == null)
if (table != null)
{
return;
return table.SelectNodes($"//tr[@class='{rowClass}']");
}

var rows = table.SelectNodes("//tr[@class='template-infotable-body table-settings-input-body-row']");
return new List<HtmlNode>();
}

private void ParseMultiplayer()
{
var rows = SelectTableRowsByClass("table-network-multiplayer", "template-infotable-body table-network-multiplayer-body-row");
string networkType = "";
string rating = "";

foreach (HtmlNode row in rows)
{
foreach (HtmlNode child in row.SelectNodes(".//th|td"))
{
switch (child.Attributes["class"].Value)
{
case "table-network-multiplayer-body-parameter":
networkType = child.FirstChild.InnerText;
break;
case "table-network-multiplayer-body-rating":
rating = child.FirstChild.Attributes["title"].Value;
break;
case "table-network-multiplayer-body-notes":
IList<string> notes = ParseMultiplayerNotes(child);

switch (networkType)
{
case "Local play":
this.game.AddMultiplayerLocal(rating, notes);
break;
case "LAN play":
this.game.AddMultiplayerLAN(rating, notes);
break;
case "Online play":
this.game.AddMultiplayerOnline(rating, notes);
break;
default:
break;

}
rating = "";
networkType = "";
break;
}
}
}
}

private IList<string> ParseMultiplayerNotes(HtmlNode notes)
{
List<string> multiplayerTypes = new List<string>();

Regex pattern = new Regex(@"class=""table-network-multiplayer-body-notes"">(?<mode1>(Co-op|Versus))?(,)?(&#32;)?(?<mode2>(Co-op|Versus))?<br>");
Match match = pattern.Match(notes.OuterHtml);

if (match.Groups["mode1"].Success)
{
multiplayerTypes.Add(match.Groups["mode1"].Value);
}

if (match.Groups["mode2"].Success)
{
multiplayerTypes.Add(match.Groups["mode2"].Value);
}

return multiplayerTypes;
}

private void ParseInput()
{
var rows = SelectTableRowsByClass("table-settings-input", "template-infotable-body table-settings-input-body-row");
string param = "";

foreach (HtmlNode row in rows)
Expand All @@ -65,6 +140,9 @@ private void ParseInput()
switch (param)
{
case "Full controller support":
this.game.AddFullControllerSupport(child.FirstChild.Attributes["title"].Value);
break;
case "Controller support":
this.game.AddControllerSupport(child.FirstChild.Attributes["title"].Value);
break;
default:
Expand All @@ -80,15 +158,7 @@ private void ParseInput()

private void ParseCloudSync()
{
var table = this.doc.DocumentNode.SelectSingleNode("//table[@id='table-cloudsync']");

if (table == null)
{
return;
}

var rows = table.SelectNodes("//tr[@class='template-infotable-body table-cloudsync-body-row']");

var rows = SelectTableRowsByClass("table-cloudsync", "template-infotable-body table-cloudsync-body-row");
string launcher = "";

foreach (HtmlNode row in rows)
Expand Down Expand Up @@ -156,7 +226,10 @@ private void ParseInfobox()
ApplyReleaseDate(key, text);
break;
case "Engines":
this.game.AddTaxonomy("Engines", text);
if (this.settings.ImportEngineTags)
{
this.game.AddTaxonomy("Engines", text);
}
break;
case "Developers":
AddCompany(child, this.game.Developers);
Expand Down
7 changes: 5 additions & 2 deletions src/PCGamingWikiJSONParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ public class PCGamingWikiJSONParser
{
private PCGWGame game;
private JObject content;
public PCGamingWikiJSONParser(JObject content, PCGWGame game)
private PCGamingWikiMetadataSettings settings;

public PCGamingWikiJSONParser(JObject content, PCGWGame game, PCGamingWikiMetadataSettings settings)
{
this.content = content;
this.game = game;
this.settings = settings;
}

public void ParseGameDataJson()
Expand All @@ -24,7 +27,7 @@ public void ParseGameDataJson()

JToken playAnywhere = this.content.SelectToken("$.parse.links[?(@.* == 'List of Xbox Play Anywhere games')]");

if (playAnywhere != null)
if (playAnywhere != null && this.settings.ImportXboxPlayAnywhere)
{
game.SetXboxPlayAnywhere();
}
Expand Down
8 changes: 8 additions & 0 deletions src/PCGamingWikiMetadata.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,12 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<Content Include="Localization/*.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion src/PCGamingWikiMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public PCGamingWikiMetadataProvider(MetadataRequestOptions options, PCGamingWiki
{
this.options = options;
this.plugin = plugin;
this.client = new PCGWClient(this.options);
this.client = new PCGWClient(this.options, (PCGamingWikiMetadataSettings)this.plugin.GetSettings(false));
}

public override string GetName(GetMetadataFieldArgs args)
Expand Down
25 changes: 23 additions & 2 deletions src/PCGamingWikiMetadataSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,32 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;

namespace PCGamingWikiMetadata
{
public class PCGamingWikiMetadataSettings : ISettings
public class PCGamingWikiMetadataSettings : ISettings, INotifyPropertyChanged
{
private readonly PCGamingWikiMetadata plugin;

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

private bool importEngineTags = true;
public bool ImportEngineTags { get { return importEngineTags; } set { importEngineTags = value; ; NotifyPropertyChanged("ImportEngineTags"); } }
private bool importXboxPlayAnywhere = true;
public bool ImportXboxPlayAnywhere { get { return importXboxPlayAnywhere; } set { importXboxPlayAnywhere = value; ; NotifyPropertyChanged("ImportXboxPlayAnywhere"); } }

private bool importMultiplayerTypes = false;
public bool ImportMultiplayerTypes { get { return importMultiplayerTypes; } set { importMultiplayerTypes = value; ; NotifyPropertyChanged("ImportMultiplayerTypes"); } }


// Parameterless constructor must exist if you want to use LoadPluginSettings method.
public PCGamingWikiMetadataSettings()
{
Expand All @@ -28,7 +47,9 @@ public PCGamingWikiMetadataSettings(PCGamingWikiMetadata plugin)
// LoadPluginSettings returns null if not saved data is available.
if (savedSettings != null)
{
// empty for now
ImportEngineTags = savedSettings.ImportEngineTags;
ImportXboxPlayAnywhere = savedSettings.ImportXboxPlayAnywhere;
ImportMultiplayerTypes = savedSettings.ImportMultiplayerTypes;
}
}

Expand Down
12 changes: 11 additions & 1 deletion src/PCGamingWikiMetadataSettingsView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="600">
<StackPanel>
<TextBlock Text="No settings currently available"/>
<StackPanel Margin="15">
<CheckBox IsChecked="{Binding ImportEngineTags}" Content="{DynamicResource LOCPCGWSettingsImportEngineTags}"/>
</StackPanel>

<StackPanel Margin="15">
<CheckBox IsChecked="{Binding ImportXboxPlayAnywhere}" Content="{DynamicResource LOCPCGWSettingsImportXboxPlayAnywhere}"/>
</StackPanel>

<StackPanel Margin="15">
<CheckBox IsChecked="{Binding ImportMultiplayerTypes}" Content="{DynamicResource LOCPCGWSettingsImportMultiplayerTypes}"/>
</StackPanel>
</StackPanel>
</UserControl>
Loading

0 comments on commit 1ff2eee

Please sign in to comment.