Fix saving TeamContainer instances and add local test files for them.

This commit is contained in:
Ray Koopa 2020-06-27 16:58:34 +02:00
parent fabc3e98b2
commit 7e3fcb766c
9 changed files with 100 additions and 121 deletions

View File

@ -211,7 +211,7 @@ namespace Syroot.Worms.Armageddon
{ {
BitsPerPixel = 8, BitsPerPixel = 8,
Size = new Size(24, 32), Size = new Size(24, 32),
Palette = reader.ReadStructs<Color>(256), Palette = reader.ReadColors(256),
Data = reader.ReadBytes(24 * 32) Data = reader.ReadBytes(24 * 32)
}; };
} }
@ -234,7 +234,7 @@ namespace Syroot.Worms.Armageddon
{ {
BitsPerPixel = 8, BitsPerPixel = 8,
Size = new Size(20, 17), Size = new Size(20, 17),
Palette = reader.ReadStructs<Color>(256), Palette = reader.ReadColors(256),
Data = reader.ReadBytes(20 * 17) Data = reader.ReadBytes(20 * 17)
}; };
@ -264,7 +264,7 @@ namespace Syroot.Worms.Armageddon
if (GraveSprite < 0) if (GraveSprite < 0)
{ {
writer.WriteString(GraveFileName, 0x20); writer.WriteString(GraveFileName, 0x20);
writer.WriteStructs(Grave.Palette); writer.WriteColors(Grave.Palette);
writer.Write(Grave.Data); writer.Write(Grave.Data);
} }
@ -282,7 +282,7 @@ namespace Syroot.Worms.Armageddon
writer.WriteStructs(MissionStatuses); writer.WriteStructs(MissionStatuses);
writer.WriteString(FlagFileName, 0x20); writer.WriteString(FlagFileName, 0x20);
writer.WriteStructs(Flag.Palette); writer.WriteColors(Flag.Palette);
writer.Write(Flag.Data); writer.Write(Flag.Data);
writer.Write(DeathmatchRank); writer.Write(DeathmatchRank);
@ -301,14 +301,11 @@ namespace Syroot.Worms.Armageddon
[DebuggerDisplay("TeamMissionStatus Attemps={Attempts} Medal={Medal}")] [DebuggerDisplay("TeamMissionStatus Attemps={Attempts} Medal={Medal}")]
public struct TeamMissionStatus public struct TeamMissionStatus
{ {
/// <summary> // ---- FIELDS -------------------------------------------------------------------------------------------------
/// The number of attempts the team required to solve the mission.
/// </summary>
public int Attempts;
/// <summary> /// <summary>The number of attempts the team required to solve the mission.</summary>
/// The medal the team got to solve the mission. public int Attempts;
/// </summary> /// <summary>The medal the team got to solve the mission.</summary>
public int Medal; public int Medal;
} }
@ -317,44 +314,21 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public enum TeamWeapon : byte public enum TeamWeapon : byte
{ {
/// <summary> /// <summary>The Flame Thrower weapon.</summary>
/// The Flame Thrower weapon.
/// </summary>
Flamethrower, Flamethrower,
/// <summary>The Mole Bomb weapon.</summary>
/// <summary>
/// The Mole Bomb weapon.
/// </summary>
MoleBomb, MoleBomb,
/// <summary>The Old Woman weapon.</summary>
/// <summary>
/// The Old Woman weapon.
/// </summary>
OldWoman, OldWoman,
/// <summary>The Homing Pigeon weapon.</summary>
/// <summary>
/// The Homing Pigeon weapon.
/// </summary>
HomingPigeon, HomingPigeon,
/// <summary>The Sheep Launcher weapon.</summary>
/// <summary>
/// The Sheep Launcher weapon.
/// </summary>
SheepLauncher, SheepLauncher,
/// <summary>The Mad Cow weapon.</summary>
/// <summary>
/// The Mad Cow weapon.
/// </summary>
MadCow, MadCow,
/// <summary>The Holy Hand Grenade weapon.</summary>
/// <summary>
/// The Holy Hand Grenade weapon.
/// </summary>
HolyHandGrenade, HolyHandGrenade,
/// <summary>The Super Sheep or Aqua Sheep weapon.</summary>
/// <summary>
/// The Super Sheep or Aqua Sheep weapon.
/// </summary>
SuperSheep SuperSheep
} }
} }

View File

@ -57,7 +57,7 @@ namespace Syroot.Worms.Armageddon
/// <summary> /// <summary>
/// Gets or sets the list of <see cref="Team"/> instances stored. /// Gets or sets the list of <see cref="Team"/> instances stored.
/// </summary> /// </summary>
public List<Team> Teams { get; set; } public IList<Team> Teams { get; set; }
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
@ -90,7 +90,7 @@ namespace Syroot.Worms.Armageddon
/// <inheritdoc/> /// <inheritdoc/>
public void Save(Stream stream) public void Save(Stream stream)
{ {
using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII); using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
// Write the header. // Write the header.
writer.Write(_signature, StringCoding.ZeroTerminated); writer.Write(_signature, StringCoding.ZeroTerminated);
@ -120,74 +120,35 @@ namespace Syroot.Worms.Armageddon
[Flags] [Flags]
public enum UnlockedFeatures : int public enum UnlockedFeatures : int
{ {
/// <summary> /// <summary>No features have been unlocked yet.</summary>
/// The utility weapon Laser Sight can be configured. None,
/// </summary> /// <summary>The utility weapon Laser Sight can be configured.</summary>
UtilityLaserSight = 1 << 0, UtilityLaserSight = 1 << 0,
/// <summary>The utility weapon Fast Walk can be configured.</summary>
/// <summary>
/// The utility weapon Fast Walk can be configured.
/// </summary>
UtilityFastWalk = 1 << 1, UtilityFastWalk = 1 << 1,
/// <summary>The utility weapon Invisibility can be configured.</summary>
/// <summary>
/// The utility weapon Invisibility can be configured.
/// </summary>
UtilityInvisibility = 1 << 2, UtilityInvisibility = 1 << 2,
/// <summary>The utility weapon Low Gravity can be configured.</summary>
/// <summary>
/// The utility weapon Low Gravity can be configured.
/// </summary>
UtilityLowGravity = 1 << 3, UtilityLowGravity = 1 << 3,
/// <summary>The utility weapon Jetpack can be configured.</summary>
/// <summary>
/// The utility weapon Jetpack can be configured.
/// </summary>
UtilityJetpack = 1 << 4, UtilityJetpack = 1 << 4,
/// <summary>The Grenade upgrade can be enabled.</summary>
/// <summary>
/// The Grenade upgrade can be enabled.
/// </summary>
UpgradedGrenade = 1 << 8, UpgradedGrenade = 1 << 8,
/// <summary>The Shotgun upgrade can be enabled.</summary>
/// <summary>
/// The Shotgun upgrade can be enabled.
/// </summary>
UpgradedShotgun = 1 << 9, UpgradedShotgun = 1 << 9,
/// <summary>The cluster upgrade can be enabled.</summary>
/// <summary>
/// The cluster upgrade can be enabled.
/// </summary>
UpgradedClusters = 1 << 10, UpgradedClusters = 1 << 10,
/// <summary>The Longbow upgrade can be enabled.</summary>
/// <summary>
/// The Longbow upgrade can be enabled.
/// </summary>
UpgradedLongbow = 1 << 11, UpgradedLongbow = 1 << 11,
/// <summary>The upgrade of Super Sheeps to become Aqua Sheeps can be enabled.</summary>
/// <summary>
/// The upgrade of Super Sheeps to become Aqua Sheeps can be enabled.
/// </summary>
AquaSheep = 1 << 12, AquaSheep = 1 << 12,
/// <summary>Worms can have infinite health and are killable only by drowning them.</summary>
/// <summary>
/// Worms can have infinite health and are killable only by drowning them.
/// </summary>
GodWorms = 1 << 16, GodWorms = 1 << 16,
/// <summary>Blood effects when hitting worms can be enabled.</summary>
/// <summary>
/// Blood effects when hitting worms can be enabled.
/// </summary>
BloodFx = 1 << 17, BloodFx = 1 << 17,
/// <summary>Every crate explodes with a sheep.</summary>
/// <summary>
/// Every crate explodes with a sheep.
/// </summary>
SheepHeaven = 1 << 18, SheepHeaven = 1 << 18,
/// <summary>Map terrain can be indestructible and Full Wormage scheme is accessible.</summary>
/// <summary>
/// Map terrain can be indestructible and Full Wormage scheme is accessible.
/// </summary>
IndestructibleAndFullWormage = 1 << 24 IndestructibleAndFullWormage = 1 << 24
} }
} }

View File

@ -210,7 +210,7 @@ namespace Syroot.Worms.WorldParty
{ {
BitsPerPixel = 8, BitsPerPixel = 8,
Size = new Size(24, 32), Size = new Size(24, 32),
Palette = reader.ReadStructs<Color>(256), Palette = reader.ReadColors(256),
Data = reader.ReadBytes(24 * 32) Data = reader.ReadBytes(24 * 32)
}; };
} }
@ -233,7 +233,7 @@ namespace Syroot.Worms.WorldParty
{ {
BitsPerPixel = 8, BitsPerPixel = 8,
Size = new Size(20, 17), Size = new Size(20, 17),
Palette = reader.ReadStructs<Color>(256), Palette = reader.ReadColors(256),
Data = reader.ReadBytes(20 * 17) Data = reader.ReadBytes(20 * 17)
}; };
@ -262,7 +262,7 @@ namespace Syroot.Worms.WorldParty
if (GraveSprite < 0) if (GraveSprite < 0)
{ {
writer.WriteString(GraveFileName, 0x20); writer.WriteString(GraveFileName, 0x20);
writer.WriteStructs(Grave.Palette); writer.WriteColors(Grave.Palette);
writer.Write(Grave.Data); writer.Write(Grave.Data);
} }
@ -280,7 +280,7 @@ namespace Syroot.Worms.WorldParty
writer.WriteStructs(MissionStatuses); writer.WriteStructs(MissionStatuses);
writer.WriteString(FlagFileName, 0x20); writer.WriteString(FlagFileName, 0x20);
writer.WriteStructs(Flag.Palette); writer.WriteColors(Flag.Palette);
writer.Write(Flag.Data); writer.Write(Flag.Data);
writer.Write(Unknown1); writer.Write(Unknown1);

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -22,7 +23,7 @@ namespace Syroot.Worms.Core.IO
/// Reads an <see cref="ILoadable"/> instance from the current stream. /// Reads an <see cref="ILoadable"/> instance from the current stream.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the <see cref="ILoadable"/> class to instantiate.</typeparam> /// <typeparam name="T">The type of the <see cref="ILoadable"/> class to instantiate.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <returns>The <see cref="ILoadable"/> instance.</returns> /// <returns>The <see cref="ILoadable"/> instance.</returns>
public static T Load<T>(this BinaryStream self) where T : ILoadable, new() public static T Load<T>(this BinaryStream self) where T : ILoadable, new()
{ {
@ -35,7 +36,7 @@ namespace Syroot.Worms.Core.IO
/// Reads <see cref="ILoadable"/> instances from the current stream. /// Reads <see cref="ILoadable"/> instances from the current stream.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the <see cref="ILoadable"/> class to instantiate.</typeparam> /// <typeparam name="T">The type of the <see cref="ILoadable"/> class to instantiate.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="count">The number of instances to read.</param> /// <param name="count">The number of instances to read.</param>
/// <returns>The <see cref="ILoadable"/> instances.</returns> /// <returns>The <see cref="ILoadable"/> instances.</returns>
public static T[] Load<T>(this BinaryStream self, int count) where T : ILoadable, new() public static T[] Load<T>(this BinaryStream self, int count) where T : ILoadable, new()
@ -46,10 +47,31 @@ namespace Syroot.Worms.Core.IO
return instances; return instances;
} }
/// <summary>
/// Reads an RGBA 32-bit color.
/// </summary>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <returns>The read color.</returns>
public static Color ReadColor(this BinaryStream self) => Color.FromArgb(self.ReadInt32());
/// <summary>
/// Reads <paramref name="count"/> RGBA 32-bit colors.
/// </summary>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="count">The number of values to read.</param>
/// <returns>The read colors.</returns>
public static Color[] ReadColors(this BinaryStream self, int count)
{
Color[] values = new Color[count];
for (int i = 0; i < count; i++)
values[i] = Color.FromArgb(self.ReadInt32());
return values;
}
/// <summary> /// <summary>
/// Reads a 0-terminated string which is stored in a fixed-size block of <paramref name="length"/> bytes. /// Reads a 0-terminated string which is stored in a fixed-size block of <paramref name="length"/> bytes.
/// </summary> /// </summary>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="length">The number of bytes the fixed-size blocks takes.</param> /// <param name="length">The number of bytes the fixed-size blocks takes.</param>
/// <returns>The read string.</returns> /// <returns>The read string.</returns>
public static string ReadString(this BinaryStream self, int length) public static string ReadString(this BinaryStream self, int length)
@ -65,10 +87,10 @@ namespace Syroot.Worms.Core.IO
/// Reads <paramref name="count"/> 0-terminated strings which are stored in a fixed-size block of /// Reads <paramref name="count"/> 0-terminated strings which are stored in a fixed-size block of
/// <paramref name="length"/> bytes. /// <paramref name="length"/> bytes.
/// </summary> /// </summary>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="count">The number of values to read.</param> /// <param name="count">The number of values to read.</param>
/// <param name="length">The number of bytes the fixed-size blocks takes.</param> /// <param name="length">The number of bytes the fixed-size blocks takes.</param>
/// <returns>The read string.</returns> /// <returns>The read strings.</returns>
public static string[] ReadStrings(this BinaryStream self, int count, int length) public static string[] ReadStrings(this BinaryStream self, int count, int length)
{ {
string[] strings = new string[count]; string[] strings = new string[count];
@ -83,7 +105,7 @@ namespace Syroot.Worms.Core.IO
/// <typeparam name="T">The type of the structure to read.</typeparam> /// <typeparam name="T">The type of the structure to read.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <returns>The structure of type <typeparamref name="T"/>.</returns> /// <returns>The structure of type <typeparamref name="T"/>.</returns>
public static T ReadStruct<T>(this BinaryStream self) where T : struct public static T ReadStruct<T>(this BinaryStream self) where T : unmanaged
{ {
// Read the raw bytes of the structure. // Read the raw bytes of the structure.
#if NETSTANDARD2_0 #if NETSTANDARD2_0
@ -106,7 +128,7 @@ namespace Syroot.Worms.Core.IO
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="count">The number of values to read.</param> /// <param name="count">The number of values to read.</param>
/// <returns>The structures of type <typeparamref name="T"/>.</returns> /// <returns>The structures of type <typeparamref name="T"/>.</returns>
public static T[] ReadStructs<T>(this BinaryStream self, int count) where T : struct public static T[] ReadStructs<T>(this BinaryStream self, int count) where T : unmanaged
{ {
// Read the raw bytes of the structures. // Read the raw bytes of the structures.
#if NETSTANDARD2_0 #if NETSTANDARD2_0
@ -141,7 +163,7 @@ namespace Syroot.Worms.Core.IO
/// Writes the given <see cref="ISaveable"/> instance into the current stream. /// Writes the given <see cref="ISaveable"/> instance into the current stream.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the <see cref="ISaveable"/> class to write.</typeparam> /// <typeparam name="T">The type of the <see cref="ISaveable"/> class to write.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="value">The instance to write into the current stream.</param> /// <param name="value">The instance to write into the current stream.</param>
public static void Save<T>(this BinaryStream self, T value) where T : ISaveable public static void Save<T>(this BinaryStream self, T value) where T : ISaveable
{ {
@ -152,7 +174,7 @@ namespace Syroot.Worms.Core.IO
/// Writes the given <see cref="ISaveable"/> instances into the current stream. /// Writes the given <see cref="ISaveable"/> instances into the current stream.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the <see cref="ISaveable"/> class to write.</typeparam> /// <typeparam name="T">The type of the <see cref="ISaveable"/> class to write.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="values">The instances to write into the current stream.</param> /// <param name="values">The instances to write into the current stream.</param>
public static void Save<T>(this BinaryStream self, IList<T> values) where T : ISaveable public static void Save<T>(this BinaryStream self, IList<T> values) where T : ISaveable
{ {
@ -166,6 +188,25 @@ namespace Syroot.Worms.Core.IO
self.WriteInt32(value); self.WriteInt32(value);
} }
/// <summary>
/// Writes the given color.
/// </summary>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="value">The color to write.</param>
public static void WriteColor(this BinaryStream self, Color color)
=> self.Write(color.R << 24 | color.G << 16 | color.B << 8 | color.A);
/// <summary>
/// Writes the given colors.
/// </summary>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="value">The colors to write.</param>
public static void WriteColors(this BinaryStream self, IEnumerable<Color> colors)
{
foreach (Color color in colors)
WriteColor(self, color);
}
/// <summary> /// <summary>
/// Writes the given string into a fixed-size block of <paramref name="length"/> bytes and 0-terminates it. /// Writes the given string into a fixed-size block of <paramref name="length"/> bytes and 0-terminates it.
/// </summary> /// </summary>
@ -187,7 +228,7 @@ namespace Syroot.Worms.Core.IO
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="values">The strings to write.</param> /// <param name="values">The strings to write.</param>
/// <param name="length">The number of bytes a fixed-size block takes.</param> /// <param name="length">The number of bytes a fixed-size block takes.</param>
public static void WriteStrings(this BinaryStream self, IList<string> values, int length) public static void WriteStrings(this BinaryStream self, IEnumerable<string> values, int length)
{ {
foreach (string value in values) foreach (string value in values)
WriteString(self, value, length); WriteString(self, value, length);
@ -199,7 +240,7 @@ namespace Syroot.Worms.Core.IO
/// <typeparam name="T">The type of the structure to read.</typeparam> /// <typeparam name="T">The type of the structure to read.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="value">The structure to write.</param> /// <param name="value">The structure to write.</param>
public static void WriteStruct<T>(this BinaryStream self, T value) where T : struct public static void WriteStruct<T>(this BinaryStream self, T value) where T : unmanaged
{ {
ReadOnlySpan<byte> bytes; ReadOnlySpan<byte> bytes;
unsafe { bytes = new ReadOnlySpan<byte>(Unsafe.AsPointer(ref value), Unsafe.SizeOf<T>()); } unsafe { bytes = new ReadOnlySpan<byte>(Unsafe.AsPointer(ref value), Unsafe.SizeOf<T>()); }
@ -216,10 +257,10 @@ namespace Syroot.Worms.Core.IO
/// <typeparam name="T">The type of the structure to read.</typeparam> /// <typeparam name="T">The type of the structure to read.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="values">The structures to write.</param> /// <param name="values">The structures to write.</param>
public static void WriteStructs<T>(this BinaryStream self, IEnumerable<T> values) where T : struct public static void WriteStructs<T>(this BinaryStream self, IEnumerable<T> values) where T : unmanaged
{ {
foreach (T value in values) foreach (T value in values)
self.WriteStruct(value); WriteStruct(self, value);
} }
} }
} }

View File

@ -13,9 +13,9 @@ namespace Syroot.Worms.Test.Armageddon
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary> /// <summary>
/// Loads all files found in any game directories. /// Tests all files found in the test directory.
/// </summary> /// </summary>
[TestMethod] [TestMethod]
public void LoadTeamContainers() => FileTester.Run<TeamContainer>(Game.Armageddon, "*.wgt"); public void LoadTeamContainers() => FileTester.Run<TeamContainer>(Game.Test, "*.wgt");
} }
} }

View File

@ -62,8 +62,11 @@ namespace Syroot.Worms.Test.Core
T newInstance = new T(); T newInstance = new T();
newInstance.Load(stream); newInstance.Load(stream);
Debug.Write($" compare"); if (instance is IEquatable<T> equatable)
Assert.IsTrue(newInstance.Equals(instance)); {
Debug.Write($" compare");
Assert.IsTrue(((IEquatable<T>)newInstance).Equals(equatable));
}
} }
Debug.WriteLine($" OK"); Debug.WriteLine($" OK");
} }