mirror of
https://gitlab.com/Syroot/Worms.git
synced 2025-01-27 22:27:58 +03:00
Fix remaining Scheme bugs.
- Implement IEquatable. - Fix RoundTimeSeconds not properly being parsed. - Uniquely throw ArgumentOutOfRangeException even for rounding properties. - Fix FallDamage not being stored properly. - Add tests for rounding properties and local scheme test files. - Implement equality operations for SchemeWeapon.
This commit is contained in:
parent
378d2474b1
commit
88d07a1ff1
@ -5,7 +5,7 @@
|
||||
<Description>.NET library for loading and modifying files of Worms Armageddon ProjectX.</Description>
|
||||
<PackageReleaseNotes>Fix saving files. Uniquely leave open Stream instances when saving into them.</PackageReleaseNotes>
|
||||
<PackageTags>$(PackageTags);project x;worms armageddon</PackageTags>
|
||||
<Version>3.0.1</Version>
|
||||
<Version>3.1.1</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
|
||||
|
@ -14,7 +14,7 @@ namespace Syroot.Worms.Armageddon
|
||||
/// RubberWorm settings encoded in those.
|
||||
/// Used by WA and WWP. S. https://worms2d.info/Game_scheme_file.
|
||||
/// </summary>
|
||||
public class Scheme : ILoadableFile, ISaveableFile
|
||||
public class Scheme : IEquatable<Scheme>, ILoadableFile, ISaveableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
@ -28,7 +28,7 @@ namespace Syroot.Worms.Armageddon
|
||||
|
||||
private static readonly byte[] _waterRiseRates;
|
||||
|
||||
private byte _fallDamage;
|
||||
private int _fallDamage;
|
||||
private byte _waterRiseIndex;
|
||||
private byte _objectCount;
|
||||
private byte _mineDelay;
|
||||
@ -147,8 +147,8 @@ namespace Syroot.Worms.Armageddon
|
||||
/// values lie between 0-508, at a granularity of 4. Note that changing this value rounds it down to a valid
|
||||
/// granularity.
|
||||
/// </summary>
|
||||
/// <remarks>Valid settings can be enumerated through <see cref="ValidFallDamages"/>.</remarks>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The value is not between 0-508.</exception>
|
||||
/// <remarks>Valid settings can be enumerated through <see cref="ValidFallDamages"/>.</remarks>
|
||||
public int FallDamage
|
||||
{
|
||||
get => _fallDamage;
|
||||
@ -156,7 +156,8 @@ namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
if (value < 0 || value > 508)
|
||||
throw new ArgumentOutOfRangeException(nameof(value), "Fall damage must be between 0-508.");
|
||||
_fallDamage = (byte)(value >> 2 << 2);
|
||||
|
||||
_fallDamage = value >> 2 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,16 +192,20 @@ namespace Syroot.Worms.Armageddon
|
||||
/// Gets or sets the amount in pixels which the water will rise between turns after Sudden Death was triggered.
|
||||
/// Note that changing this value rounds it down to a valid setting.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The value is not between 0-253.</exception>
|
||||
/// <remarks>Valid settings can be enumerated through <see cref="ValidWateRiseRates"/>.</remarks>
|
||||
public byte WaterRiseRate
|
||||
{
|
||||
get => _waterRiseRates[_waterRiseIndex];
|
||||
set
|
||||
{
|
||||
if (value > 253)
|
||||
throw new ArgumentOutOfRangeException(nameof(value), "Water rise rate must be between 0-253.");
|
||||
|
||||
int smallestDeviation = Int32.MaxValue;
|
||||
for (int i = 0; i < _waterRiseRates.Length; i++)
|
||||
{
|
||||
int deviation = Math.Abs(value - _waterRiseRates[i]);
|
||||
int deviation = value - _waterRiseRates[i];
|
||||
if (deviation >= 0 && smallestDeviation > deviation)
|
||||
{
|
||||
smallestDeviation = deviation;
|
||||
@ -247,12 +252,16 @@ namespace Syroot.Worms.Armageddon
|
||||
/// Gets or sets the maximum number of objects (mines or oil drums) on the map. Note that changing this value
|
||||
/// rounds it down to a valid setting.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The value is not between 1-250.</exception>
|
||||
/// <remarks>Valid settings can be enumerated through <see cref="ValidObjectCounts"/>.</remarks>
|
||||
public byte ObjectCount
|
||||
{
|
||||
get => _objectCount;
|
||||
set
|
||||
{
|
||||
if (value < 1 || value > 250)
|
||||
throw new ArgumentOutOfRangeException(nameof(value), "Object count must be between 1-250.");
|
||||
|
||||
if (value > 100)
|
||||
_objectCount = (byte)(value - value % 10);
|
||||
else if (value > 30)
|
||||
@ -651,10 +660,10 @@ namespace Syroot.Worms.Armageddon
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj) => Equals(obj as Scheme);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
@ -714,20 +723,14 @@ namespace Syroot.Worms.Armageddon
|
||||
LoadRubberWormSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
/// <inheritdoc/>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data into the given <paramref name="stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
|
||||
/// <inheritdoc/>
|
||||
public void Save(Stream stream) => Save(stream, SchemeSaveFormat.ExtendedWithObjectCount);
|
||||
|
||||
/// <summary>
|
||||
@ -790,10 +793,7 @@ namespace Syroot.Worms.Armageddon
|
||||
writer.WriteStruct(weapon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data in the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to save the data in.</param>
|
||||
/// <inheritdoc/>
|
||||
public void Save(string fileName) => Save(fileName, SchemeSaveFormat.ExtendedWithObjectCount);
|
||||
|
||||
/// <summary>
|
||||
@ -809,6 +809,101 @@ namespace Syroot.Worms.Armageddon
|
||||
|
||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(Scheme other)
|
||||
=> other != null
|
||||
&& Version == other.Version
|
||||
&& HotSeatDelay == other.HotSeatDelay
|
||||
&& RetreatTime == other.RetreatTime
|
||||
&& RetreatTimeRope == other.RetreatTimeRope
|
||||
&& ShowRoundTime == other.ShowRoundTime
|
||||
&& AutomaticReplays == other.AutomaticReplays
|
||||
&& FallDamage == other.FallDamage
|
||||
&& ArtilleryMode == other.ArtilleryMode
|
||||
&& SchemeEditor == other.SchemeEditor
|
||||
&& StockpilingMode == other.StockpilingMode
|
||||
&& WormSelectMode == other.WormSelectMode
|
||||
&& SuddenDeathEvent == other.SuddenDeathEvent
|
||||
&& WaterRiseRate == other.WaterRiseRate
|
||||
&& WeaponCrateProbability == other.WeaponCrateProbability
|
||||
&& DonorCards == other.DonorCards
|
||||
&& HealthCrateProbability == other.HealthCrateProbability
|
||||
&& HealthCrateEnergy == other.HealthCrateEnergy
|
||||
&& UtilityCrateProbability == other.UtilityCrateProbability
|
||||
&& ObjectTypes == other.ObjectTypes
|
||||
&& ObjectCount == other.ObjectCount
|
||||
&& MineDelay == other.MineDelay
|
||||
&& MineDelayRandom == other.MineDelayRandom
|
||||
&& DudMines == other.DudMines
|
||||
&& ManualWormPlacement == other.ManualWormPlacement
|
||||
&& WormEnergy == other.WormEnergy
|
||||
&& TurnTime == other.TurnTime
|
||||
&& TurnTimeInfinite == other.TurnTimeInfinite
|
||||
&& RoundTimeMinutes == other.RoundTimeMinutes
|
||||
&& RoundTimeSeconds == other.RoundTimeSeconds
|
||||
&& NumberOfWins == other.NumberOfWins
|
||||
&& Blood == other.Blood
|
||||
&& AquaSheep == other.AquaSheep
|
||||
&& SheepHeaven == other.SheepHeaven
|
||||
&& GodWorms == other.GodWorms
|
||||
&& IndestructibleLand == other.IndestructibleLand
|
||||
&& UpgradedGrenade == other.UpgradedGrenade
|
||||
&& UpgradedShotgun == other.UpgradedShotgun
|
||||
&& UpgradedCluster == other.UpgradedCluster
|
||||
&& UpgradedLongbow == other.UpgradedLongbow
|
||||
&& EnableTeamWeapons == other.EnableTeamWeapons
|
||||
&& EnableSuperWeapons == other.EnableSuperWeapons
|
||||
&& Weapons.SequenceEqual(other.Weapons);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
HashCode hash = new HashCode();
|
||||
hash.Add(Version);
|
||||
hash.Add(HotSeatDelay);
|
||||
hash.Add(RetreatTime);
|
||||
hash.Add(RetreatTimeRope);
|
||||
hash.Add(ShowRoundTime);
|
||||
hash.Add(AutomaticReplays);
|
||||
hash.Add(FallDamage);
|
||||
hash.Add(ArtilleryMode);
|
||||
hash.Add(SchemeEditor);
|
||||
hash.Add(StockpilingMode);
|
||||
hash.Add(WormSelectMode);
|
||||
hash.Add(SuddenDeathEvent);
|
||||
hash.Add(WaterRiseRate);
|
||||
hash.Add(WeaponCrateProbability);
|
||||
hash.Add(DonorCards);
|
||||
hash.Add(HealthCrateProbability);
|
||||
hash.Add(HealthCrateEnergy);
|
||||
hash.Add(UtilityCrateProbability);
|
||||
hash.Add(ObjectTypes);
|
||||
hash.Add(ObjectCount);
|
||||
hash.Add(MineDelay);
|
||||
hash.Add(MineDelayRandom);
|
||||
hash.Add(DudMines);
|
||||
hash.Add(ManualWormPlacement);
|
||||
hash.Add(WormEnergy);
|
||||
hash.Add(TurnTime);
|
||||
hash.Add(TurnTimeInfinite);
|
||||
hash.Add(RoundTimeMinutes);
|
||||
hash.Add(RoundTimeSeconds);
|
||||
hash.Add(NumberOfWins);
|
||||
hash.Add(Blood);
|
||||
hash.Add(AquaSheep);
|
||||
hash.Add(SheepHeaven);
|
||||
hash.Add(GodWorms);
|
||||
hash.Add(IndestructibleLand);
|
||||
hash.Add(UpgradedGrenade);
|
||||
hash.Add(UpgradedShotgun);
|
||||
hash.Add(UpgradedCluster);
|
||||
hash.Add(UpgradedLongbow);
|
||||
hash.Add(EnableTeamWeapons);
|
||||
hash.Add(EnableSuperWeapons);
|
||||
hash.Add(Weapons);
|
||||
return hash.ToHashCode();
|
||||
}
|
||||
|
||||
private int GetWeaponCount() => Version == SchemeVersion.Extended ? 64 : 45;
|
||||
|
||||
private void LoadObjectTypesAndCount(BinaryStream reader)
|
||||
@ -851,10 +946,10 @@ namespace Syroot.Worms.Armageddon
|
||||
private void LoadRoundTimeConfig(BinaryStream reader)
|
||||
{
|
||||
byte raw = reader.Read1Byte();
|
||||
if (raw > 0x7F)
|
||||
if (raw > 127)
|
||||
{
|
||||
RoundTimeMinutes = 0;
|
||||
RoundTimeSeconds = (byte)(raw - 0x7F);
|
||||
RoundTimeSeconds = (byte)(256 - raw);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -941,7 +1036,7 @@ namespace Syroot.Worms.Armageddon
|
||||
private void SaveTurnTimeConfig(BinaryStream writer) => writer.Write(TurnTimeInfinite ? (byte)0xFF : TurnTime);
|
||||
|
||||
private void SaveRoundTimeConfig(BinaryStream writer) => writer.Write(RoundTimeSeconds > 0
|
||||
? (byte)(0xFF - (RoundTimeSeconds - 1))
|
||||
? (byte)(256 - RoundTimeSeconds)
|
||||
: RoundTimeMinutes);
|
||||
|
||||
private void SaveRubberWormSettings()
|
||||
|
@ -1,25 +1,47 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the configuration of a weapon.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("Ammo={Ammunition} Power={Power} Delay={Delay} Prob={Probability}")]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SchemeWeapon
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the configuration of a weapon.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("Ammo={Ammunition} Power={Power} Delay={Delay} Prob={Probability}")]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SchemeWeapon : IEquatable<SchemeWeapon>
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>Amount with which a team is equipped at game start. 10 and negative values represent infinity.</summary>
|
||||
public sbyte Ammunition;
|
||||
/// <summary>Power of this weapon.</summary>
|
||||
public byte Power;
|
||||
|
||||
/// <summary>Amount with which a team is equipped at game start. 10 and negative values represent infinity.</summary>
|
||||
public sbyte Ammunition;
|
||||
/// <summary>Power of this weapon.</summary>
|
||||
public byte Power;
|
||||
/// <summary>Number of turns required to be taken by each team before this weapon becomes available. Negative
|
||||
/// values represent infinity.</summary>
|
||||
public sbyte Delay;
|
||||
/// <summary>Percentual chance of this weapon to appear in crates. Has no effect for super weapons.</summary>
|
||||
public sbyte Probability;
|
||||
}
|
||||
}
|
||||
/// values represent infinity.</summary>
|
||||
public sbyte Delay;
|
||||
/// <summary>Percentual chance of this weapon to appear in crates. Has no effect for super weapons.</summary>
|
||||
public sbyte Probability;
|
||||
|
||||
// ---- OPERATORS ----------------------------------------------------------------------------------------------
|
||||
|
||||
public static bool operator ==(SchemeWeapon left, SchemeWeapon right) => left.Equals(right);
|
||||
|
||||
public static bool operator !=(SchemeWeapon left, SchemeWeapon right) => !(left == right);
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj) => obj is SchemeWeapon weapon && Equals(weapon);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(SchemeWeapon other)
|
||||
=> Ammunition == other.Ammunition
|
||||
&& Power == other.Power
|
||||
&& Delay == other.Delay
|
||||
&& Probability == other.Probability;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode() => HashCode.Combine(Ammunition, Power, Delay, Probability);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
<Description>.NET library for loading and modifying files of Team17's Worms Armageddon.</Description>
|
||||
<PackageReleaseNotes>Simplify scheme fall damage and water rise usage.</PackageReleaseNotes>
|
||||
<PackageTags>$(PackageTags);worms armageddon</PackageTags>
|
||||
<Version>3.1.0</Version>
|
||||
<Version>3.1.1</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||
|
@ -5,7 +5,7 @@
|
||||
<Description>.NET library for loading and modifying files of Mgame Worms clients.</Description>
|
||||
<PackageReleaseNotes>Fix saving files. Uniquely leave open Stream instances when saving into them.</PackageReleaseNotes>
|
||||
<PackageTags>$(PackageTags);online worms;worms world party aqua</PackageTags>
|
||||
<Version>3.0.1</Version>
|
||||
<Version>3.1.1</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||
|
@ -5,7 +5,7 @@
|
||||
<Description>.NET library for loading and modifying files of Team17's Worms World Party.</Description>
|
||||
<PackageReleaseNotes>Fix saving files. Uniquely leave open Stream instances when saving into them.</PackageReleaseNotes>
|
||||
<PackageTags>$(PackageTags);worms world party</PackageTags>
|
||||
<Version>3.0.1</Version>
|
||||
<Version>3.1.1</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||
|
@ -5,7 +5,7 @@
|
||||
<Description>.NET library for loading and modifying files of Team17's Worms 2.</Description>
|
||||
<PackageReleaseNotes>Fix saving files. Uniquely leave open Stream instances when saving into them.</PackageReleaseNotes>
|
||||
<PackageTags>$(PackageTags);worms 2</PackageTags>
|
||||
<Version>3.0.1</Version>
|
||||
<Version>3.1.1</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||
|
@ -5,7 +5,7 @@
|
||||
<AssemblyName>Syroot.Worms</AssemblyName>
|
||||
<Description>.NET library for loading and modifying files of Team17 Worms games.</Description>
|
||||
<PackageReleaseNotes>Fix saving files. Uniquely leave open Stream instances when saving into them.</PackageReleaseNotes>
|
||||
<Version>3.0.1</Version>
|
||||
<Version>3.1.1</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Syroot.BinaryData.Serialization" Version="[5.2.0, 6)" />
|
||||
@ -13,4 +13,7 @@
|
||||
<PackageReference Include="System.Drawing.Common" Version="[4.7.0, 5)" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="[4.7.1, 5)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
|
||||
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Armageddon.ProjectX
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadLibraries()
|
||||
{
|
||||
FileTester.LoadFiles<Library>(Game.Armageddon, "*.pxl");
|
||||
}
|
||||
public void LoadLibraries() => FileTester.Run<Library>(Game.Armageddon, "*.pxl");
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Armageddon.ProjectX
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadSchemes()
|
||||
{
|
||||
FileTester.LoadFiles<Scheme>(Game.Armageddon, "*.pxs");
|
||||
}
|
||||
public void LoadSchemes() => FileTester.Run<Scheme>(Game.Armageddon, "*.pxs");
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/test/Syroot.Worms.Armageddon.Test/Files/Schemes/WWP/Pro.wsc
Normal file
BIN
src/test/Syroot.Worms.Armageddon.Test/Files/Schemes/WWP/Pro.wsc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Armageddon
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadGeneratedMaps()
|
||||
{
|
||||
FileTester.LoadFiles<GeneratedMap>(Game.Armageddon | Game.WorldParty, "*.lev");
|
||||
}
|
||||
public void LoadGeneratedMaps() => FileTester.Run<GeneratedMap>(Game.Armageddon | Game.WorldParty, "*.lev");
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Armageddon
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadLandData()
|
||||
{
|
||||
FileTester.LoadFiles<LandData>(Game.Armageddon, "land.dat");
|
||||
}
|
||||
public void LoadLandData() => FileTester.Run<LandData>(Game.Armageddon, "land.dat");
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,79 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Syroot.Worms.Armageddon;
|
||||
using Syroot.Worms.Test.Core;
|
||||
|
||||
namespace Syroot.Worms.Test.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of tests for the <see cref="Scheme"/> class.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class SchemeTests
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadSchemes()
|
||||
{
|
||||
FileTester.LoadFiles<Scheme>(Game.Armageddon | Game.WorldParty, "*.wsc");
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Syroot.Worms.Armageddon;
|
||||
using Syroot.Worms.Test.Core;
|
||||
|
||||
namespace Syroot.Worms.Test.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of tests for the <see cref="Scheme"/> class.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class SchemeTests
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads all files found in the test directory.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestFiles() => FileTester.Run<Scheme>(Game.Test, "*.wsc");
|
||||
|
||||
/// <summary>
|
||||
/// Tests rounding down to the nearest valid fall damage value.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void RoundFallDamage()
|
||||
{
|
||||
Scheme scheme = new Scheme();
|
||||
Assert.ThrowsException<ArgumentOutOfRangeException>(() => scheme.FallDamage = -1);
|
||||
scheme.FallDamage = 0; Assert.AreEqual(0, scheme.FallDamage);
|
||||
scheme.FallDamage = 1; Assert.AreEqual(0, scheme.FallDamage);
|
||||
scheme.FallDamage = 3; Assert.AreEqual(0, scheme.FallDamage);
|
||||
scheme.FallDamage = 4; Assert.AreEqual(4, scheme.FallDamage);
|
||||
scheme.FallDamage = 507; Assert.AreEqual(504, scheme.FallDamage);
|
||||
scheme.FallDamage = 508; Assert.AreEqual(508, scheme.FallDamage);
|
||||
Assert.ThrowsException<ArgumentOutOfRangeException>(() => scheme.FallDamage = 509);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests rounding down to the nearest valid water rise rate value.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void RoundWaterRiseRate()
|
||||
{
|
||||
Scheme scheme = new Scheme();
|
||||
scheme.WaterRiseRate = 0; Assert.AreEqual(0, scheme.WaterRiseRate);
|
||||
scheme.WaterRiseRate = 1; Assert.AreEqual(0, scheme.WaterRiseRate);
|
||||
scheme.WaterRiseRate = 4; Assert.AreEqual(0, scheme.WaterRiseRate);
|
||||
scheme.WaterRiseRate = 5; Assert.AreEqual(5, scheme.WaterRiseRate);
|
||||
scheme.WaterRiseRate = 252; Assert.AreEqual(245, scheme.WaterRiseRate);
|
||||
scheme.WaterRiseRate = 253; Assert.AreEqual(253, scheme.WaterRiseRate);
|
||||
Assert.ThrowsException<ArgumentOutOfRangeException>(() => scheme.WaterRiseRate = 254);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests rounding down to the nearest valid fall damage value.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void RoundObjectCount()
|
||||
{
|
||||
Scheme scheme = new Scheme();
|
||||
Assert.ThrowsException<ArgumentOutOfRangeException>(() => scheme.ObjectCount = 0);
|
||||
scheme.ObjectCount = 1; Assert.AreEqual(1, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 2; Assert.AreEqual(2, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 30; Assert.AreEqual(30, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 31; Assert.AreEqual(30, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 34; Assert.AreEqual(30, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 35; Assert.AreEqual(35, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 99; Assert.AreEqual(95, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 100; Assert.AreEqual(100, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 101; Assert.AreEqual(100, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 109; Assert.AreEqual(100, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 110; Assert.AreEqual(110, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 249; Assert.AreEqual(240, scheme.ObjectCount);
|
||||
scheme.ObjectCount = 250; Assert.AreEqual(250, scheme.ObjectCount);
|
||||
Assert.ThrowsException<ArgumentOutOfRangeException>(() => scheme.ObjectCount = 251);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
|
||||
<ProjectReference Include="..\..\library\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
|
||||
<ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
|
||||
<ProjectReference Include="..\..\library\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
|
||||
<ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Files\**\*.*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Armageddon
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadTeamContainers()
|
||||
{
|
||||
FileTester.LoadFiles<TeamContainer>(Game.Armageddon, "*.wgt");
|
||||
}
|
||||
public void LoadTeamContainers() => FileTester.Run<TeamContainer>(Game.Armageddon, "*.wgt");
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,6 @@ namespace Syroot.Worms.Test
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadArchives()
|
||||
{
|
||||
FileTester.LoadFiles<Archive>(Game.Team17, "*.dir");
|
||||
}
|
||||
public void LoadArchives() => FileTester.Run<Archive>(Game.Team17, "*.dir");
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Syroot.Worms.Core.IO;
|
||||
|
||||
namespace Syroot.Worms.Test.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents methods helping in executing file-based tests.
|
||||
/// </summary>
|
||||
public static class FileTester
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private static readonly Dictionary<Game, string> _gamePaths = new Dictionary<Game, string>
|
||||
{
|
||||
[Game.Worms2] = @"C:\Games\Worms2",
|
||||
[Game.Armageddon] = @"C:\Games\Worms Armageddon 3.6.31.0",
|
||||
[Game.WorldParty] = @"C:\Games\Worms World Party",
|
||||
[Game.OnlineWorms] = @"C:\Games\Online Worms",
|
||||
[Game.WorldPartyAqua] = @"C:\Games\WWP Aqua"
|
||||
};
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads the files found with the given <paramref name="wildcard"/>. Excludes file names specified in the
|
||||
/// optional array <paramref name="excludedFiles"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the files to load.</typeparam>
|
||||
/// <param name="games">The games to test.</param>
|
||||
/// <param name="wildcard">The wildcard to match.</param>
|
||||
/// <param name="excludedFiles">Optionally, the files to exclude.</param>
|
||||
public static void LoadFiles<T>(Game games, string wildcard, string[] excludedFiles = null)
|
||||
where T : ILoadableFile, new()
|
||||
{
|
||||
foreach (string fileName in FindFiles(games, wildcard))
|
||||
{
|
||||
if (excludedFiles?.Contains(Path.GetFileName(fileName), StringComparer.OrdinalIgnoreCase) == true)
|
||||
{
|
||||
Debug.WriteLine($"Skipping {fileName}");
|
||||
continue;
|
||||
}
|
||||
Debug.Write($"Loading {fileName}...");
|
||||
T instance = new T();
|
||||
instance.Load(fileName);
|
||||
Debug.WriteLine($" ok");
|
||||
}
|
||||
}
|
||||
|
||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||
|
||||
private static List<string> FindFiles(Game games, string wildcard)
|
||||
{
|
||||
List<string> files = new List<string>();
|
||||
foreach (string path in GetGamePaths(games))
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
files.AddRange(Directory.GetFiles(path, wildcard, SearchOption.AllDirectories));
|
||||
}
|
||||
if (files.Count == 0)
|
||||
throw new InvalidOperationException("No files found to test.");
|
||||
return files;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetGamePaths(Game game)
|
||||
{
|
||||
return _gamePaths.Where(x => game.HasFlag(x.Key)).Select(x => x.Value);
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Game
|
||||
{
|
||||
Worms2 = 1 << 0,
|
||||
Armageddon = 1 << 1,
|
||||
WorldParty = 1 << 2,
|
||||
OnlineWorms = 1 << 3,
|
||||
WorldPartyAqua = 1 << 4,
|
||||
|
||||
Team17 = Worms2 | Armageddon | WorldParty,
|
||||
Mgame = OnlineWorms | WorldPartyAqua,
|
||||
All = -1
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Syroot.Worms.Core.IO;
|
||||
|
||||
namespace Syroot.Worms.Test.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents methods helping in executing file-based tests.
|
||||
/// </summary>
|
||||
public static class FileTester
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private static readonly Dictionary<Game, string> _gamePaths = new Dictionary<Game, string>
|
||||
{
|
||||
[Game.Worms2] = @"C:\Games\Worms2",
|
||||
[Game.Armageddon] = @"C:\Games\Worms Armageddon 3.6.31.0",
|
||||
[Game.WorldParty] = @"C:\Games\Worms World Party",
|
||||
[Game.OnlineWorms] = @"C:\Games\Online Worms",
|
||||
[Game.WorldPartyAqua] = @"C:\Games\WWP Aqua",
|
||||
[Game.Test] = "Files"
|
||||
};
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads, saves, reloads, and compares the files found with the given <paramref name="wildcard"/>, as long as
|
||||
/// each operation is supported. Excludes file names specified in the optional array
|
||||
/// <paramref name="excludedFiles"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the files to load.</typeparam>
|
||||
/// <param name="games">The games to test.</param>
|
||||
/// <param name="wildcard">The wildcard to match.</param>
|
||||
/// <param name="excludedFiles">Optionally, the files to exclude.</param>
|
||||
public static void Run<T>(Game games, string wildcard, string[] excludedFiles = null)
|
||||
where T : ILoadableFile, new()
|
||||
{
|
||||
foreach (string fileName in FindFiles(games, wildcard))
|
||||
{
|
||||
if (excludedFiles?.Contains(Path.GetFileName(fileName), StringComparer.OrdinalIgnoreCase) == true)
|
||||
{
|
||||
Debug.WriteLine($"Skipping {fileName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug.Write($"\"{fileName}\" load");
|
||||
T instance = new T();
|
||||
instance.Load(fileName);
|
||||
|
||||
if (instance is ISaveableFile saveable)
|
||||
{
|
||||
Debug.Write($" save");
|
||||
using MemoryStream stream = new MemoryStream();
|
||||
saveable.Save(stream);
|
||||
|
||||
Debug.Write($" reload");
|
||||
stream.Position = 0;
|
||||
T newInstance = new T();
|
||||
newInstance.Load(stream);
|
||||
|
||||
Debug.Write($" compare");
|
||||
Assert.IsTrue(newInstance.Equals(instance));
|
||||
}
|
||||
Debug.WriteLine($" OK");
|
||||
}
|
||||
}
|
||||
|
||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||
|
||||
private static List<string> FindFiles(Game games, string wildcard)
|
||||
{
|
||||
List<string> files = new List<string>();
|
||||
foreach (string path in GetGamePaths(games))
|
||||
if (Directory.Exists(path))
|
||||
files.AddRange(Directory.GetFiles(path, wildcard, SearchOption.AllDirectories));
|
||||
if (files.Count == 0)
|
||||
throw new InvalidOperationException("No files found to test.");
|
||||
return files;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetGamePaths(Game game)
|
||||
{
|
||||
return _gamePaths.Where(x => game.HasFlag(x.Key)).Select(x => x.Value);
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Game
|
||||
{
|
||||
Worms2 = 1 << 0,
|
||||
Armageddon = 1 << 1,
|
||||
WorldParty = 1 << 2,
|
||||
OnlineWorms = 1 << 3,
|
||||
WorldPartyAqua = 1 << 4,
|
||||
Test = 1 << 32,
|
||||
|
||||
Team17 = Worms2 | Armageddon | WorldParty,
|
||||
Mgame = OnlineWorms | WorldPartyAqua,
|
||||
All = -1
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,6 @@ namespace Syroot.Worms.Test
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadImages()
|
||||
{
|
||||
FileTester.LoadFiles<Img>(Game.All, "*.img");
|
||||
}
|
||||
public void LoadImages() => FileTester.Run<Img>(Game.All, "*.img");
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace Syroot.Worms.Test
|
||||
[TestMethod]
|
||||
public void LoadPalettes()
|
||||
{
|
||||
FileTester.LoadFiles<RiffPalette>(Game.Team17, "*.pal", new string[]
|
||||
FileTester.Run<RiffPalette>(Game.Team17, "*.pal", new string[]
|
||||
{
|
||||
"wwp.pal", // Contains 4 bytes of trash after the data chunk.
|
||||
"wwpmaped.pal" // Contains 4 bytes of trash after the data chunk.
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.WorldParty
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadLandData()
|
||||
{
|
||||
FileTester.LoadFiles<LandData>(Game.WorldParty, "land.dat");
|
||||
}
|
||||
public void LoadLandData() => FileTester.Run<LandData>(Game.WorldParty, "land.dat");
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.WorldParty
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadTeamContainers()
|
||||
{
|
||||
FileTester.LoadFiles<TeamContainer>(Game.WorldParty, "*.wwp");
|
||||
}
|
||||
public void LoadTeamContainers() => FileTester.Run<TeamContainer>(Game.WorldParty, "*.wwp");
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Worms2
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadLandData()
|
||||
{
|
||||
FileTester.LoadFiles<LandData>(Game.Worms2, "land.dat");
|
||||
}
|
||||
public void LoadLandData() => FileTester.Run<LandData>(Game.Worms2, "land.dat");
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Worms2
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadSchemeOptions()
|
||||
{
|
||||
FileTester.LoadFiles<SchemeOptions>(Game.Worms2, "*.opt");
|
||||
}
|
||||
public void LoadSchemeOptions() => FileTester.Run<SchemeOptions>(Game.Worms2, "*.opt");
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Worms2
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadSchemeWeapons()
|
||||
{
|
||||
FileTester.LoadFiles<SchemeWeapons>(Game.Worms2, "*.wep");
|
||||
}
|
||||
public void LoadSchemeWeapons() => FileTester.Run<SchemeWeapons>(Game.Worms2, "*.wep");
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ namespace Syroot.Worms.Test.Worms2
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadTeamContainers()
|
||||
{
|
||||
FileTester.LoadFiles<TeamContainer>(Game.Worms2, "*.st1");
|
||||
}
|
||||
public void LoadTeamContainers() => FileTester.Run<TeamContainer>(Game.Worms2, "*.st1");
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using Syroot.Worms.Armageddon;
|
||||
using Syroot.Worms.Mgame;
|
||||
|
||||
namespace Syroot.Worms.Scratchpad
|
||||
@ -11,31 +8,7 @@ namespace Syroot.Worms.Scratchpad
|
||||
{
|
||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||
|
||||
private static void Main()
|
||||
{
|
||||
IEnumerable<string> fileNames = Directory.EnumerateFiles(
|
||||
@"C:\Games\Worms Armageddon 3.7.2.1\User\Schemes", "*.wsc", SearchOption.AllDirectories);
|
||||
|
||||
foreach (string fileName in fileNames)
|
||||
{
|
||||
string tempFile = Path.GetTempFileName();
|
||||
using (Stream tempStream = new FileStream(tempFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
// Load the scheme and save it to temp file.
|
||||
Scheme origScheme = new Scheme(fileName);
|
||||
tempStream.Position = 0;
|
||||
origScheme.Save(tempStream);
|
||||
|
||||
// Load the temp file.
|
||||
tempStream.Position = 0;
|
||||
Scheme newScheme = new Scheme(tempStream);
|
||||
|
||||
if (origScheme.ObjectCount != newScheme.ObjectCount || origScheme.ObjectTypes != newScheme.ObjectTypes)
|
||||
throw new InvalidOperationException("mismatch");
|
||||
}
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
}
|
||||
private static void Main() { }
|
||||
|
||||
private static void ConvertIgdImages()
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user