Compare commits

..

9 Commits

Author SHA1 Message Date
3ed7191acf Use System.Text.Json with BepInEx (#1)
When running via BepInEx, Unity's JsonUtility produces and reads empty documents.

As a bit of a hacky fix, this builds using System.Text.Json. granted, this pulls new deps in. All of the deps listed in the csproj will need to be included in the install package for BepInEx.

Reviewed-on: #1
Co-authored-by: Adele Reed <virepri2k@gmail.com>
Co-committed-by: Adele Reed <virepri2k@gmail.com>
2024-08-06 17:26:31 +00:00
971f8f6c2b Update README.md 2024-06-01 17:52:53 +00:00
18c559847c Add warning for MelonLoader 2024-06-01 07:41:41 +00:00
a664f59f4b Create external folder for dependencies 2024-05-23 16:25:12 +07:00
2a92885367 Release 0.1.2 2024-05-23 16:18:12 +07:00
fefc398f07 Refactor and support BepInEx's native plugin format 2024-05-23 16:13:19 +07:00
6056dbcb31 License 2024-05-22 22:32:34 +07:00
c9f0759905 mention bundled zip 2024-05-22 03:58:22 +07:00
ddf57a3640 Force Unity to accept all certificates 2024-05-22 03:53:02 +07:00
61 changed files with 1068 additions and 433 deletions

4
.gitignore vendored
View File

@ -489,5 +489,5 @@ fabric.properties
# End of https://www.toptal.com/developers/gitignore/api/csharp,rider,dotnetcore
External
!External/.gitkeep
External/*
!External/.gitkeep

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

14
LICENSE Normal file
View File

@ -0,0 +1,14 @@
BSD Zero Clause License
Copyright (c) 2024 beerpsi
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

140
README.md
View File

@ -1,59 +1,81 @@
# Rizu
A Tachi score hook for maimai DX.
Tested versions:
- BUDDiES
## Installation
First, get the [config file](https://kamai.tachi.ac/client-file-flow/CIaa7b4d91041688189231cfc696c0754120b1790b) and
place it in the same folder as the game executable (Sinmai.exe), then follow one of the methods below (**either**
BepInEx **or** hard-patching using MonoMod).
### BepInEx
#### Installing BepInEx
- Update [segatools](https://gitea.tendokyu.moe/Dniel97/segatools/releases/latest).
- Download [BepInEx 5](https://github.com/BepInEx/BepInEx/releases/tag/v5.4.23.1).
- Extract the `BepInEx` folder from the archive into the base game folder, ignoring other files.
- Edit `segatools.ini`, adding this entry:
```ini
[unity]
targetAssembly=BepInEx\core\BepInEx.Preloader.dll
```
#### Installing the MonoMod loader for BepInEx
- Download the [MonoMod loader for BepInEx](https://github.com/BepInEx/BepInEx.MonoMod.Loader/releases/latest)
- Extract the `BepInEx` folder from the archive into the base game folder.
#### Installing the score hook
- Download `Assembly-CSharp.Rizu.mm.dll` from [releases](https://gitea.tendokyu.moe/beerpsi/Rizu/releases/latest) and
place it in `BepInEx/monomod`.
In the end, your game directory should look like this:
```
└───BepInEx
└───monomod
└───Assembly-CSharp.Rizu.mm.dll
├───Sinmai_Data
├───Rizu.cfg
├───Sinmai.exe
└───segatools.ini
```
### Hard-patching using MonoMod
- Download [MonoMod](https://github.com/MonoMod/MonoMod/releases/latest).
- Download `Assembly-CSharp.Rizu.mm.dll` from[releases](https://gitea.tendokyu.moe/beerpsi/Rizu/releases/latest)
and place it in `Sinmai_Data/Managed`.
- Run `MonoMod.exe path\to\Sinmai_Data\Managed\Assembly-CSharp.dll` in a command prompt.
- Rename `MONOMODDED_Assembly-CSharp.dll` to `Assembly-CSharp.dll`, optionally backing up the original file.
## Development
Copy these files from `Sinmai_Data/Managed` into `Rizu/External`:
- `Assembly-CSharp.dll`
- `UnityEngine.dll`
- `UnityEngine.CoreModule.dll`
- `UnityEngine.JSONSerializeModule.dll`
- `UnityEngine.UnityWebRequestModule.dll`
You will also need to download [MonoMod](https://github.com/MonoMod/MonoMod/releases/latest). and extract to `Rizu/External`.
After that, the project can be restored and built normally.
# Rizu
A Tachi score hook for maimai DX.
Tested versions:
- BUDDiES
## Installation
First, get the [config file](https://kamai.tachi.ac/client-file-flow/CIaa7b4d91041688189231cfc696c0754120b1790b) and
place it in the same folder as the game executable (Sinmai.exe), then follow **only** one of three methods:
- [BepInEx (fast)](#bepinex-fast)
- [BepInEx](#bepinex)
- [Hard-patching using MonoMod](#hard-patching-using-monomod)
### BepInEx (fast)
- Update [segatools](https://gitea.tendokyu.moe/Dniel97/segatools/releases/latest).
- Download [Rizu-BepInEx-v0.1.2.zip](https://gitea.tendokyu.moe/beerpsi/Rizu/releases/download/v0.1.2/Rizu-BepInEx-v0.1.2.zip).
- Extract the zip into the base game folder (containing `Sinmai.exe`).
- Edit `segatools.ini`, adding this entry:
```ini
[unity]
targetAssembly=BepInEx\core\BepInEx.Preloader.dll
```
> **Warning**
>
> If you have MelonLoader installed (for YuanCon ADX HID input or other mods):
> - Grab [MLLoader-UnityMono-BepInEx5-v0.5.7.zip](https://github.com/BepInEx/BepInEx.MelonLoader.Loader/releases/download/v2.1.0/MLLoader-UnityMono-BepInEx5-v0.5.7.zip) and extract this zip into the base game folder, overwriting any conflicts. This allow BepInEx to also load MelonLoader mods.
> - Delete `version.dll`, which is used to load MelonLoader, from the game folder.
### BepInEx
#### Installing BepInEx
- Update [segatools](https://gitea.tendokyu.moe/Dniel97/segatools/releases/latest).
- Download [BepInEx v5.4.22](https://github.com/BepInEx/BepInEx/releases/tag/v5.4.22) (>=v5.4.23 does not work on stable segatools!).
- Extract the `BepInEx` folder from the archive into the base game folder, ignoring other files.
- Edit `segatools.ini`, adding this entry:
```ini
[unity]
targetAssembly=BepInEx\core\BepInEx.Preloader.dll
```
#### Installing the score hook
- Download [Rizu-v0.1.2.zip](https://gitea.tendokyu.moe/beerpsi/Rizu/releases/download/v0.1.2/Rizu-v0.1.2.zip).
- Extract it into the base game folder.
In the end, your game directory should look like this:
```
└───BepInEx
└───plugins
└───Rizu
├───Rizu.dll
└───Rizu.Core.dll
├───Sinmai_Data
├───Rizu.cfg
├───Sinmai.exe
└───segatools.ini
```
> **Warning**
>
> If you have MelonLoader installed (for YuanCon ADX HID input or other mods):
> - Grab [MLLoader-UnityMono-BepInEx5-v0.5.7.zip](https://github.com/BepInEx/BepInEx.MelonLoader.Loader/releases/download/v2.1.0/MLLoader-UnityMono-BepInEx5-v0.5.7.zip) and extract this zip into the base game folder, overwriting any conflicts. This allow BepInEx to also load MelonLoader mods.
> - Delete `version.dll`, which is used to load MelonLoader, from the game folder.
### Hard-patching using MonoMod
- Download [MonoMod](https://github.com/MonoMod/MonoMod/releases/latest).
- Download `Assembly-CSharp.Rizu.mm.dll` from [releases](https://gitea.tendokyu.moe/beerpsi/Rizu/releases/latest)
and place it in `Sinmai_Data/Managed`.
- Run `MonoMod.exe path\to\Sinmai_Data\Managed\Assembly-CSharp.dll` in a command prompt.
- Rename `MONOMODDED_Assembly-CSharp.dll` to `Assembly-CSharp.dll`, optionally backing up the original file.
## Development
Copy these files from `Sinmai_Data/Managed` into `External`:
- `Assembly-CSharp.dll`
- `UnityEngine.dll`
- `UnityEngine.CoreModule.dll`
- `UnityEngine.JSONSerializeModule.dll`
- `UnityEngine.UnityWebRequestModule.dll`
You will also need to download [MonoMod](https://github.com/MonoMod/MonoMod/releases/latest). and extract to `External`.
After that, the project can be restored and built normally.

View File

@ -0,0 +1,38 @@
using System.Reflection;
using Game;
using HarmonyLib;
using Manager;
using Rizu.Core;
namespace Rizu.BepInEx;
[HarmonyPatch(typeof(GameScoreList))]
public class PatchGameScoreList
{
// New field introduced in SDEZ 1.40 (maimai DX BUDDiES)
private static readonly FieldInfo UtageKanjiTextField = typeof(SessionInfo)
.GetField("utageKanjiText", BindingFlags.Instance | BindingFlags.Public);
// ReSharper disable once InconsistentNaming
[HarmonyPatch(nameof(GameScoreList.SetPlayAfterRate))]
[HarmonyPostfix]
private static void SetPlayAfterRatePostfix(GameScoreList __instance, int musicRate, int danRate, UdemaeID dan, int classValue)
{
if (!__instance.IsEnable)
{
return;
}
if (__instance.SessionInfo.isAdvDemo || __instance.SessionInfo.isTutorial)
{
return;
}
if (UtageKanjiTextField != null && !string.IsNullOrEmpty((string)UtageKanjiTextField.GetValue(__instance.SessionInfo)))
{
return;
}
RizuPlugin.Instance.StartCoroutine(Exporter.Instance.ExportScore(__instance));
}
}

View File

@ -0,0 +1,27 @@
using HarmonyLib;
using Manager.UserDatas;
using Rizu.Core;
namespace Rizu.BepInEx;
[HarmonyPatch(typeof(UserDetail))]
public class PatchUserDetail
{
// ReSharper disable once InconsistentNaming
[HarmonyPatch(nameof(UserDetail.CourseRank), MethodType.Setter)]
[HarmonyPrefix]
private static bool CourseRankPrefix(UserDetail __instance, ref uint value)
{
var previousValue = __instance.CourseRank;
// Don't send an import if it's the same rank
if (value == previousValue || value == 0)
{
return true;
}
RizuPlugin.Instance.StartCoroutine(Exporter.Instance.ExportDan(__instance));
return true;
}
}

View File

@ -4,12 +4,12 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Rizu")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("Rizu.BepInEx")]
[assembly: AssemblyDescription("Tachi score hook for maimai DX")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Rizu")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyCopyright("Copyright © beerpsi 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("0.1.2.0")]
[assembly: AssemblyFileVersion("0.1.2.0")]

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4DDF918E-7A74-4266-B56A-028D66ED336F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Rizu.BepInEx</RootNamespace>
<AssemblyName>Rizu</AssemblyName>
<Product>Rizu</Product>
<Version>0.1.2</Version>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources>
https://api.nuget.org/v3/index.json;
https://nuget.bepinex.dev/v3/index.json
</RestoreAdditionalProjectSources>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'BepInEx (Debug)|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<OutputPath>bin\BepInEx (Debug)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'BepInEx (Release)|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<OutputPath>bin\BepInEx (Release)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<PackageReference Include="BepInEx.Analyzers" Version="1.*" PrivateAssets="all" />
<PackageReference Include="BepInEx.BaseLib" Version="5.*" GeneratePathProperty="true" />
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="2.*" />
<PackageReference Include="HarmonyX" Version="2.12.0" GeneratePathProperty="true" />
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>..\External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="PatchGameScoreList.cs" />
<Compile Include="PatchUserDetail.cs" />
<Compile Include="RizuPlugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Rizu.Core\Rizu.Core.csproj">
<Project>{4241a369-1619-4450-8182-cb66f447985f}</Project>
<Name>Rizu.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,34 @@
using BepInEx;
using HarmonyLib;
using Rizu.Core;
namespace Rizu.BepInEx;
[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]
[BepInProcess("Sinmai.exe")]
public class RizuPlugin : BaseUnityPlugin
{
public static RizuPlugin Instance { get; private set; }
private Harmony _harmony;
private void Awake()
{
Instance = this;
Exporter.Instance.LoadConfig();
if (!Exporter.Instance.IsEnabled)
{
return;
}
_harmony = new Harmony(MyPluginInfo.PLUGIN_GUID);
_harmony.PatchAll();
}
private void OnDestroy()
{
_harmony?.UnpatchSelf();
}
}

10
Rizu.Core/App.config Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?><configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

13
Rizu.Core/Config.cs Normal file
View File

@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Rizu.Core;
public class Config
{
public bool Enabled;
public int NetworkTimeout;
public string FailedImportsFolder;
public string TachiBaseUrl;
public string TachiImportEndpoint;
public Dictionary<string, string> AccessTokens = new();
}

View File

@ -1,6 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
@ -8,19 +7,20 @@ using MAI2.Util;
using MAI2System;
using Manager;
using Manager.UserDatas;
using Rizu.Models;
using Rizu.Core.Models;
using UnityEngine;
using UnityEngine.Networking;
using Path = System.IO.Path;
namespace Rizu;
namespace Rizu.Core;
public class Exporter : SingletonMonoBehaviour<Exporter>
public class Exporter
{
protected Exporter()
{
_dontDestroyOnLoad = true;
}
public static readonly Exporter Instance = new();
private readonly Config _config = new();
public bool IsEnabled => _config.Enabled;
// ReSharper disable Unity.PerformanceAnalysis
public IEnumerator ExportScore(GameScoreList score)
@ -29,11 +29,21 @@ public class Exporter : SingletonMonoBehaviour<Exporter>
{
yield break;
}
var user = Singleton<UserDataManager>.Instance.GetUserData(score.PlayerIndex);
var import = ScoreConversion.CreateScoreBatchManual(score);
yield return SubmitImport(import, user.Detail.AccessCode);
var user = Singleton<UserDataManager>.Instance.GetUserData(score.PlayerIndex);
string import = "";
try
{
import = ScoreConversion.CreateScoreBatchManual(score);
}
catch (Exception exception)
{
Logger.Error(exception.ToString());
}
if (import != "")
yield return SubmitImport(import, user.Detail.AccessCode);
}
public IEnumerator ExportDan(UserDetail userDetail)
@ -93,7 +103,7 @@ public class Exporter : SingletonMonoBehaviour<Exporter>
using var certHandler = new ForceAcceptAllCertificateHandler();
req.method = UnityWebRequest.kHttpVerbPOST;
req.timeout = _config.NetworkTimeout;
// req.certificateHandler = certHandler;
req.certificateHandler = certHandler;
req.uploadHandler = new UploadHandlerRaw(new UTF8Encoding().GetBytes(import));
req.downloadHandler = new DownloadHandlerBuffer();
req.SetRequestHeader("Content-Type", "application/json");
@ -123,9 +133,10 @@ public class Exporter : SingletonMonoBehaviour<Exporter>
TachiResponse<BatchManualResponseBody> resp;
Logger.Debug("Received response from Tachi (Response code {1}): {0}", req.downloadHandler.text, req.responseCode);
try
{
resp = JsonUtility.FromJson<TachiResponse<BatchManualResponseBody>>(req.downloadHandler.text);
resp = JsonShim.Deserialize<TachiResponse<BatchManualResponseBody>>(req.downloadHandler.text);
}
catch (Exception e)
{
@ -139,12 +150,11 @@ public class Exporter : SingletonMonoBehaviour<Exporter>
yield break;
}
Logger.Info("{0}", resp.description);
var pollUrl = resp.body?.url;
if (string.IsNullOrEmpty(pollUrl))
{
Logger.Debug("Received no poll uri!");
yield break;
}
@ -170,7 +180,7 @@ public class Exporter : SingletonMonoBehaviour<Exporter>
try
{
pollResp = JsonUtility.FromJson<TachiResponse<ImportStatusResponseBody>>(pollReq.downloadHandler.text);
pollResp = JsonShim.Deserialize<TachiResponse<ImportStatusResponseBody>>(pollReq.downloadHandler.text);
}
catch (Exception e)
{
@ -199,7 +209,7 @@ public class Exporter : SingletonMonoBehaviour<Exporter>
}
}
private void SaveFailedImport(string path, string import)
private static void SaveFailedImport(string path, string import)
{
var parent = Path.GetDirectoryName(path);
@ -210,7 +220,7 @@ public class Exporter : SingletonMonoBehaviour<Exporter>
File.WriteAllText(path, import);
}
public void LoadConfig()
{
using var ini = new IniFile(".\\Rizu.cfg");
@ -239,16 +249,4 @@ public class Exporter : SingletonMonoBehaviour<Exporter>
Logger.Info("> Tachi import URL: {0}{1}", _config.TachiBaseUrl, _config.TachiImportEndpoint);
Logger.Info("> {0} API key{1} loaded", _config.AccessTokens.Count, _config.AccessTokens.Count != 1 ? "s" : "");
}
private readonly Config _config = new();
private class Config
{
public bool Enabled;
public int NetworkTimeout;
public string FailedImportsFolder;
public string TachiBaseUrl;
public string TachiImportEndpoint;
public Dictionary<string, string> AccessTokens = new();
}
}

View File

@ -1,6 +1,6 @@
using UnityEngine.Networking;
namespace Rizu;
namespace Rizu.Core;
public class ForceAcceptAllCertificateHandler : CertificateHandler
{

39
Rizu.Core/JsonShim.cs Normal file
View File

@ -0,0 +1,39 @@
namespace Rizu.Core;
/*
* JsonShim creates a single place that JSON APIs get called from, to avoid having to manually write precompiler directives every time.
* Never call a JSON package directly, always call via JsonShim.
*/
#if MONOMOD
using UnityEngine;
using System;
#else
using System.Text.Json;
#endif
public class JsonShim
{
public static string Serialize(object Target)
{
#if MONOMOD
return JsonUtility.ToJson(Target);
#else
return JsonSerializer.Serialize(Target);
#endif
}
public static T Deserialize<T>(string data)
{
#if MONOMOD
return JsonUtility.FromJson<T>(data);
#else
return JsonSerializer.Deserialize<T>(data);
#endif
}
}
#if MONOMOD
[AttributeUsage(AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple = false)]
public class JsonIncludeAttribute : Attribute { }
#endif

View File

@ -1,7 +1,7 @@
using System.Diagnostics;
using JetBrains.Annotations;
namespace Rizu;
namespace Rizu.Core;
// UnityEngine.Debug logs don't show up in BepInEx logs for some reason
public static class Logger
@ -54,5 +54,4 @@ public static class Logger
{
System.Console.WriteLine($"{LogPrefix} [{level}] {format}", args);
}
}
}

View File

@ -0,0 +1,18 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManual
{
[JsonInclude]
public BatchManualMeta meta = new();
[JsonInclude]
public BatchManualScore[] scores;
[JsonInclude]
public BatchManualMatchingClass classes;
}

View File

@ -0,0 +1,14 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManualDan
{
[JsonInclude]
public string dan;
}

View File

@ -0,0 +1,14 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManualMatchingClass
{
[JsonInclude]
public string matchingClass;
}

View File

@ -0,0 +1,18 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManualMeta
{
[JsonInclude]
public string game = "maimaidx";
[JsonInclude]
public string playtype = "Single";
[JsonInclude]
public string service = "Rizu";
}

View File

@ -0,0 +1,18 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManualOptional
{
[JsonInclude]
public uint fast;
[JsonInclude]
public uint slow;
[JsonInclude]
public uint maxCombo;
}

View File

@ -0,0 +1,18 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManualRankUp
{
[JsonInclude]
public BatchManualMeta meta = new();
[JsonInclude]
public BatchManualScore[] scores;
[JsonInclude]
public BatchManualDan classes;
}

View File

@ -0,0 +1,14 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManualResponseBody
{
[JsonInclude]
public string url;
}

View File

@ -0,0 +1,28 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManualScore
{
[JsonInclude]
public float percent;
[JsonInclude]
public string lamp;
[JsonInclude]
public string matchType = "songTitle";
[JsonInclude]
public string identifier;
[JsonInclude]
public string difficulty;
[JsonInclude]
public long timeAchieved;
[JsonInclude]
public BatchManualScoreJudgements judgements;
[JsonInclude]
public BatchManualOptional optional;
}

View File

@ -0,0 +1,22 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class BatchManualScoreJudgements
{
[JsonInclude]
public uint pcrit;
[JsonInclude]
public uint perfect;
[JsonInclude]
public uint great;
[JsonInclude]
public uint good;
[JsonInclude]
public uint miss;
}

View File

@ -0,0 +1,18 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class ImportDocument
{
[JsonInclude]
public string[] scoreIDs;
[JsonInclude]
public ImportErrContent[] errors;
[JsonInclude]
public SessionInfoReturn[] createdSessions;
}

View File

@ -0,0 +1,16 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class ImportErrContent
{
[JsonInclude]
public string type;
[JsonInclude]
public string message;
}

View File

@ -0,0 +1,16 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class ImportProgress
{
[JsonInclude]
public string description;
[JsonInclude]
public int value;
}

View File

@ -0,0 +1,18 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class ImportStatusResponseBody
{
[JsonInclude]
public string importStatus;
[JsonInclude]
public ImportProgress progress;
[JsonInclude]
public ImportDocument import;
}

View File

@ -0,0 +1,16 @@
using System;
#if BEPINEX
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class SessionInfoReturn
{
[JsonInclude]
public string type;
[JsonInclude]
public string sessionID;
}

View File

@ -0,0 +1,18 @@
using System;
#if BEPINEX // When we're building for BepInEx, the dummy JsonInclude is *not* defined, so let's cover that base.
using System.Text.Json.Serialization;
#endif
namespace Rizu.Core.Models;
[Serializable]
public class TachiResponse<T>
{
[JsonInclude]
public bool success;
[JsonInclude]
public string description;
[JsonInclude]
public T body;
}

View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Rizu.Core")]
[assembly: AssemblyDescription("Tachi score hook for maimai DX")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Rizu.Core")]
[assembly: AssemblyCopyright("Copyright © beerpsi 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4241A369-1619-4450-8182-CB66F447985F")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.2.0")]
[assembly: AssemblyFileVersion("0.1.2.0")]

146
Rizu.Core/Rizu.Core.csproj Normal file
View File

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4241A369-1619-4450-8182-CB66F447985F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Rizu.Core</RootNamespace>
<AssemblyName>Rizu.Core</AssemblyName>
<Version>0.1.2</Version>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'MonoMod (Release)|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>MONOMOD;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<OutputPath>bin\MonoMod (Release)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'MonoMod (Debug)|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>MONOMOD;DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<OutputPath>bin\MonoMod (Debug)\</OutputPath>
</PropertyGroup>
<ItemGroup Condition="$(DefineConstants.Contains(MONOMOD))">
<Reference Include="UnityEngine.JSONSerializeModule">
<HintPath>..\External\UnityEngine.JSONSerializeModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'BepInEx (Debug)|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>BEPINEX;DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<OutputPath>bin\BepInEx (Debug)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'BepInEx (Release)|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>BEPINEX;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<OutputPath>bin\BepInEx (Release)\</OutputPath>
</PropertyGroup>
<ItemGroup Condition="$(DefineConstants.Contains(BEPINEX))">
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encodings.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
</Reference>
<Reference Include="System.Text.Json, Version=8.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Json.8.0.4\lib\net462\System.Text.Json.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
</Reference>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UnityWebRequestModule">
<HintPath>..\External\UnityEngine.UnityWebRequestModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Config.cs" />
<Compile Include="Exporter.cs" />
<Compile Include="ForceAcceptAllCertificateHandler.cs" />
<Compile Include="JsonShim.cs" />
<Compile Include="Logger.cs" />
<Compile Include="Models\BatchManual.cs" />
<Compile Include="Models\BatchManualDan.cs" />
<Compile Include="Models\BatchManualMatchingClass.cs" />
<Compile Include="Models\BatchManualMeta.cs" />
<Compile Include="Models\BatchManualOptional.cs" />
<Compile Include="Models\BatchManualRankUp.cs" />
<Compile Include="Models\BatchManualResponseBody.cs" />
<Compile Include="Models\BatchManualScore.cs" />
<Compile Include="Models\BatchManualScoreJudgements.cs" />
<Compile Include="Models\ImportDocument.cs" />
<Compile Include="Models\ImportErrContent.cs" />
<Compile Include="Models\ImportProgress.cs" />
<Compile Include="Models\ImportStatusResponseBody.cs" />
<Compile Include="Models\SessionInfoReturn.cs" />
<Compile Include="Models\TachiResponse.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
<Compile Include="ScoreConversion.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -2,10 +2,9 @@
using DB;
using MAI2.Util;
using Manager;
using Rizu.Models;
using UnityEngine;
using Rizu.Core.Models;
namespace Rizu;
namespace Rizu.Core;
public static class ScoreConversion
{
@ -89,7 +88,7 @@ public static class ScoreConversion
score.matchType = "tachiSongID";
}
return JsonUtility.ToJson(new BatchManual
return JsonShim.Serialize(new BatchManual
{
meta = new BatchManualMeta(),
scores = [score],
@ -108,7 +107,7 @@ public static class ScoreConversion
return null;
}
return JsonUtility.ToJson(new BatchManualRankUp
return JsonShim.Serialize(new BatchManualRankUp
{
meta = new BatchManualMeta(),
scores = [],

12
Rizu.Core/packages.config Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net462" />
<package id="System.Buffers" version="4.5.1" targetFramework="net462" />
<package id="System.Memory" version="4.5.5" targetFramework="net462" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net462" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net462" />
<package id="System.Text.Encodings.Web" version="8.0.0" targetFramework="net462" />
<package id="System.Text.Json" version="8.0.4" targetFramework="net462" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net462" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net462" />
</packages>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- ILRepack -->
<Target Name="ILRepacker" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
<ItemGroup>
<InputAssemblies Include="$(OutputPath)\Rizu.MonoMod.dll" />
<InputAssemblies Include="$(OutputPath)\Rizu.Core.dll" />
</ItemGroup>
<ItemGroup>
<LibraryPaths Include="..\External" />
</ItemGroup>
<ILRepack
LogFile="ILRepack.log"
Parallel="true"
InputAssemblies="@(InputAssemblies)"
LibraryPath="@(LibraryPaths)"
TargetKind="Dll"
OutputFile="$(OutputPath)\Assembly-CSharp.Rizu.mm.dll" />
</Target>
<!-- /ILRepack -->
</Project>

View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Rizu.MonoMod")]
[assembly: AssemblyDescription("Tachi score hook for maimai DX")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Rizu")]
[assembly: AssemblyCopyright("Copyright © beerpsi 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("888E076C-8A77-453F-87DC-BC0186FDBB55")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.2.0")]
[assembly: AssemblyFileVersion("0.1.2.0")]

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{888E076C-8A77-453F-87DC-BC0186FDBB55}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Rizu.MonoMod</RootNamespace>
<AssemblyName>Rizu.MonoMod</AssemblyName>
<Version>0.1.2</Version>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'MonoMod (Debug)|AnyCPU' ">
<OutputPath>bin\MonoMod (Debug)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'MonoMod (Release)|AnyCPU' ">
<OutputPath>bin\MonoMod (Release)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="all" />
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.32" PrivateAssets="all" />
<Reference Include="Assembly-CSharp">
<HintPath>..\External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MonoMod">
<HintPath>..\External\MonoMod.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>..\External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="patch_GameScoreList.cs" />
<Compile Include="patch_AmManager.cs" />
<Compile Include="patch_UserDetail.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
<Compile Include="RizuMonoBehaviour.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="ILRepack.targets" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Rizu.Core\Rizu.Core.csproj">
<Project>{4241a369-1619-4450-8182-cb66f447985f}</Project>
<Name>Rizu.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,5 @@
using MAI2.Util;
namespace Rizu.MonoMod;
public class RizuMonoBehaviour : SingletonMonoBehaviour<RizuMonoBehaviour>;

View File

@ -1,7 +1,7 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using MAI2.Util;
using Rizu.Core;
using UnityEngine;
namespace Manager;
@ -13,8 +13,9 @@ public class patch_AmManager : AmManager
private void Execute_WaitAmDaemonReady()
{
var go = new GameObject { name = "Rizu" };
go.AddComponent<Rizu.Exporter>();
SingletonMonoBehaviour<Rizu.Exporter>.instance.LoadConfig();
go.AddComponent<Rizu.MonoMod.RizuMonoBehaviour>();
Exporter.Instance.LoadConfig();
orig_Execute_WaitAmDaemonReady();
}

View File

@ -0,0 +1,41 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using System.Reflection;
using Game;
using MAI2.Util;
using Rizu.Core;
using Rizu.MonoMod;
namespace Manager;
public class patch_GameScoreList(int index) : GameScoreList(index)
{
// New field introduced in SDEZ 1.40 (maimai DX BUDDiES)
private static readonly FieldInfo utageKanjiTextField = typeof(SessionInfo)
.GetField("utageKanjiText", BindingFlags.Instance | BindingFlags.Public);
private extern void orig_SetPlayAfterRate(int musicRate, int danRate, UdemaeID dan, int classValue);
public new void SetPlayAfterRate(int musicRate, int danRate, UdemaeID dan, int classValue)
{
orig_SetPlayAfterRate(musicRate, danRate, dan, classValue);
if (!IsEnable)
{
return;
}
if (SessionInfo.isAdvDemo || SessionInfo.isTutorial)
{
return;
}
if (utageKanjiTextField != null && !string.IsNullOrEmpty((string)utageKanjiTextField.GetValue(SessionInfo)))
{
return;
}
SingletonMonoBehaviour<RizuMonoBehaviour>.instance.StartCoroutine(Exporter.Instance.ExportScore(this));
}
}

View File

@ -2,6 +2,8 @@
// ReSharper disable InconsistentNaming
using MAI2.Util;
using Rizu.Core;
using Rizu.MonoMod;
namespace Manager.UserDatas;
@ -11,23 +13,16 @@ public class patch_UserDetail : UserDetail
public void set_CourseRank(uint value)
{
// Don't send an import if it's the same rank
if (value == CourseRank)
{
orig_set_CourseRank(value);
return;
}
var prevValue = CourseRank;
orig_set_CourseRank(value);
// Don't send an import if it's rank 0 (invalid)
if (value == 0)
// Don't send an import if it's the same rank
if (value == prevValue || value == 0)
{
return;
}
var exporter = SingletonMonoBehaviour<Rizu.Exporter>.instance;
exporter.StartCoroutine(exporter.ExportDan(this));
SingletonMonoBehaviour<RizuMonoBehaviour>.instance.StartCoroutine(Exporter.Instance.ExportDan(this));
}
}

View File

@ -1,16 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rizu", "Rizu\Rizu.csproj", "{888E076C-8A77-453F-87DC-BC0186FDBB55}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rizu.Core", "Rizu.Core\Rizu.Core.csproj", "{4241A369-1619-4450-8182-CB66F447985F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rizu.MonoMod", "Rizu.MonoMod\Rizu.MonoMod.csproj", "{888E076C-8A77-453F-87DC-BC0186FDBB55}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rizu.BepInEx", "Rizu.BepInEx\Rizu.BepInEx.csproj", "{4DDF918E-7A74-4266-B56A-028D66ED336F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
MonoMod (Debug)|Any CPU = MonoMod (Debug)|Any CPU
MonoMod (Release)|Any CPU = MonoMod (Release)|Any CPU
BepInEx (Release)|Any CPU = BepInEx (Release)|Any CPU
BepInEx (Debug)|Any CPU = BepInEx (Debug)|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{888E076C-8A77-453F-87DC-BC0186FDBB55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.Debug|Any CPU.Build.0 = Debug|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.Release|Any CPU.ActiveCfg = Release|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.Release|Any CPU.Build.0 = Release|Any CPU
{4DDF918E-7A74-4266-B56A-028D66ED336F}.MonoMod (Debug)|Any CPU.ActiveCfg = BepInEx (Debug)|Any CPU
{4DDF918E-7A74-4266-B56A-028D66ED336F}.MonoMod (Release)|Any CPU.ActiveCfg = BepInEx (Release)|Any CPU
{4DDF918E-7A74-4266-B56A-028D66ED336F}.BepInEx (Release)|Any CPU.ActiveCfg = BepInEx (Release)|Any CPU
{4DDF918E-7A74-4266-B56A-028D66ED336F}.BepInEx (Release)|Any CPU.Build.0 = BepInEx (Release)|Any CPU
{4DDF918E-7A74-4266-B56A-028D66ED336F}.BepInEx (Debug)|Any CPU.ActiveCfg = BepInEx (Debug)|Any CPU
{4DDF918E-7A74-4266-B56A-028D66ED336F}.BepInEx (Debug)|Any CPU.Build.0 = BepInEx (Debug)|Any CPU
{4241A369-1619-4450-8182-CB66F447985F}.MonoMod (Debug)|Any CPU.ActiveCfg = MonoMod (Debug)|Any CPU
{4241A369-1619-4450-8182-CB66F447985F}.MonoMod (Debug)|Any CPU.Build.0 = MonoMod (Debug)|Any CPU
{4241A369-1619-4450-8182-CB66F447985F}.MonoMod (Release)|Any CPU.ActiveCfg = MonoMod (Release)|Any CPU
{4241A369-1619-4450-8182-CB66F447985F}.MonoMod (Release)|Any CPU.Build.0 = MonoMod (Release)|Any CPU
{4241A369-1619-4450-8182-CB66F447985F}.BepInEx (Release)|Any CPU.ActiveCfg = BepInEx (Release)|Any CPU
{4241A369-1619-4450-8182-CB66F447985F}.BepInEx (Release)|Any CPU.Build.0 = BepInEx (Release)|Any CPU
{4241A369-1619-4450-8182-CB66F447985F}.BepInEx (Debug)|Any CPU.ActiveCfg = BepInEx (Debug)|Any CPU
{4241A369-1619-4450-8182-CB66F447985F}.BepInEx (Debug)|Any CPU.Build.0 = BepInEx (Debug)|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.MonoMod (Debug)|Any CPU.ActiveCfg = MonoMod (Debug)|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.MonoMod (Debug)|Any CPU.Build.0 = MonoMod (Debug)|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.MonoMod (Release)|Any CPU.ActiveCfg = MonoMod (Release)|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.MonoMod (Release)|Any CPU.Build.0 = MonoMod (Release)|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.BepInEx (Release)|Any CPU.ActiveCfg = MonoMod (Release)|Any CPU
{888E076C-8A77-453F-87DC-BC0186FDBB55}.BepInEx (Debug)|Any CPU.ActiveCfg = MonoMod (Debug)|Any CPU
EndGlobalSection
EndGlobal

View File

@ -1,11 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManual
{
public BatchManualMeta meta = new();
public BatchManualScore[] scores;
public BatchManualMatchingClass classes;
}

View File

@ -1,9 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManualDan
{
public string dan;
}

View File

@ -1,9 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManualMatchingClass
{
public string matchingClass;
}

View File

@ -1,11 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManualMeta
{
public string game = "maimaidx";
public string playtype = "Single";
public string service = "Rizu";
}

View File

@ -1,11 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManualOptional
{
public uint fast;
public uint slow;
public uint maxCombo;
}

View File

@ -1,11 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManualRankUp
{
public BatchManualMeta meta = new();
public BatchManualScore[] scores;
public BatchManualDan classes;
}

View File

@ -1,9 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManualResponseBody
{
public string url;
}

View File

@ -1,16 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManualScore
{
public float percent;
public string lamp;
public string matchType = "songTitle";
public string identifier;
public string difficulty;
public long timeAchieved;
public BatchManualScoreJudgements judgements;
public BatchManualOptional optional;
}

View File

@ -1,13 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class BatchManualScoreJudgements
{
public uint pcrit;
public uint perfect;
public uint great;
public uint good;
public uint miss;
}

View File

@ -1,11 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class ImportDocument
{
public string[] scoreIDs;
public ImportErrContent[] errors;
public SessionInfoReturn[] createdSessions;
}

View File

@ -1,10 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class ImportErrContent
{
public string type;
public string message;
}

View File

@ -1,10 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class ImportProgress
{
public string description;
public int value;
}

View File

@ -1,11 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class ImportStatusResponseBody
{
public string importStatus;
public ImportProgress progress;
public ImportDocument import;
}

View File

@ -1,10 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class SessionInfoReturn
{
public string type;
public string sessionID;
}

View File

@ -1,11 +0,0 @@
using System;
namespace Rizu.Models;
[Serializable]
public class TachiResponse<T>
{
public bool success;
public string description;
public T body;
}

View File

@ -1,111 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{888E076C-8A77-453F-87DC-BC0186FDBB55}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Rizu</RootNamespace>
<AssemblyName>Assembly-CSharp.Rizu.mm</AssemblyName>
<TargetFramework>net46</TargetFramework>
<FileAlignment>512</FileAlignment>
<LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources>
https://api.nuget.org/v3/index.json;
https://nuget.bepinex.dev/v3/index.json;
https://nuget.samboy.dev/v3/index.json
</RestoreAdditionalProjectSources>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="all" />
<Reference Include="Assembly-CSharp">
<HintPath>External\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MonoMod">
<HintPath>External\MonoMod.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>External\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>External\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.JSONSerializeModule">
<HintPath>External\UnityEngine.JSONSerializeModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UnityWebRequestModule">
<HintPath>External\UnityEngine.UnityWebRequestModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ForceAcceptAllCertificateHandler.cs" />
<Compile Include="Logger.cs" />
<Compile Include="Models\BatchManual.cs" />
<Compile Include="Models\BatchManualDan.cs" />
<Compile Include="Models\BatchManualMatchingClass.cs" />
<Compile Include="Models\BatchManualMeta.cs" />
<Compile Include="Models\BatchManualOptional.cs" />
<Compile Include="Models\BatchManualRankUp.cs" />
<Compile Include="Models\BatchManualResponseBody.cs" />
<Compile Include="Models\BatchManualScore.cs" />
<Compile Include="Models\BatchManualScoreJudgements.cs" />
<Compile Include="Models\ImportDocument.cs" />
<Compile Include="Models\ImportErrContent.cs" />
<Compile Include="Models\ImportProgress.cs" />
<Compile Include="Models\ImportStatusResponseBody.cs" />
<Compile Include="Models\SessionInfoReturn.cs" />
<Compile Include="Models\TachiResponse.cs" />
<Compile Include="patch_GameScoreList.cs" />
<Compile Include="patch_AmManager.cs" />
<Compile Include="patch_UserDetail.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
<Compile Include="Exporter.cs" />
<Compile Include="ScoreConversion.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Resources\Rizu.cfg" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,30 +0,0 @@
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
using MAI2.Util;
namespace Manager;
public class patch_GameScoreList(int index) : GameScoreList(index)
{
private extern void orig_SetPlayAfterRate(int musicRate, int danRate, UdemaeID dan, int classValue);
public new void SetPlayAfterRate(int musicRate, int danRate, UdemaeID dan, int classValue)
{
orig_SetPlayAfterRate(musicRate, danRate, dan, classValue);
if (!IsEnable)
{
return;
}
if (SessionInfo.isAdvDemo || SessionInfo.isTutorial || !string.IsNullOrEmpty(SessionInfo.utageKanjiText))
{
return;
}
var exporter = SingletonMonoBehaviour<Rizu.Exporter>.instance;
exporter.StartCoroutine(exporter.ExportScore(this));
}
}