feat: allow lists of replacement text

This commit is contained in:
Anna 2024-06-21 11:27:36 -04:00
parent feb08ab877
commit c63514d9ad
Signed by: anna
GPG Key ID: D0943384CD9F87D1
7 changed files with 83 additions and 11 deletions

View File

@ -5,7 +5,7 @@ using YamlDotNet.Serialization;
namespace TimePasses.Model; namespace TimePasses.Model;
public interface IWhen { public interface IWhen {
string Text { get; } ReplacementText Text { get; }
bool Slowly { get; } bool Slowly { get; }
bool IsValid(Plugin plugin); bool IsValid(Plugin plugin);

View File

@ -1,9 +1,11 @@
using YamlDotNet.Serialization;
namespace TimePasses.Model; namespace TimePasses.Model;
[Serializable] [Serializable]
internal class Replacement { internal class Replacement {
public uint Id { get; init; } public uint Id { get; init; }
public string? Text { get; init; } public ReplacementText? Text { get; init; }
public bool Slowly { get; init; } public bool Slowly { get; init; }
public IWhen[] When { get; init; } = []; public IWhen[] When { get; init; } = [];
} }

66
Model/ReplacementText.cs Normal file
View File

@ -0,0 +1,66 @@
using System.Collections;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
namespace TimePasses.Model;
[Serializable]
public class ReplacementText : IReadOnlyList<string> {
private IReadOnlyList<string> List { get; }
internal ReplacementText(IReadOnlyList<string> list) {
this.List = list;
}
public string this[int index] => this.List[index];
public int Count => this.List.Count;
public IEnumerator<string> GetEnumerator() {
return this.List.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return this.List.GetEnumerator();
}
}
internal class ReplacementTextConverter : IYamlTypeConverter {
internal static readonly ReplacementTextConverter Instance = new();
public bool Accepts(Type type) {
return type == typeof(ReplacementText);
}
public object? ReadYaml(IParser parser, Type type) {
var list = new List<string>();
if (parser.Current is Scalar) {
AddItem();
} else if (parser.Current is SequenceStart) {
parser.Consume<SequenceStart>();
while (parser.Current is not SequenceEnd) {
AddItem();
}
parser.Consume<SequenceEnd>();
} else {
throw new YamlException("expected string or list of strings");
}
return new ReplacementText(list);
void AddItem() {
var scalar = parser.Consume<Scalar>();
if (scalar.IsKey) {
throw new YamlException("invalid key found: expected string or list of strings");
}
list.Add(scalar.Value);
}
}
public void WriteYaml(IEmitter emitter, object? value, Type type) {
throw new NotImplementedException();
}
}

View File

@ -8,7 +8,7 @@ namespace TimePasses.Model;
public class WhenLevel : IWhen { public class WhenLevel : IWhen {
public uint Level { get; init; } public uint Level { get; init; }
public int CompareResult { get; init; } public int CompareResult { get; init; }
public string Text { get; init; } public ReplacementText Text { get; init; }
public bool Slowly { get; init; } public bool Slowly { get; init; }
public bool IsValid(Plugin plugin) { public bool IsValid(Plugin plugin) {
@ -34,7 +34,7 @@ public class WhenLevelConverter : IYamlTypeConverter {
public object ReadYaml(IParser parser, Type type) { public object ReadYaml(IParser parser, Type type) {
parser.Consume<MappingStart>(); parser.Consume<MappingStart>();
string? text = null; ReplacementText? text = null;
int? comparerResult = null; int? comparerResult = null;
uint? level = null; uint? level = null;
var slowly = false; var slowly = false;
@ -44,6 +44,11 @@ public class WhenLevelConverter : IYamlTypeConverter {
throw new YamlException("expected key"); throw new YamlException("expected key");
} }
if (key.Value == "text") {
text = (ReplacementText?) ReplacementTextConverter.Instance.ReadYaml(parser, type);
continue;
}
var value = parser.Consume<Scalar>(); var value = parser.Consume<Scalar>();
switch (key.Value) { switch (key.Value) {
@ -59,10 +64,6 @@ public class WhenLevelConverter : IYamlTypeConverter {
ParseOperation(-1); ParseOperation(-1);
break; break;
} }
case "text": {
text = value.Value;
break;
}
case "slowly": { case "slowly": {
if (!bool.TryParse(value.Value, out slowly)) { if (!bool.TryParse(value.Value, out slowly)) {
throw new YamlException("invalid whenlevel: slowly was not a boolean"); throw new YamlException("invalid whenlevel: slowly was not a boolean");

View File

@ -6,7 +6,7 @@ namespace TimePasses.Model;
public class WhenQuest : IWhen { public class WhenQuest : IWhen {
public uint Id { get; init; } public uint Id { get; init; }
public QuestStatus Status { get; init; } public QuestStatus Status { get; init; }
public string Text { get; init; } public ReplacementText Text { get; init; }
public bool Slowly { get; init; } public bool Slowly { get; init; }
public unsafe bool IsValid(Plugin plugin) { public unsafe bool IsValid(Plugin plugin) {

View File

@ -33,6 +33,7 @@ public sealed class Plugin : IDalamudPlugin {
private static IDeserializer Deserializer { get; } = new DeserializerBuilder() private static IDeserializer Deserializer { get; } = new DeserializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance) .WithNamingConvention(UnderscoredNamingConvention.Instance)
.WithTypeConverter(new WhenLevelConverter()) .WithTypeConverter(new WhenLevelConverter())
.WithTypeConverter(ReplacementTextConverter.Instance)
.WithNodeDeserializer(new WhenNodeDeserialiser()) .WithNodeDeserializer(new WhenNodeDeserialiser())
.IgnoreUnmatchedProperties() .IgnoreUnmatchedProperties()
.Build(); .Build();
@ -111,11 +112,13 @@ public sealed class Plugin : IDalamudPlugin {
var when = rep.When.FirstOrDefault(when => when.IsValid(this)); var when = rep.When.FirstOrDefault(when => when.IsValid(this));
if (when != null) { if (when != null) {
return this.GetOrCreateReplacementPointer(when.Text, when.Slowly); var idx = Random.Shared.Next(when.Text.Count);
return this.GetOrCreateReplacementPointer(when.Text[idx], when.Slowly);
} }
if (rep.Text != null) { if (rep.Text != null) {
return this.GetOrCreateReplacementPointer(rep.Text, rep.Slowly); var idx = Random.Shared.Next(rep.Text.Count);
return this.GetOrCreateReplacementPointer(rep.Text[idx], rep.Slowly);
} }
return null; return null;