mirror of
https://gitlab.com/Syroot/Worms.git
synced 2025-03-03 17:05:21 +03:00
Syroot.Worms.Armageddon 4.0.1: Optimize WA v3 schemes to store only non-default extended options.
- Adds SchemeVersionExtensions.GetWeaponCount(), returning how many weapons are stored by the corresponding SchemeVersion. - Adds ExtendedOptions.AsSpan() to return the unmanaged representation of the extended settings. - Optimize usage of .NET Standard 2.0 Span backports.
This commit is contained in:
parent
08703b6c12
commit
5b69f82a35
@ -72,6 +72,21 @@ namespace Syroot.Worms.Armageddon
|
||||
Version3 = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents extension methods for <see cref="SchemeVersion"/> instances.
|
||||
/// </summary>
|
||||
public static class SchemeVersionExtensions
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Returns how many <see cref="SchemeWeapon"/> instances are stored in the <paramref name="version"/>.
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="SchemeVersion"/>.</param>
|
||||
/// <returns>The number of weapons stored for this version.</returns>
|
||||
public static int GetWeaponCount(this SchemeVersion version) => version == SchemeVersion.Version1 ? 45 : 64;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the gravity simulation used in a game (as originating from RubberWorm).
|
||||
/// </summary>
|
||||
|
@ -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;
|
||||
/// <summary>
|
||||
/// Returns this instance as raw data.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Span{Byte}"/> storing the raw data of the options.</returns>
|
||||
internal unsafe Span<byte> AsSpan()
|
||||
=> new Span<byte>(Unsafe.AsPointer(ref this), Unsafe.SizeOf<ExtendedOptions>());
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -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<SchemeWeapon>(Weapons.AsSpan(GetWeaponCount(version)));
|
||||
writer.WriteStructs<SchemeWeapon>(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<byte> bytes = new Span<byte>(
|
||||
Unsafe.AsPointer(ref _extended), Unsafe.SizeOf<ExtendedOptions>());
|
||||
#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<byte> 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<byte> bytes = new ReadOnlySpan<byte>(
|
||||
Unsafe.AsPointer(ref _extended), Unsafe.SizeOf<ExtendedOptions>());
|
||||
#if NETSTANDARD2_0
|
||||
// Cannot prevent copy in .NET Standard 2.0.
|
||||
writer.Write(bytes.ToArray());
|
||||
#else
|
||||
writer.Write(bytes);
|
||||
#endif
|
||||
ReadOnlySpan<byte> bytes = _extended.AsSpan();
|
||||
|
||||
// Trim away default bytes.
|
||||
int length = bytes.Length;
|
||||
if (trim)
|
||||
{
|
||||
ReadOnlySpan<byte> defaultBytes = ExtendedOptions.Default.AsSpan();
|
||||
for (; length > 0 && bytes[length - 1] == defaultBytes[length - 1]; length--) ;
|
||||
}
|
||||
|
||||
writer.Write(bytes.Slice(0, length));
|
||||
}
|
||||
|
||||
private void SaveRubberWorm()
|
||||
|
@ -7,7 +7,7 @@
|
||||
<Description>.NET library for loading and modifying files of Team17's Worms Armageddon.</Description>
|
||||
<PackageReleaseNotes>Overhaul implementation and documentation. Implement W:A V3 scheme format.</PackageReleaseNotes>
|
||||
<PackageTags>$(PackageTags);worms armageddon</PackageTags>
|
||||
<Version>4.0.0</Version>
|
||||
<Version>4.0.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- References -->
|
||||
|
@ -84,8 +84,8 @@ namespace Syroot.Worms.IO
|
||||
/// <param name="value">The instance to write into the current stream.</param>
|
||||
public static void Save<T>(this Stream stream, T value) where T : ISaveable => value.Save(stream);
|
||||
|
||||
// ---- Backports ----
|
||||
#if NETSTANDARD2_0
|
||||
// ---- Backports ----
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the
|
||||
|
@ -19,13 +19,13 @@ namespace Syroot.Worms.Test.Armageddon
|
||||
/// Tests all files found in the test directory.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestFiles() => Tools.TestFiles<Scheme>("*.wsc");
|
||||
public void TestSchemes() => Tools.TestFiles<Scheme>("*.wsc");
|
||||
|
||||
/// <summary>
|
||||
/// Tests all schemes from a Worms Scheme Database CSV dump (ask owner Byte for updated dumps).
|
||||
/// </summary>
|
||||
[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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user