Skip to content

Commit 56f5173

Browse files
committed
wip
1 parent 3ba0509 commit 56f5173

23 files changed

+1040
-204
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Threading.Tasks;
2+
using ModestTree;
3+
using SongCore.Patches;
4+
using UnityEngine.SceneManagement;
5+
6+
namespace SongCore
7+
{
8+
internal record BeatmapDataRequest(IBeatmapLevelData BeatmapLevelData, BeatmapKey BeatmapKey, float StartBpm, bool LoadingForDesignatedEnvironment, IEnvironmentInfo? TargetEnvironmentInfo, IEnvironmentInfo? OriginalEnvironmentInfo, BeatmapLevelDataVersion BeatmapLevelDataVersion, GameplayModifiers? GameplayModifiers, PlayerSpecificSettings? PlayerSpecificSettings, bool EnableBeatmapDataCaching)
9+
{
10+
public Task<IReadonlyBeatmapData?> Start(BeatmapDataLoader beatmapDataLoader, bool loadInGameScene = false)
11+
{
12+
if (!loadInGameScene)
13+
{
14+
Assert.That(SceneManager.GetActiveScene().name != "GameCore", "Beatmap data should not be loaded in the game scene, as GC is disabled. Set SongCore.Patches.BeatmapDataCachePatches.LoadBeatmapDataInGameScene to true to force loading.");
15+
}
16+
17+
return ReversePatches.BeatmapDataLoader.LoadBeatmapDataAsync(beatmapDataLoader, BeatmapLevelData, BeatmapKey, StartBpm, LoadingForDesignatedEnvironment, TargetEnvironmentInfo, OriginalEnvironmentInfo, BeatmapLevelDataVersion, GameplayModifiers, PlayerSpecificSettings, EnableBeatmapDataCaching);
18+
}
19+
}
20+
}

source/SongCore/BeatmapDataType.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace SongCore
2+
{
3+
internal enum BeatmapDataType
4+
{
5+
Beatmap,
6+
Lightshow,
7+
Audio
8+
}
9+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using SongCore.Patches;
4+
using SongCore.Utilities;
5+
6+
namespace SongCore
7+
{
8+
internal class BeatmapLevelCache
9+
{
10+
private static readonly int BeatmapDataTypeCount = Enum.GetValues(typeof(BeatmapDataType)).Length;
11+
12+
private readonly string?[] _jsonData = new string?[BeatmapDataTypeCount];
13+
private readonly Task<string?>?[] _jsonTasks = new Task<string?>?[BeatmapDataTypeCount];
14+
15+
public IBeatmapLevelData? BeatmapLevelData { get; set; }
16+
public BeatmapKey BeatmapKey { get; set; }
17+
public BeatmapDataRequest? BeatmapDataRequest { get; set; }
18+
public Task<IReadonlyBeatmapData?>? BeatmapDataLoadingTask { get; set; }
19+
20+
public void Invalidate()
21+
{
22+
BeatmapLevelData = null;
23+
BeatmapKey = new BeatmapKey();
24+
BeatmapDataRequest = null;
25+
BeatmapDataLoadingTask = null;
26+
27+
for (var i = 0; i < BeatmapDataTypeCount; i++)
28+
{
29+
_jsonData[i] = null;
30+
_jsonTasks[i] = null;
31+
}
32+
}
33+
34+
public string? GetJsonData(IBeatmapLevelData beatmapLevelData, BeatmapKey beatmapKey, BeatmapDataType beatmapDataType, Func<string?> original)
35+
{
36+
if (TryGetCachedJsonData(beatmapLevelData, beatmapKey, beatmapDataType, out var data))
37+
{
38+
return data;
39+
}
40+
41+
try
42+
{
43+
IOBlacklistPatch.AllowIO.Value = true;
44+
data = original();
45+
CacheJsonData(beatmapDataType, data);
46+
}
47+
finally
48+
{
49+
IOBlacklistPatch.AllowIO.Value = false;
50+
}
51+
52+
return data;
53+
}
54+
55+
public async Task<string?> GetJsonDataAsync(IBeatmapLevelData beatmapLevelData, BeatmapKey beatmapKey, BeatmapDataType beatmapDataType, Func<Task<string?>> original)
56+
{
57+
if (TryGetCachedJsonData(beatmapLevelData, beatmapKey, beatmapDataType, out var data))
58+
{
59+
return data;
60+
}
61+
62+
var idx = (int)beatmapDataType;
63+
64+
var cachedTask = _jsonTasks[idx];
65+
if (cachedTask != null)
66+
{
67+
return await cachedTask;
68+
}
69+
70+
try
71+
{
72+
IOBlacklistPatch.AllowIO.Value = true;
73+
var originalTask = original();
74+
_jsonTasks[idx] = originalTask;
75+
data = await originalTask;
76+
CacheJsonData(beatmapDataType, data);
77+
78+
return data;
79+
}
80+
finally
81+
{
82+
IOBlacklistPatch.AllowIO.Value = false;
83+
_jsonTasks[idx] = null;
84+
}
85+
}
86+
87+
private bool TryGetCachedJsonData(IBeatmapLevelData beatmapLevelData, BeatmapKey beatmapKey, BeatmapDataType beatmapDataType, out string? value)
88+
{
89+
Assertions.AssertMainThread();
90+
91+
if (IsForLevel(beatmapLevelData) && (beatmapDataType == BeatmapDataType.Audio || IsForDifficulty(beatmapKey)))
92+
{
93+
var cachedData = _jsonData[(int)beatmapDataType];
94+
if (cachedData != null)
95+
{
96+
Plugin.Log.Notice($"Returning {beatmapDataType} JSON data from cache");
97+
value = cachedData;
98+
return true;
99+
}
100+
}
101+
102+
value = null;
103+
return false;
104+
}
105+
106+
private void CacheJsonData(BeatmapDataType beatmapDataType, string? data)
107+
{
108+
Plugin.Log.Info($"Storing {beatmapDataType} JSON data in cache");
109+
_jsonData[(int)beatmapDataType] = data;
110+
}
111+
112+
public bool IsForLevel(IBeatmapLevelData levelData) => BeatmapLevelData == levelData;
113+
public bool IsForDifficulty(BeatmapKey beatmapKey) => beatmapKey.IsValid() && beatmapKey == BeatmapKey;
114+
}
115+
}

source/SongCore/Collections.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
using System.IO;
1010
using System.Linq;
1111
using System.Threading.Tasks;
12+
using BGLib.JsonExtension;
13+
using Newtonsoft.Json.Serialization;
1214
using UnityEngine;
1315

1416
namespace SongCore
@@ -61,12 +63,34 @@ public static string GetCustomLevelHash(string levelID)
6163
return CustomSongsData.GetValueOrDefault(levelID);
6264
}
6365

66+
private static readonly JsonSerializerSettings compactWithDefaultUnderscore = new(JsonSettings.compactWithDefault)
67+
{
68+
ContractResolver = new DefaultContractResolver
69+
{
70+
NamingStrategy = new UnderscoreNamingStrategy()
71+
}
72+
};
73+
6474
internal static void CreateCustomLevelSongData(string levelID, CustomLevelLoader.LoadedSaveData loadedSaveData)
6575
{
6676
var extraSongData = new SongData();
6777
if (CustomSongsData.TryAdd(levelID, extraSongData))
6878
{
79+
// SongDataClean songDataClean = null!;
80+
// if (loadedSaveData.standardLevelInfoSaveData != null)
81+
// {
82+
// songDataClean = JsonConvert.DeserializeObject<SongDataClean>(loadedSaveData.customLevelFolderInfo.levelInfoJsonString, compactWithDefaultUnderscore);
83+
// _ = songDataClean?.CustomData;
84+
// }
85+
// else if (loadedSaveData.beatmapLevelSaveData != null)
86+
// {
87+
// songDataClean = JsonConvert.DeserializeObject<SongDataClean>(loadedSaveData.customLevelFolderInfo.levelInfoJsonString, JsonSettings.compactWithDefault);
88+
// _ = songDataClean?.CustomData;
89+
// }
90+
6991
extraSongData.PopulateFromLoadedSaveData(loadedSaveData);
92+
93+
// Assert.IsEqual(JsonConvert.SerializeObject(extraSongData),JsonConvert.SerializeObject(songDataClean));
7094
}
7195
}
7296

source/SongCore/Data/SongData.cs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,148 @@
44
using System.Linq;
55
using Newtonsoft.Json;
66
using Newtonsoft.Json.Linq;
7+
using Newtonsoft.Json.Serialization;
78
using SongCore.Utilities;
89
using UnityEngine;
910

1011
namespace SongCore.Data
1112
{
13+
internal class UnderscoreNamingStrategy : NamingStrategy
14+
{
15+
protected override string ResolvePropertyName(string name)
16+
{
17+
return string.Create(name.Length + 1, name, (span, src) =>
18+
{
19+
span[0] = '_';
20+
span[1] = char.ToLowerInvariant(src[0]);
21+
src.AsSpan(1).CopyTo(span[2..]);
22+
});
23+
}
24+
}
25+
26+
public class SongDataClean
27+
{
28+
public CustomSongData? CustomData { get; init; }
29+
30+
public string? CustomEnvironment { get; init; }
31+
32+
public string? CustomEnvironmentHash { get; init; }
33+
34+
// [JsonAlias("_difficulties")]
35+
// public DifficultyData[] Difficulties { get; init; }
36+
37+
public BeatmapLevelColorSchemeSaveData[]? ColorSchemes { get; init; }
38+
39+
public string[]? EnvironmentNames { get; init; }
40+
41+
public required DifficultyBeatmapSet[] DifficultyBeatmapSets { get; init; }
42+
43+
public class DifficultyBeatmapSet
44+
{
45+
public required string BeatmapCharacteristicName { get; init; }
46+
47+
public required DifficultyBeatmap[] DifficultyBeatmaps { get; init; }
48+
49+
public CustomSongData? CustomData { get; init; }
50+
51+
public class CustomSongData
52+
{
53+
public string? CharacteristicLabel { get; init; }
54+
55+
public string? CharacteristicIconImageFilename { get; init; }
56+
}
57+
}
58+
59+
public class DifficultyBeatmap
60+
{
61+
public CustomSongData? CustomData { get; init; }
62+
63+
public class CustomSongData
64+
{
65+
public string[]? StyleTags { get; init; }
66+
67+
public string[]? Requirements { get; init; }
68+
69+
public string[]? Suggestions { get; init; }
70+
71+
public string[]? Warnings { get; init; }
72+
73+
public string[]? Information { get; init; }
74+
75+
public string? DifficultyLabel { get; init; }
76+
77+
public bool? OneSaber { get; init; }
78+
79+
public bool? ShowRotationNoteSpawnLines { get; init; }
80+
81+
public Color? ColorLeft { get; init; }
82+
83+
public Color? ColorRight { get; init; }
84+
85+
public Color? EnvColorLeft { get; init; }
86+
87+
public Color? EnvColorRight { get; init; }
88+
89+
public Color? EnvColorWhite { get; init; }
90+
91+
public Color? EnvColorLeftBoost { get; init; }
92+
93+
public Color? EnvColorRightBoost { get; init; }
94+
95+
public Color? EnvColorWhiteBoost { get; init; }
96+
97+
public Color? ObstacleColor { get; init; }
98+
}
99+
}
100+
101+
public class CustomSongData
102+
{
103+
public string[]? GenreTags { get; init; }
104+
105+
public Contributor[]? Contributors { get; init; }
106+
107+
public string? DefaultCharacteristic { get; init; }
108+
}
109+
110+
public class Contributor
111+
{
112+
public string? Role { get; init; }
113+
114+
public string? Name { get; init; }
115+
116+
public string? IconPath { get; init; }
117+
118+
[JsonIgnore]
119+
public Sprite? Icon { get; init; }
120+
}
121+
122+
// [Serializable]
123+
// public class DifficultyData
124+
// {
125+
// public string _beatmapCharacteristicName;
126+
// public BeatmapDifficulty _difficulty;
127+
// public string _difficultyLabel;
128+
// public RequirementData additionalDifficultyData;
129+
// public MapColor? _colorLeft;
130+
// public MapColor? _colorRight;
131+
// public MapColor? _envColorLeft;
132+
// public MapColor? _envColorRight;
133+
// public MapColor? _envColorWhite;
134+
// public MapColor? _envColorLeftBoost;
135+
// public MapColor? _envColorRightBoost;
136+
// public MapColor? _envColorWhiteBoost;
137+
// public MapColor? _obstacleColor;
138+
// public int? _beatmapColorSchemeIdx;
139+
// public int? _environmentNameIdx;
140+
//
141+
// //PinkCore Port
142+
// public bool? _oneSaber;
143+
// public bool? _showRotationNoteSpawnLines;
144+
// //Tags
145+
// public string[] _styleTags;
146+
// }
147+
}
148+
12149
[Serializable]
13150
public class SongData
14151
{

source/SongCore/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<!-- Overriding default csproj property values which would otherwise interfere with the manifest regeneration. -->
1616
<PropertyGroup>
1717
<Authors>Kyle1413</Authors>
18-
<Version>3.15.3</Version>
18+
<Version>3.16.0</Version>
1919
</PropertyGroup>
2020

2121
</Project>

source/SongCore/Installers/MenuInstaller.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public override void InstallBindings()
1313
Container.BindInterfacesAndSelfTo<ColorsUI>().AsSingle();
1414
Container.Bind<ProgressBar>().FromNewComponentOnNewGameObject().AsSingle();
1515
Container.BindInterfacesAndSelfTo<RequirementsUI>().AsSingle();
16+
Container.Bind<BeatmapLevelCache>().AsSingle();
17+
Container.BindInterfacesTo<BeatmapJsonCachePatches>().AsSingle();
18+
Container.BindInterfacesTo<BeatmapDataCachePatches>().AsSingle();
1619
Container.BindInterfacesTo<SongDataMenuPatches>().AsSingle();
1720
Container.BindInterfacesTo<InternalRestartPatch>().AsSingle();
1821
}

0 commit comments

Comments
 (0)