Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions CVRMelonAssistant/CVRMelonAssistant.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,21 @@
<Error Condition="!Exists('..\packages\ILRepack.MSBuild.Task.2.0.13\build\ILRepack.MSBuild.Task.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ILRepack.MSBuild.Task.2.0.13\build\ILRepack.MSBuild.Task.props'))" />
</Target>
<Target Name="ILRepack" AfterTargets="Build" Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

<PropertyGroup>
<WorkingDirectory>$(MSBuildThisFileDirectory)bin\$(Configuration)\$(TargetFramework)</WorkingDirectory>
</PropertyGroup>

<ILRepack OutputType="$(OutputType)" MainAssembly="$(AssemblyName).exe" OutputAssembly="$(AssemblyName).exe" InputAssemblies="$(WorkingDirectory)\Mono.Cecil.dll" WilcardInputAssemblies="true" WorkingDirectory="$(WorkingDirectory)" />

</Target>
<PropertyGroup>
<WorkingDirectory>$(MSBuildThisFileDirectory)bin\$(Configuration)\$(TargetFramework)</WorkingDirectory>
</PropertyGroup>
<ItemGroup>
<InputAssemblies Include="$(WorkingDirectory)\Mono.Cecil.dll" />
<InputAssemblies Include="$(WorkingDirectory)\Microsoft.Bcl.AsyncInterfaces.dll" />
<InputAssemblies Include="$(WorkingDirectory)\System.Buffers.dll" />
<InputAssemblies Include="$(WorkingDirectory)\System.IO.Pipelines.dll" />
<InputAssemblies Include="$(WorkingDirectory)\System.Memory.dll" />
<InputAssemblies Include="$(WorkingDirectory)\System.Runtime.CompilerServices.Unsafe.dll" />
<InputAssemblies Include="$(WorkingDirectory)\System.Text.Encodings.Web.dll" />
<InputAssemblies Include="$(WorkingDirectory)\System.Text.Json.dll" />
<InputAssemblies Include="$(WorkingDirectory)\System.Threading.Tasks.Extensions.dll" />
<InputAssemblies Include="$(WorkingDirectory)\System.Numerics.Vectors.dll" />
</ItemGroup>
<ILRepack OutputType="$(OutputType)" MainAssembly="$(AssemblyName).exe" OutputAssembly="$(AssemblyName).exe" InputAssemblies= "@(InputAssemblies)" WilcardInputAssemblies="true" WorkingDirectory="$(WorkingDirectory)" />
</Target>
</Project>
28 changes: 27 additions & 1 deletion CVRMelonAssistant/Classes/InstallHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using System.Windows;
using CVRMelonAssistant.Pages;
Expand Down Expand Up @@ -41,6 +43,29 @@ public static bool RemoveMelonLoader()
return true;
}

private static async Task<string?> GetLatestWindowsMelonLoaderNightlyDownloadUrl()
{
const string apiUrl =
"https://api.github.com/repos/LavaGang/MelonLoader/actions/workflows/5411546/runs" +
"?branch=alpha-development&event=push&status=success&per_page=1&sort=created&direction=desc";

using var http = new HttpClient();

// GitHub requires a user-agent header
http.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0");

var resp = await http.GetStringAsync(apiUrl);
var json = JsonNode.Parse(resp)!["workflow_runs"]!.AsArray();

if (json.Count == 0)
return null;

var run = json[0];
var runId = run!["id"]!.ToString();

return $"https://nightly.link/LavaGang/MelonLoader/actions/runs/{runId}/MelonLoader.Windows.x64.CI.Release.zip";
}

public static async Task InstallMelonLoader()
{
if (!RemoveMelonLoader()) return;
Expand All @@ -49,7 +74,8 @@ public static async Task InstallMelonLoader()
{
MainWindow.Instance.MainText = $"{(string) App.Current.FindResource("Mods:DownloadingMelonLoader")}...";

using var installerZip = await DownloadFileToMemory("https://github.com/LavaGang/MelonLoader/releases/latest/download/MelonLoader.x64.zip");
string nightlyLink = await GetLatestWindowsMelonLoaderNightlyDownloadUrl();
using var installerZip = await DownloadFileToMemory(nightlyLink);
using var zipReader = new ZipArchive(installerZip, ZipArchiveMode.Read);

MainWindow.Instance.MainText = $"{(string) App.Current.FindResource("Mods:UnpackingMelonLoader")}...";
Expand Down
6 changes: 6 additions & 0 deletions CVRMelonAssistant/Classes/Mod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class Mod
public string installedVersion;
public bool installedInBrokenDir;
public bool installedInRetiredDir;
public int flag;

public class ModVersion
{
Expand All @@ -38,4 +39,9 @@ public class ModVersion
public bool IsPlugin => modType.Equals("plugin", StringComparison.InvariantCultureIgnoreCase);
}
}
public class FlagEntry
{
public int _id;
public int flag;
}
}
2 changes: 1 addition & 1 deletion CVRMelonAssistant/Classes/Updater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace CVRMelonAssistant
{
class Updater
{
private static readonly string APILatestURL = "https://api.github.com/repos/knah/CVRMelonAssistant/releases/latest";
private static readonly string APILatestURL = "https://api.github.com/repos/Nirv-git/CVRMelonAssistant/releases/latest";

private static Update LatestUpdate;
private static Version CurrentVersion;
Expand Down
1 change: 1 addition & 0 deletions CVRMelonAssistant/Classes/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class Constants
{
public const string ChilloutVRAppId = "661130";
public const string CVRMGModsJson = "https://api.cvrmg.com/v1/mods";
public const string CVRMGModsFlagsJson = "https://gist.githubusercontent.com/Nirv-git/1963e20d855c401349820a93b4d2639b/raw/cvrModFlags.json";
public const string WeebCDNAPIURL = "https://pat.assistant.moe/api/v1.0/";
public const string MD5Spacer = " ";
public static readonly char[] IllegalCharacters = new char[]
Expand Down
6 changes: 4 additions & 2 deletions CVRMelonAssistant/Localisation/en.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
ChilloutVR allows modding the game under certain conditions, specifically as long as mods are not used for evil.
</Span>
<Span x:Key="Intro:Terms:Term0">
ChilloutVR Modding Assistant and mods provided here are not associated with or endorsed by Alpha Blend Interactive (the devloper).
ChilloutVR Modding Assistant and mods provided here are not associated with or endorsed by ChilloutVR.
</Span>
<Span x:Key="Intro:Terms:Term1">
Mods
Expand Down Expand Up @@ -113,6 +113,8 @@
<sys:String x:Key="Mods:FailedExtract">Failed to extract {0}, trying again in {1} seconds. ({2}/{3})</sys:String>
<sys:String x:Key="Mods:FailedExtractMaxReached">Failed to extract {0} after max attempts ({1}), skipping. This mod might not work properly so proceed at your own risk</sys:String>
<sys:String x:Key="Mods:SearchLabel">Search...</sys:String>
<sys:String xml:space="preserve" x:Key="Mods:SymKey">★ - Recommend for most users ⓘ - Niche, make sure you understand what the mod does</sys:String>
<!-- <sys:String xml:space="preserve" x:Key="Mods:SymKey">★ - Recommend for most users ♥ - Well liked ⓘ - Niche, make sure you understand what the mod does</sys:String> -->

<!-- About Page -->
<sys:String x:Key="About:Title">About</sys:String>
Expand Down Expand Up @@ -199,5 +201,5 @@
<sys:String x:Key="ModInfoWindow:NoDescription">No description available</sys:String>
<sys:String x:Key="ModInfoWindow:DownloadLink">Download link: </sys:String>
<sys:String x:Key="ModInfoWindow:SourceCodeLink">Source code: </sys:String>
<sys:String x:Key="ModInfoWindow:InternalIds">Internal ID: {0} {1}</sys:String>
<sys:String x:Key="ModInfoWindow:InternalIds">Internal ID: {0} - {1}</sys:String>
</ResourceDictionary>
2 changes: 1 addition & 1 deletion CVRMelonAssistant/ModInfoWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<TextBlock />
<TextBlock Name="SourceCodeLink" />
<TextBlock Name="DownloadLink" />
<TextBlock Name="InternalIds" />
<TextBlock Name="InternalIds" FontStyle="Italic" FontSize="10" />
</StackPanel>
</ScrollViewer>
</Grid>
Expand Down
96 changes: 95 additions & 1 deletion CVRMelonAssistant/ModInfoWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using static System.Windows.Forms.LinkLabel;

namespace CVRMelonAssistant
{
Expand All @@ -16,6 +19,10 @@ public void SetMod(Mod mod)
Title = string.Format((string) FindResource("ModInfoWindow:Title"), mod.versions[0].name);

ModDescription.Text = mod.versions[0].description ?? (string) FindResource("ModInfoWindow:NoDescription");

var desc = mod.versions[0].description ?? (string)FindResource("ModInfoWindow:NoDescription");
SetMarkdownText(ModDescription, desc);

ModName.Text = mod.versions[0].name;
ModAuthor.Text = string.Format((string) FindResource("ModInfoWindow:Author"), mod.versions[0].author ?? FindResource("ModInfoWindow:NoAuthor"));
ModVersion.Text = mod.versions[0].modVersion;
Expand All @@ -39,9 +46,96 @@ public void SetMod(Mod mod)
InternalIds.Text = string.Format((string) FindResource("ModInfoWindow:InternalIds"), mod._id, mod.versions[0]._version);
}

private static readonly Regex Linkish = new(
@"\[(?<text>[^\]]+)\]\((?<url>https?://[^\s)]+)\)|<(?<auto>https?://[^>\s]+)>",
RegexOptions.Compiled | RegexOptions.IgnoreCase);

private static readonly Regex Emphasis = new(
@"(?<strongem>\*\*\*.+?\*\*\*|___.+?___)|(?<strong>\*\*.+?\*\*|__.+?__)|(?<em>\*(?!\s).+?\*|_(?!\s).+?_)",
RegexOptions.Compiled);

public void SetMarkdownText(TextBlock tb, string? text)
{
tb.Inlines.Clear();
if (string.IsNullOrEmpty(text)) return;

int last = 0;
foreach (Match m in Linkish.Matches(text))
{
if (m.Index > last)
AddFormattedText(tb.Inlines, text.Substring(last, m.Index - last));

if (m.Groups["url"].Success)
{ // [text](url)
var url = m.Groups["url"].Value;
var linkText = m.Groups["text"].Value;
var link = CreateHyperlink(linkText, url);
tb.Inlines.Add(link);
}
else
{ // <url>
string url = m.Groups["auto"].Value;
tb.Inlines.Add(CreateHyperlink(url));
}
last = m.Index + m.Length;
}

if (last < text.Length)
AddFormattedText(tb.Inlines, text.Substring(last));
}

// Parse **bold**, *italics*, and ***bold+italics***
private static void AddFormattedText(InlineCollection inlines, string text)
{
int last = 0;
foreach (Match m in Emphasis.Matches(text))
{
if (m.Index > last)
inlines.Add(new Run(text.Substring(last, m.Index - last)));

Inline styled;
if (m.Groups["strongem"].Success)
{
string inner = StripOuter(m.Value, 3);
styled = new Run(inner) { FontWeight = FontWeights.Bold, FontStyle = FontStyles.Italic };
}
else if (m.Groups["strong"].Success)
{
string inner = StripOuter(m.Value, 2);
styled = new Run(inner) { FontWeight = FontWeights.Bold };
}
else // em
{
string inner = StripOuter(m.Value, 1);
styled = new Run(inner) { FontStyle = FontStyles.Italic };
}

inlines.Add(styled);
last = m.Index + m.Length;
}

if (last < text.Length)
inlines.Add(new Run(text.Substring(last)));
}

private static string StripOuter(string s, int n)
{
if (s.Length >= 2 * n) return s.Substring(n, s.Length - 2 * n);
return s;
}

private static Hyperlink CreateHyperlink(string uri)
{
var link = new Hyperlink(new Run(uri)) {NavigateUri = new Uri(uri)};
var link = new Hyperlink { NavigateUri = new Uri(uri) };
link.Inlines.Add(new Run(uri));
link.RequestNavigate += HyperlinkExtensions.Hyperlink_RequestNavigate;
return link;
}

private static Hyperlink CreateHyperlink(string text, string uri)
{
var link = new Hyperlink { NavigateUri = new Uri(uri) };
link.Inlines.Add(new Run(text));
link.RequestNavigate += HyperlinkExtensions.Hyperlink_RequestNavigate;
return link;
}
Expand Down
59 changes: 48 additions & 11 deletions CVRMelonAssistant/Pages/Mods.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,45 @@
<TextBlock
Name="SearchText"
Grid.Row="0"
Height="20"
Height="30"
Padding="5,0,0,0"
Panel.ZIndex="1"
Background="{DynamicResource BottomStatusBarBackground}"
Foreground="{DynamicResource TextColor}"
Text="{DynamicResource Mods:SearchLabel}" />
Text="{DynamicResource Mods:SearchLabel}"
FontSize="20"/>
<TextBox
Name="SearchBar"
Grid.Row="0"
Height="20"
Height="30"
Margin="0,-1,0,0"
Padding="3,1,0,0"
Panel.ZIndex="2"
Background="#00000000"
BorderThickness="0"
Foreground="{DynamicResource TextColor}"
TextChanged="SearchBar_TextChanged" />
TextChanged="SearchBar_TextChanged"
FontSize="20"/>
<ListView
Name="ModsListView"
Grid.Row="1"
Grid.Column="0"
SelectionChanged="ModsListView_SelectionChanged"
SelectionMode="Single"
MouseDoubleClick="ModsListView_OnMouseDoubleClick">
MouseDoubleClick="ModsListView_OnMouseDoubleClick"
Margin="0,0,0,20"
ScrollViewer.CanContentScroll="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingPanel.CacheLengthUnit="Item"
VirtualizingPanel.CacheLength="2">

<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="30">
<GridViewColumn Width="25">
<GridViewColumn.Header>
<Button
Name="SearchButton"
Expand All @@ -79,8 +90,23 @@
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding ModName}" Header="{DynamicResource Mods:Header:Name}" />
<GridViewColumn Header="{DynamicResource Mods:Header:Author}">

<GridViewColumn Width="30">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding GetFlagString}"
TextAlignment="Center"
Width="20"
Foreground="{Binding GetFlagColor}"
FontSize="22"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

<GridViewColumn DisplayMemberBinding="{Binding ModName}" Header="{DynamicResource Mods:Header:Name}" Width="265"/>
<GridViewColumn Header="{DynamicResource Mods:Header:Author}" Width="140">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Expand All @@ -91,7 +117,7 @@
</GridViewColumn.CellTemplate>
</GridViewColumn>

<GridViewColumn x:Name="InstalledColumn" Header="{DynamicResource Mods:Header:Installed}">
<GridViewColumn x:Name="InstalledColumn" Header="{DynamicResource Mods:Header:Installed}" Width="95">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Expand All @@ -102,8 +128,8 @@
</GridViewColumn.CellTemplate>
</GridViewColumn>

<GridViewColumn DisplayMemberBinding="{Binding ModVersion}" Header="{DynamicResource Mods:Header:Latest}" />
<GridViewColumn x:Name="DescriptionColumn" Header="{DynamicResource Mods:Header:Description}">
<GridViewColumn DisplayMemberBinding="{Binding ModVersion}" Header="{DynamicResource Mods:Header:Latest}" Width="50"/>
<GridViewColumn x:Name="DescriptionColumn" Header="{DynamicResource Mods:Header:Description}" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
Expand Down Expand Up @@ -159,6 +185,17 @@
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>

<TextBlock
Name="SymbolsKey"
VerticalAlignment="Bottom"
Grid.Row="5"
Height="20"
Padding="10,0,0,0"
Background="{DynamicResource BottomStatusBarBackground}"
Foreground="{DynamicResource TextColor}"
Text="{DynamicResource Mods:SymKey}"/>

</Grid>
</Grid>
</Page>
Loading