Skip to content

Commit 3af507c

Browse files
committed
BeatBlock 部分内容的向下兼容
1 parent 22684c8 commit 3af507c

15 files changed

Lines changed: 397 additions & 227 deletions

File tree

RhythmBase.BeatBlock/BeatBlock/Components/Level.SerializeMethods.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ private static List<IBaseEvent> DeserializeEvents(ref Utf8JsonReader reader, Met
8383
#if DEBUG
8484
int index = 0;
8585
#endif
86+
bool _14_useEffectCanvas = false;
87+
float _14_firstDecoTime = float.MaxValue;
88+
bool _17_useEaseSequence = false;
89+
float _17_firstEaseTime = float.MaxValue;
8690
while (reader.Read())
8791
{
8892
if (reader.TokenType == JsonTokenType.EndArray)
@@ -92,6 +96,34 @@ private static List<IBaseEvent> DeserializeEvents(ref Utf8JsonReader reader, Met
9296
try
9397
{
9498
e = baseEventConverter.Read(ref reader, typeof(IBaseEvent), options);
99+
if (options.Version <= 10 && e is Paddles && e["paddles"] is JsonElement { ValueKind: JsonValueKind.Number } p)
100+
{
101+
p.TryGetInt32(out int paddles);
102+
float paddleDistance = 360 / paddles;
103+
for (int i = 0; i < paddles; i++)
104+
{
105+
events.Add(new Paddles()
106+
{
107+
Angle = e.Angle,
108+
Time = e.Time,
109+
Order = e.Order,
110+
// Enabled = true,
111+
Duration = 0,
112+
Paddle = i + 1,
113+
NewAngle = i * paddleDistance,
114+
});
115+
}
116+
}
117+
else if (options.Version <= 14 && e is Decoration d && d.EffectCanvas)
118+
{
119+
_14_useEffectCanvas = true;
120+
_14_firstDecoTime = float.Min(_14_firstDecoTime, d.Time);
121+
}
122+
else if (options.Version <= 17 && e is IEaseSequenceEvent s)
123+
{
124+
_17_useEaseSequence = true;
125+
_17_firstEaseTime = float.Min(_17_firstEaseTime, s.Time);
126+
}
95127
index++;
96128
}
97129
catch (Exception)
@@ -120,6 +152,36 @@ private static List<IBaseEvent> DeserializeEvents(ref Utf8JsonReader reader, Met
120152
continue;
121153
events.Add(e);
122154
}
155+
if(_14_useEffectCanvas)
156+
{
157+
events.Add(new SetBoolean()
158+
{
159+
Time = _14_firstDecoTime,
160+
Order = -999,
161+
Enable = true,
162+
Var = "vfx.effectCanvas.oldColors",
163+
});
164+
}
165+
if(_17_useEaseSequence)
166+
{
167+
events.Add(new SetBoolean()
168+
{
169+
Time = _17_firstEaseTime - (/*level.properties.offset ??*/ 8),
170+
Order = -1,
171+
Enable = false,
172+
Var = "vfx.useVFXDistanceForVFXAngle",
173+
});
174+
events.Add(new Comment()
175+
{
176+
Angle = 10,
177+
Time = _17_firstEaseTime - (/*level.properties.offset ??*/ 8),
178+
Text = """
179+
This boolean was added for backwards compatibility when this level was upgraded from format 17 to format 18.
180+
Version 18: use VFX distance (from ease sequence) for VFX angle calculation
181+
If the new behavior is wanted, simply delete the boolean and this comment.
182+
"""
183+
});
184+
}
123185
return events;
124186
}
125187
public static void WriteManifestToStream(Stream stream, Level level, MetadataJsonSerializerOptions options)

RhythmBase.BeatBlock/BeatBlock/Converters/MemberConverter.cs

Lines changed: 96 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,87 @@ namespace RhythmBase.BeatBlock.Converters;
66

77
internal class BaseEventConverter : BackwardCompatibleMetadataJsonConverter
88
{
9+
private float _6_bpm;
10+
private float _12_playSongTime;
11+
public void Reset()
12+
{
13+
_6_bpm = 0;
14+
_12_playSongTime = 0;
15+
}
16+
public BaseEventConverter()
17+
{
18+
Reset();
19+
}
920
protected override void InitializeUpgraters()
1021
{
22+
Register<Hold>(2, (e) =>
23+
{
24+
e.Angle = e["angle1"].TryGetSingle(out var angle1) ? angle1 : 0;
25+
e["angle1"] = default;
26+
});
27+
Register<MineHold>(3, (e) =>
28+
{
29+
e.Angle = e["angle1"].TryGetSingle(out var angle1) ? angle1 : 0;
30+
e["angle1"] = default;
31+
});
32+
Register<Play>(6, (e) =>
33+
{
34+
if (e is not Play p) return;
35+
_6_bpm = p.BeatsPerMinute;
36+
});
37+
Register<Paddles>(6, (e) =>
38+
{
39+
if (e is not Paddles p) return;
40+
p.Duration /= 3600 / _6_bpm;
41+
});
42+
Register<Decoration>(9, (e) =>
43+
{
44+
if (e is not Decoration p) return;
45+
p.DrawOrder = p.Order;
46+
p.Order = null;
47+
});
48+
Register<Decoration>(11, (e) =>
49+
{
50+
if (e is not Decoration p) return;
51+
p.Order = p.Order is null or 0 ? -999 : p.Order;
52+
});
53+
Register<SetColor>(11, (e) =>
54+
{
55+
if (e is not SetColor p) return;
56+
p.Order = p.Order is null or 0 ? -999 : p.Order;
57+
});
58+
Register<Ease>(11, (e) =>
59+
{
60+
if (e is not Ease p) return;
61+
p.Order = p.Order is null or 0 ? -999 : p.Order;
62+
});
63+
Register<Play>(12, (e) =>
64+
{
65+
if (e is not Play p) return;
66+
_12_playSongTime = p.Time;
67+
});
68+
Register<SetBeatsPerMinute>(12, (e) =>
69+
{
70+
if (e is not SetBeatsPerMinute s) return;
71+
if(_12_playSongTime == 0) return;
72+
e.Time += _12_playSongTime;
73+
});
74+
//Register<PlaySound>(13, (e) =>
75+
//{
76+
// if(e is not PlaySound p) return;
77+
// if(false /*not in built-in sounds*/)
78+
// p.Sound += ".ogg";
79+
//});
80+
Register<Paddles>(15, (e) =>
81+
{
82+
if (e is not Paddles p) return;
83+
p.ForceStoreInLevel = true;
84+
});
85+
Register<Decoration>(16, (e) =>
86+
{
87+
if (e is not Decoration d) return;
88+
d.EffectCanvasRaw = d.EffectCanvas;
89+
});
1190
}
1291
public override bool CanConvert(Type typeToConvert)
1392
{
@@ -18,26 +97,28 @@ public override bool CanConvert(Type typeToConvert)
1897
JsonException.ThrowIfNotMatch(ref reader, JsonTokenType.StartObject);
1998

2099
Utf8JsonReader checkpoint = reader;
21-
while (reader.Read())
100+
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
22101
{
23-
if (reader.TokenType == JsonTokenType.EndObject)
102+
JsonException.ThrowIfNotMatch(ref reader, JsonTokenType.PropertyName);
103+
if (reader.ValueTextEquals("type"u8) && reader.Read())
24104
break;
25-
if (reader.TokenType == JsonTokenType.PropertyName)
26-
{
27-
if (reader.ValueTextEquals("type"u8))
28-
{
29-
reader.Read();
30-
break;
31-
}
32-
else
33-
reader.Skip();
34-
}
105+
else
106+
reader.Skip();
35107
}
36108
IBaseEvent e;
37-
if (!EnumConverter.TryParse(ref reader, out EventType typeEnum))
38-
e = ReadForwardEvent(ref checkpoint) ?? new ForwardEvent() { ActualType = reader.GetString() ?? "" };
39-
else
109+
// upgrate to the latest version
110+
111+
if (EnumConverter.TryParse(ref reader, out EventType typeEnum))
40112
e = EventConverterMap.GetConverter(typeEnum).ReadProperties(ref checkpoint, options);
113+
else
114+
{
115+
if (options.Version <= 1 && reader.ValueTextEquals("beat"u8))
116+
e = EventConverterMap.GetConverter(EventType.Block).ReadProperties(ref checkpoint, options);
117+
else if (options.Version <= 10 && reader.ValueTextEquals("width"u8))
118+
e = EventConverterMap.GetConverter(EventType.Paddles).ReadProperties(ref checkpoint, options);
119+
else
120+
e = ReadForwardEvent(ref checkpoint) ?? new ForwardEvent() { ActualType = reader.GetString() ?? "" };
121+
}
41122
JsonException.ThrowIfNotMatch(ref checkpoint, JsonTokenType.EndObject);
42123
reader = checkpoint;
43124
return e;

RhythmBase.BeatBlock/BeatBlock/Events/BaseEvent.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using RhythmBase.BeatBlock.Components;
2+
using RhythmBase.BeatBlock.Events;
3+
using RhythmBase.Global.Components.Easing;
24
using System.Text.Json;
35

46
namespace RhythmBase.BeatBlock.Events;
@@ -33,6 +35,11 @@ public abstract record class BaseEvent : IBaseEvent
3335
/// Gets the beat of the event.
3436
/// </summary>
3537
public TickTime TickTime { get; set; }
38+
/// <summary>
39+
///
40+
/// </summary>
41+
[JsonCondition($"$&.{nameof(ForceStoreInLevel)}")]
42+
public bool ForceStoreInLevel { get; set; }
3643
/// <summary>
3744
/// Gets or sets additional data associated with the specified property name.
3845
/// </summary>

RhythmBase.BeatBlock/BeatBlock/Events/Block.cs

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,34 @@ namespace RhythmBase.BeatBlock.Events;
1010
/// Basic note
1111
/// </remarks>
1212
[JsonObjectSerializable]
13-
public record class Block : BaseEvent, IChartEvent, IPureEvent
13+
public record class Block : BaseEvent, IChartEvent, IPureEvent, IEaseSequenceEvent
1414
{
15-
/// <inheritdoc/>
16-
public override EventType Type => EventType.Block;
17-
/// <summary>
18-
/// Angle to end up at
19-
/// </summary>
20-
public float? EndAngle { get; set; }
21-
/// <summary>
22-
/// Ease to use while rotating
23-
/// </summary>
24-
public EaseType? SpinEase { get; set; }
25-
/// <summary>
26-
/// Speed multiplier for approach
27-
/// </summary>
28-
public float? SpeedMult { get; set; }
29-
/// <summary>
30-
/// Make this note a Tap note
31-
/// </summary>
32-
public bool Tap { get; set; }
33-
/// <summary>
34-
/// Color channel 0 (default white)
35-
/// </summary>
36-
public ColorIndex? Color0 { get; set; }
37-
/// <summary>
38-
/// Color channel 1 (default black)
39-
/// </summary>
40-
public ColorIndex? Color1 { get; set; }
41-
/// <summary>
42-
/// Ease sequence to use, if any
43-
/// </summary>
44-
public string? EaseSequence { get; set; } = string.Empty;
15+
/// <inheritdoc/>
16+
public override EventType Type => EventType.Block;
17+
/// <summary>
18+
/// Angle to end up at
19+
/// </summary>
20+
public float? EndAngle { get; set; }
21+
/// <summary>
22+
/// Ease to use while rotating
23+
/// </summary>
24+
public EaseType? SpinEase { get; set; }
25+
/// <summary>
26+
/// Speed multiplier for approach
27+
/// </summary>
28+
public float? SpeedMult { get; set; }
29+
/// <summary>
30+
/// Make this note a Tap note
31+
/// </summary>
32+
public bool Tap { get; set; }
33+
/// <summary>
34+
/// Color channel 0 (default white)
35+
/// </summary>
36+
public ColorIndex? Color0 { get; set; }
37+
/// <summary>
38+
/// Color channel 1 (default black)
39+
/// </summary>
40+
public ColorIndex? Color1 { get; set; }
41+
/// <inheritdoc/>
42+
public string? EaseSequence { get; set; } = string.Empty;
4543
}

RhythmBase.BeatBlock/BeatBlock/Events/Bounce.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace RhythmBase.BeatBlock.Events;
1010
/// No description
1111
/// </remarks>
1212
[JsonObjectSerializable]
13-
public record class Bounce : BaseEvent, IChartEvent, IPureEvent
13+
public record class Bounce : BaseEvent, IChartEvent, IPureEvent, IEaseSequenceEvent
1414
{
1515
/// <inheritdoc/>
1616
public override EventType Type => EventType.Bounce;

RhythmBase.BeatBlock/BeatBlock/Events/ExtraTap.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace RhythmBase.BeatBlock.Events;
99
/// A tap independent of other notes
1010
/// </remarks>
1111
[JsonObjectSerializable]
12-
public record class ExtraTap : BaseEvent, IChartEvent, IPureEvent
12+
public record class ExtraTap : BaseEvent, IChartEvent, IPureEvent, IEaseSequenceEvent
1313
{
1414
/// <inheritdoc/>
1515
public override EventType Type => EventType.ExtraTap;

RhythmBase.BeatBlock/BeatBlock/Events/IBaseEvent.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,18 @@ public interface IBaseEvent : IEvent<EventType, TickTime>
3434
/// <summary>
3535
/// Represents a chart event in a BeatBlock level.
3636
/// </summary>
37+
/// <remarks>
38+
/// The event will be stored in the chart rather than the level.
39+
/// </remarks>
3740
public interface IChartEvent : IBaseEvent
3841
{
3942
}
4043
/// <summary>
4144
/// Represents a pure event in a BeatBlock level.
4245
/// </summary>
46+
/// <remarks>
47+
/// The event will be allowed in the <b>no visual effects</b> mode.
48+
/// </remarks>
4349
public interface IPureEvent : IBaseEvent
4450
{
4551
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace RhythmBase.BeatBlock.Events
2+
{
3+
/// <summary>
4+
/// Interface for events that can have an ease sequence
5+
/// </summary>
6+
public interface IEaseSequenceEvent : IBaseEvent
7+
{
8+
/// <summary>
9+
/// Ease sequence to use, if any
10+
/// </summary>
11+
string? EaseSequence { get; set; }
12+
}
13+
}

RhythmBase.BeatBlock/BeatBlock/Events/Inverse.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace RhythmBase.BeatBlock.Events;
99
/// Similar to a basic note, but must be hit with the back of the paddle
1010
/// </remarks>
1111
[JsonObjectSerializable]
12-
public record class Inverse : BaseEvent, IChartEvent, IPureEvent
12+
public record class Inverse : BaseEvent, IChartEvent, IPureEvent, IEaseSequenceEvent
1313
{
1414
/// <inheritdoc/>
1515
public override EventType Type => EventType.Inverse;

RhythmBase.BeatBlock/BeatBlock/Events/Mine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace RhythmBase.BeatBlock.Events;
99
/// Similar to a basic note, but must NOT be hit.
1010
/// </remarks>
1111
[JsonObjectSerializable]
12-
public record class Mine : BaseEvent, IChartEvent, IPureEvent
12+
public record class Mine : BaseEvent, IChartEvent, IPureEvent, IEaseSequenceEvent
1313
{
1414
/// <inheritdoc/>
1515
public override EventType Type => EventType.Mine;

0 commit comments

Comments
 (0)