public void SerializeChart(Chart chart, Stream outStream) { var writer = new BinaryWriter(outStream); writer.WriteUInt32BE(MAGIC); writer.WriteUInt8(VERSION); writer.WriteUInt16BE((ushort)chart.StreamCount); Logger.Log($"chart.binwrite stream count { chart.StreamCount }"); var effectTable = new ChartEffectTable(); for (int s = 0; s < chart.StreamCount; s++) { var stream = chart[s]; foreach (var obj in stream) { if (obj is IHasEffectDef e) { var effect = e.Effect; if (effect == null || effect.Type == EffectType.None) { continue; } effectTable.Add(effect); } } } writer.WriteUInt16BE((ushort)effectTable.Count); Logger.Log($"chart.binwrite effect count { effectTable.Count }"); for (int i = 0; i < effectTable.Count; i++) { var effect = effectTable[i]; Logger.Log($"chart.binwrite effect { effect.Type }"); SerializeEffectDef(effect, writer); } int controlPointCount = chart.ControlPoints.Count; writer.WriteUInt16BE((ushort)controlPointCount); Logger.Log($"chart.binwrite control point count { controlPointCount }"); for (int i = 0; i < controlPointCount; i++) { var cp = chart.ControlPoints[i]; Logger.Log($"chart.binwrite control point { cp.Position } { cp.BeatsPerMinute } { cp.BeatCount }/{ cp.BeatKind } { cp.SpeedMultiplier }"); writer.WriteDoubleBE((double)cp.Position); writer.WriteDoubleBE(cp.BeatsPerMinute); writer.WriteUInt8((byte)cp.BeatCount); writer.WriteUInt8((byte)cp.BeatKind); writer.WriteDoubleBE(cp.SpeedMultiplier); } for (int s = 0; s < chart.StreamCount; s++) { var stream = chart[s]; int count = stream.Count; writer.WriteUInt32BE((uint)count); for (int i = 0; i < count; i++) { var obj = stream[i]; var serializer = GetSerializerForType(obj); byte objId = (byte)(serializer?.ID ?? 0); writer.WriteUInt8(objId); if (obj.IsInstant) { writer.WriteUInt8(0); } else { writer.WriteUInt8(0x01); } writer.WriteDoubleBE((double)obj.Position); if (!obj.IsInstant) { writer.WriteDoubleBE((double)obj.Duration); } serializer?.SerializeSubclass(obj, writer, effectTable); } } }
public abstract ChartObject DeserializeSubclass(tick_t pos, tick_t dur, BinaryReader reader, ChartEffectTable effects);
public Chart DeserializeChart(ChartInfo chartInfo, Stream inStream) { var reader = new BinaryReader(inStream, Encoding.UTF8); uint magicCheck = reader.ReadUInt32BE(); if (magicCheck != MAGIC) { throw new ChartFormatException($"Invalid input stream given."); } uint versionCheck = reader.ReadUInt8(); if (versionCheck > VERSION) { throw new ChartFormatException($"Input stream cannot be read by this serializer: the version is too high."); } ushort streamCount = reader.ReadUInt16BE(); var chart = new Chart(streamCount) { Info = chartInfo }; chart.Offset = chartInfo.ChartOffset; int effectCount = reader.ReadUInt16BE(); var effectTable = new ChartEffectTable(); for (int i = 0; i < effectCount; i++) { var effect = DeserializeEffectDef(reader); effectTable.Add(effect); } ushort controlPointCount = reader.ReadUInt16BE(); for (int i = 0; i < controlPointCount; i++) { tick_t position = reader.ReadDoubleBE(); double bpm = reader.ReadDoubleBE(); int beatCount = reader.ReadUInt8(); int beatKind = reader.ReadUInt8(); double mult = reader.ReadDoubleBE(); var cp = chart.ControlPoints.GetOrCreate(position, false); cp.BeatsPerMinute = bpm; cp.BeatCount = beatCount; cp.BeatKind = beatKind; cp.SpeedMultiplier = mult; } for (int s = 0; s < streamCount; s++) { var stream = chart[s]; uint ucount = reader.ReadUInt32BE(); if (ucount > int.MaxValue) { throw new ChartFormatException($"Too many objects declared in stream { s }."); } int count = (int)ucount; for (int i = 0; i < count; i++) { byte objId = reader.ReadUInt8(); var serializer = GetSerializerByID(objId); byte flags = reader.ReadUInt8(); bool hasDuration = (flags & 0x01) != 0; tick_t position = reader.ReadDoubleBE(); tick_t duration = hasDuration ? reader.ReadDoubleBE() : 0; ChartObject obj; if (serializer != null) { obj = serializer.DeserializeSubclass(position, duration, reader, effectTable); } else { obj = new ChartObject() { Position = position, Duration = duration, } }; stream.Add(obj); } } return(chart); }
public abstract void SerializeSubclass(ChartObject obj, BinaryWriter writer, ChartEffectTable effects);