Implement a better way to disable tracks while keeping them in JSON

This commit is contained in:
ivan tkachenko 2026-01-23 15:32:33 +02:00
parent f20a500992
commit 98244dd3f1
3 changed files with 33 additions and 13 deletions

View File

@ -54,6 +54,7 @@ namespace MuzikaGromche
{ {
var obj = new Dictionary<string, object?> var obj = new Dictionary<string, object?>
{ {
["Enabled"] = selectableTrack.Enabled,
["Name"] = audioTrack.Name, // may be different from selectableTrack.Name, if selectable track is a group ["Name"] = audioTrack.Name, // may be different from selectableTrack.Name, if selectable track is a group
["Artist"] = selectableTrack.Artist, ["Artist"] = selectableTrack.Artist,
["Song"] = selectableTrack.Song, ["Song"] = selectableTrack.Song,

View File

@ -364,9 +364,9 @@ public static class Library
FlickerLightsTimeSeries = [-8, 31], FlickerLightsTimeSeries = [-8, 31],
Lyrics = [], Lyrics = [],
}, },
#if DEBUG // No one knows it, and it's a bit out of place with a long 52 seconds intro
new SelectableAudioTrack new SelectableAudioTrack
{ {
Enabled = false, // No one knows it, and it's a bit out of place with a long 52 seconds intro
Name = "Yalgaar", Name = "Yalgaar",
Artist = "Ajey Nagar and Wily Frenzy", Artist = "Ajey Nagar and Wily Frenzy",
Song = "Yalgaar", Song = "Yalgaar",
@ -385,7 +385,6 @@ public static class Library
FlickerLightsTimeSeries = [-5], FlickerLightsTimeSeries = [-5],
Lyrics = [], Lyrics = [],
}, },
#endif
new SelectableAudioTrack new SelectableAudioTrack
{ {
Name = "Chereshnya", Name = "Chereshnya",

View File

@ -53,6 +53,7 @@ namespace MuzikaGromche
{ {
tracksEnumerable = tracksEnumerable.Where(track => !track.IsExplicit); tracksEnumerable = tracksEnumerable.Where(track => !track.IsExplicit);
} }
tracksEnumerable = tracksEnumerable.Where(track => track.Enabled);
var tracks = tracksEnumerable.ToArray(); var tracks = tracksEnumerable.ToArray();
return (tracks, season); return (tracks, season);
} }
@ -61,7 +62,7 @@ namespace MuzikaGromche
{ {
var seed = GetCurrentSeed(); var seed = GetCurrentSeed();
var (tracks, season) = GetTracksAndSeason(); var (tracks, season) = GetTracksAndSeason();
int[] weights = tracks.Select(track => track.Weight.Value).ToArray(); int[] weights = tracks.Select(track => track.Weight!.Value).ToArray();
var rwi = new RandomWeightedIndex(weights); var rwi = new RandomWeightedIndex(weights);
var trackId = rwi.GetRandomWeightedIndex(seed); var trackId = rwi.GetRandomWeightedIndex(seed);
var track = tracks[trackId]; var track = tracks[trackId];
@ -86,8 +87,8 @@ namespace MuzikaGromche
// Similar to RandomWeightedIndex: // Similar to RandomWeightedIndex:
// If everything is set to zero, everything is equally possible // If everything is set to zero, everything is equally possible
var allWeightsAreZero = tracks.All(t => t.Weight.Value == 0); var allWeightsAreZero = tracks.All(t => t.Weight!.Value == 0);
bool WeightIsCompatible(ISelectableTrack t) => allWeightsAreZero || t.Weight.Value > 0; bool WeightIsCompatible(ISelectableTrack t) => allWeightsAreZero || t.Weight!.Value > 0;
var compatibleSelectableTracks = tracks var compatibleSelectableTracks = tracks
.Where(track => WeightIsCompatible(track) && track.GetTracks().Any(TimerIsCompatible)) .Where(track => WeightIsCompatible(track) && track.GetTracks().Any(TimerIsCompatible))
@ -100,7 +101,7 @@ namespace MuzikaGromche
} }
// Select track group where at least one track member is compatible // Select track group where at least one track member is compatible
int[] weights = compatibleSelectableTracks.Select(track => track.Weight.Value).ToArray(); int[] weights = compatibleSelectableTracks.Select(track => track.Weight!.Value).ToArray();
var rwi = new RandomWeightedIndex(weights); var rwi = new RandomWeightedIndex(weights);
var trackId = rwi.GetRandomWeightedIndex(seed); var trackId = rwi.GetRandomWeightedIndex(seed);
var selectableTrack = compatibleSelectableTracks[trackId]; var selectableTrack = compatibleSelectableTracks[trackId];
@ -324,6 +325,9 @@ namespace MuzikaGromche
// can be selected using weighted random from a list of selectable tracks. // can be selected using weighted random from a list of selectable tracks.
public interface ISelectableTrack : ISeasonalContent public interface ISelectableTrack : ISeasonalContent
{ {
// Provide means to disable the track and hide it from user-facing config, while keeping it around in code and still exporting to JSON.
public bool Enabled { get; init; }
// Name of the track, as shown in config entry UI; also used for default file names. // Name of the track, as shown in config entry UI; also used for default file names.
public string Name { get; init; } public string Name { get; init; }
@ -339,7 +343,7 @@ namespace MuzikaGromche
public bool IsExplicit { get; init; } public bool IsExplicit { get; init; }
// How often this track should be chosen, relative to the sum of weights of all tracks. // How often this track should be chosen, relative to the sum of weights of all tracks.
internal ConfigEntry<int> Weight { get; set; } internal ConfigEntry<int>? Weight { get; set; }
internal IAudioTrack[] GetTracks(); internal IAudioTrack[] GetTracks();
@ -575,13 +579,14 @@ namespace MuzikaGromche
// Standalone, top-level, selectable audio track // Standalone, top-level, selectable audio track
public class SelectableAudioTrack : CoreAudioTrack, ISelectableTrack public class SelectableAudioTrack : CoreAudioTrack, ISelectableTrack
{ {
public bool Enabled { get; init; } = true;
public /* required */ string Artist { get; init; } = ""; public /* required */ string Artist { get; init; } = "";
public /* required */ string Song { get; init; } = ""; public /* required */ string Song { get; init; } = "";
public /* required */ Language Language { get; init; } public /* required */ Language Language { get; init; }
public bool IsExplicit { get; init; } = false; public bool IsExplicit { get; init; } = false;
public Season? Season { get; init; } = null; public Season? Season { get; init; } = null;
ConfigEntry<int> ISelectableTrack.Weight { get; set; } = null!; ConfigEntry<int>? ISelectableTrack.Weight { get; set; } = null;
IAudioTrack[] ISelectableTrack.GetTracks() => [this]; IAudioTrack[] ISelectableTrack.GetTracks() => [this];
@ -595,6 +600,7 @@ namespace MuzikaGromche
public class SelectableTracksGroup : ISelectableTrack public class SelectableTracksGroup : ISelectableTrack
{ {
public bool Enabled { get; init; } = true;
public /* required */ string Name { get; init; } = ""; public /* required */ string Name { get; init; } = "";
public /* required */ string Artist { get; init; } = ""; public /* required */ string Artist { get; init; } = "";
@ -602,7 +608,7 @@ namespace MuzikaGromche
public /* required */ Language Language { get; init; } public /* required */ Language Language { get; init; }
public bool IsExplicit { get; init; } = false; public bool IsExplicit { get; init; } = false;
public Season? Season { get; init; } = null; public Season? Season { get; init; } = null;
ConfigEntry<int> ISelectableTrack.Weight { get; set; } = null!; ConfigEntry<int>? ISelectableTrack.Weight { get; set; } = null;
public /* required */ IAudioTrack[] Tracks = []; public /* required */ IAudioTrack[] Tracks = [];
@ -1614,6 +1620,11 @@ namespace MuzikaGromche
foreach (var track in Plugin.Tracks) foreach (var track in Plugin.Tracks)
{ {
if (!track.Enabled)
{
// hide disabled tracks from user-facing config
continue;
}
var language = track.Language; var language = track.Language;
string section = $"Tracks.{language.Short}"; string section = $"Tracks.{language.Short}";
@ -1627,11 +1638,14 @@ namespace MuzikaGromche
var button = new GenericButtonConfigItem(section, buttonOptionName, buttonDescription, buttonText, () => var button = new GenericButtonConfigItem(section, buttonOptionName, buttonDescription, buttonText, () =>
{ {
var tracks = Plugin.Tracks.Where(t => t.Language.Equals(language)).ToList(); var tracks = Plugin.Tracks.Where(t => t.Language.Equals(language)).ToList();
var isOff = tracks.All(t => t.Weight.Value == 0); var isOff = tracks.All(t => t.Weight == null || t.Weight.Value == 0);
var newWeight = isOff ? 50 : 0; var newWeight = isOff ? 50 : 0;
foreach (var t in tracks) foreach (var t in tracks)
{ {
t.Weight.Value = newWeight; if (t.Weight != null)
{
t.Weight.Value = newWeight;
}
} }
}); });
LethalConfigManager.AddConfigItem(button); LethalConfigManager.AddConfigItem(button);
@ -2099,7 +2113,10 @@ namespace MuzikaGromche
ChooseTrackDeferred(); ChooseTrackDeferred();
foreach (var track in Plugin.Tracks) foreach (var track in Plugin.Tracks)
{ {
track.Weight.SettingChanged += ChooseTrackDeferredDelegate; if (track.Weight is { } weight)
{
weight.SettingChanged += ChooseTrackDeferredDelegate;
}
} }
Config.SkipExplicitTracks.SettingChanged += ChooseTrackDeferredDelegate; Config.SkipExplicitTracks.SettingChanged += ChooseTrackDeferredDelegate;
base.OnNetworkSpawn(); base.OnNetworkSpawn();
@ -2109,7 +2126,10 @@ namespace MuzikaGromche
{ {
foreach (var track in Plugin.Tracks) foreach (var track in Plugin.Tracks)
{ {
track.Weight.SettingChanged -= ChooseTrackDeferredDelegate; if (track.Weight is { } weight)
{
weight.SettingChanged -= ChooseTrackDeferredDelegate;
}
} }
Config.SkipExplicitTracks.SettingChanged -= ChooseTrackDeferredDelegate; Config.SkipExplicitTracks.SettingChanged -= ChooseTrackDeferredDelegate;
base.OnNetworkDespawn(); base.OnNetworkDespawn();