diff --git a/src/library/Syroot.Worms.Armageddon/Scheme.Enums.cs b/src/library/Syroot.Worms.Armageddon/Scheme.Enums.cs
index 01cefa2..4289b18 100644
--- a/src/library/Syroot.Worms.Armageddon/Scheme.Enums.cs
+++ b/src/library/Syroot.Worms.Armageddon/Scheme.Enums.cs
@@ -72,6 +72,21 @@ namespace Syroot.Worms.Armageddon
Version3 = 3
}
+ ///
+ /// Represents extension methods for instances.
+ ///
+ public static class SchemeVersionExtensions
+ {
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Returns how many instances are stored in the .
+ ///
+ /// The .
+ /// The number of weapons stored for this version.
+ public static int GetWeaponCount(this SchemeVersion version) => version == SchemeVersion.Version1 ? 45 : 64;
+ }
+
///
/// Represents the gravity simulation used in a game (as originating from RubberWorm).
///
diff --git a/src/library/Syroot.Worms.Armageddon/Scheme.ExtendedOptions.cs b/src/library/Syroot.Worms.Armageddon/Scheme.ExtendedOptions.cs
index 0eb324b..d49a526 100644
--- a/src/library/Syroot.Worms.Armageddon/Scheme.ExtendedOptions.cs
+++ b/src/library/Syroot.Worms.Armageddon/Scheme.ExtendedOptions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Syroot.Worms.Armageddon
@@ -1102,7 +1103,14 @@ namespace Syroot.Worms.Armageddon
return hash.ToHashCode();
}
- private float FixedPointToSingle(int value) => value / 65536f;
+ ///
+ /// Returns this instance as raw data.
+ ///
+ /// A storing the raw data of the options.
+ internal unsafe Span AsSpan()
+ => new Span(Unsafe.AsPointer(ref this), Unsafe.SizeOf());
+
+ private static float FixedPointToSingle(int value) => value / 65536f;
private static byte NullBoolToTriState(bool? value) => value switch
{
@@ -1117,7 +1125,7 @@ namespace Syroot.Worms.Armageddon
_ => value.Value
};
- private int SingleToFixedPoint(float value) => (int)(value * 65536);
+ private static int SingleToFixedPoint(float value) => (int)(value * 65536);
private static bool? TriStateToNullBool(byte value) => value switch
{
diff --git a/src/library/Syroot.Worms.Armageddon/Scheme.cs b/src/library/Syroot.Worms.Armageddon/Scheme.cs
index 6bee604..a4be57f 100644
--- a/src/library/Syroot.Worms.Armageddon/Scheme.cs
+++ b/src/library/Syroot.Worms.Armageddon/Scheme.cs
@@ -3,7 +3,6 @@ using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Runtime.CompilerServices;
using System.Text;
using Syroot.BinaryData;
using Syroot.Worms.Core;
@@ -1067,7 +1066,7 @@ namespace Syroot.Worms.Armageddon
// Read the weapons.
Weapons = new WeaponList();
- reader.ReadStructs(Weapons.AsSpan(GetWeaponCount(Version)));
+ reader.ReadStructs(Weapons.AsSpan(Version.GetWeaponCount()));
// Read available extended settings or deserialize them from RubberWorm settings encoded in probabilities.
switch (Version)
@@ -1201,13 +1200,13 @@ namespace Syroot.Worms.Armageddon
SaveRubberWorm();
// Write the weapons.
- writer.WriteStructs(Weapons.AsSpan(GetWeaponCount(version)));
+ writer.WriteStructs(Weapons.AsSpan(version.GetWeaponCount()));
// Clear RubberWorm probabilities again or write available extended settings.
switch (version)
{
case SchemeVersion.Version2: ClearRubberWorm(); break;
- case SchemeVersion.Version3: SaveExtendedOptions(writer); break;
+ case SchemeVersion.Version3: SaveExtendedOptions(writer, Attachment.Length == 0); break;
}
// Write any trailing bytes (either unknown extended scheme options or unknown WWP trash).
@@ -1216,8 +1215,6 @@ namespace Syroot.Worms.Armageddon
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
- private static int GetWeaponCount(SchemeVersion version) => version == SchemeVersion.Version1 ? 45 : 64;
-
private void ClearRubberWorm()
{
// Reset all super weapon probabilities to remove any settings made by RubberWorm.
@@ -1229,23 +1226,10 @@ namespace Syroot.Worms.Armageddon
private unsafe void LoadExtendedOptions(BinaryStream reader)
{
- if (reader.EndOfStream)
- {
- ClearExtendedOptions();
- }
- else
- {
- Span bytes = new Span(
- Unsafe.AsPointer(ref _extended), Unsafe.SizeOf());
-#if NETSTANDARD2_0
- // Cannot prevent copy in .NET Standard 2.0.
- byte[] buffer = new byte[(int)Math.Min(bytes.Length, reader.Length - reader.Position)];
- reader.Read(buffer, 0, buffer.Length);
- buffer.AsSpan().CopyTo(bytes);
-#else
- reader.Read(bytes);
-#endif
- }
+ // Create a copy of default options overwritten by available extended data.
+ Span bytes = _extended.AsSpan();
+ ExtendedOptions.Default.AsSpan().CopyTo(bytes);
+ reader.Read(bytes);
}
private void LoadRubberWorm()
@@ -1362,16 +1346,19 @@ namespace Syroot.Worms.Armageddon
ClearRubberWorm();
}
- private unsafe void SaveExtendedOptions(BinaryStream writer)
+ private unsafe void SaveExtendedOptions(BinaryStream writer, bool trim)
{
- ReadOnlySpan bytes = new ReadOnlySpan(
- Unsafe.AsPointer(ref _extended), Unsafe.SizeOf());
-#if NETSTANDARD2_0
- // Cannot prevent copy in .NET Standard 2.0.
- writer.Write(bytes.ToArray());
-#else
- writer.Write(bytes);
-#endif
+ ReadOnlySpan bytes = _extended.AsSpan();
+
+ // Trim away default bytes.
+ int length = bytes.Length;
+ if (trim)
+ {
+ ReadOnlySpan defaultBytes = ExtendedOptions.Default.AsSpan();
+ for (; length > 0 && bytes[length - 1] == defaultBytes[length - 1]; length--) ;
+ }
+
+ writer.Write(bytes.Slice(0, length));
}
private void SaveRubberWorm()
diff --git a/src/library/Syroot.Worms.Armageddon/Syroot.Worms.Armageddon.csproj b/src/library/Syroot.Worms.Armageddon/Syroot.Worms.Armageddon.csproj
index 0d718ce..5a53fd3 100644
--- a/src/library/Syroot.Worms.Armageddon/Syroot.Worms.Armageddon.csproj
+++ b/src/library/Syroot.Worms.Armageddon/Syroot.Worms.Armageddon.csproj
@@ -7,7 +7,7 @@
.NET library for loading and modifying files of Team17's Worms Armageddon.
Overhaul implementation and documentation. Implement W:A V3 scheme format.
$(PackageTags);worms armageddon
- 4.0.0
+ 4.0.1
diff --git a/src/library/Syroot.Worms/IO/StreamExtensions.cs b/src/library/Syroot.Worms/IO/StreamExtensions.cs
index 7fc2f46..5f535ea 100644
--- a/src/library/Syroot.Worms/IO/StreamExtensions.cs
+++ b/src/library/Syroot.Worms/IO/StreamExtensions.cs
@@ -84,8 +84,8 @@ namespace Syroot.Worms.IO
/// The instance to write into the current stream.
public static void Save(this Stream stream, T value) where T : ISaveable => value.Save(stream);
- // ---- Backports ----
#if NETSTANDARD2_0
+ // ---- Backports ----
///
/// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the
diff --git a/src/test/Syroot.Worms.Armageddon.Test/SchemeTests.cs b/src/test/Syroot.Worms.Armageddon.Test/SchemeTests.cs
index 7932d6b..3952f4a 100644
--- a/src/test/Syroot.Worms.Armageddon.Test/SchemeTests.cs
+++ b/src/test/Syroot.Worms.Armageddon.Test/SchemeTests.cs
@@ -19,13 +19,13 @@ namespace Syroot.Worms.Test.Armageddon
/// Tests all files found in the test directory.
///
[TestMethod]
- public void TestFiles() => Tools.TestFiles("*.wsc");
+ public void TestSchemes() => Tools.TestFiles("*.wsc");
///
/// Tests all schemes from a Worms Scheme Database CSV dump (ask owner Byte for updated dumps).
///
[TestMethod]
- public void TestWsdb()
+ public void TestSchemesWsdb()
{
// Reuse buffer for all schemes, including the SCHM header stripped in the dump.
byte[] buffer = new byte[407];