Review code, update code standards and NuGet packages.

This commit is contained in:
Ray Koopa 2019-09-27 20:13:24 +02:00
parent c5391c3d66
commit e57c593efa
62 changed files with 1765 additions and 2221 deletions

View File

@ -11,31 +11,20 @@ namespace Syroot.Worms.Armageddon.ProjectX
public object Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute, public object Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute,
ByteConverter byteConverter) ByteConverter byteConverter)
{ {
ExplosionAction explosionAction; ExplosionAction explosionAction = instance switch
switch (instance)
{ {
case LauncherStyle launcherStyle: LauncherStyle launcherStyle => launcherStyle.ExplosionAction,
explosionAction = launcherStyle.ExplosionAction; ClusterTarget clusterTarget => clusterTarget.ExplosionAction,
break; _ => throw new NotImplementedException(),
case ClusterTarget clusterTarget: };
explosionAction = clusterTarget.ExplosionAction; return explosionAction switch
break;
default:
throw new NotImplementedException();
}
switch (explosionAction)
{ {
case ExplosionAction.Bounce: ExplosionAction.Bounce => stream.ReadObject<BounceAction>(),
return stream.ReadObject<BounceAction>(); ExplosionAction.Dig => stream.ReadObject<DigAction>(),
case ExplosionAction.Dig: ExplosionAction.Home => stream.ReadObject<HomeAction>(),
return stream.ReadObject<DigAction>(); ExplosionAction.Roam => stream.ReadObject<RoamAction>(),
case ExplosionAction.Home: _ => null,
return stream.ReadObject<HomeAction>(); };
case ExplosionAction.Roam:
return stream.ReadObject<RoamAction>();
}
return null;
} }
public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value, public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value,

View File

@ -1,6 +1,4 @@
namespace Syroot.Worms.Armageddon.ProjectX namespace Syroot.Worms.Armageddon.ProjectX
{ {
public interface IAction public interface IAction { }
{
}
} }

View File

@ -25,28 +25,20 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Scheme"/> class. /// Initializes a new instance of the <see cref="Scheme"/> class.
/// </summary> /// </summary>
public Library() public Library() { }
{
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given /// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public Library(Stream stream) public Library(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public Library(string fileName) public Library(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -59,13 +51,7 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// </summary> /// </summary>
/// <param name="key">The key of the entries to match.</param> /// <param name="key">The key of the entries to match.</param>
/// <returns>All matching entries.</returns> /// <returns>All matching entries.</returns>
public IEnumerable<LibraryItem> this[string key] public IEnumerable<LibraryItem> this[string key] => this.Where(x => x.Key == key);
{
get
{
return this.Where(x => x.Key == key);
}
}
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
@ -75,34 +61,31 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadInt32() != _signature)
{
throw new InvalidDataException("Invalid PXL file signature.");
}
Version = reader.Read1Byte();
// Read the items. // Read the header.
Clear(); if (reader.ReadInt32() != _signature)
int itemCount = reader.ReadInt32(); throw new InvalidDataException("Invalid PXL file signature.");
for (int i = 0; i < itemCount; i++) Version = reader.Read1Byte();
// Read the items.
Clear();
int itemCount = reader.ReadInt32();
for (int i = 0; i < itemCount; i++)
{
LibraryItemType type = reader.ReadEnum<LibraryItemType>(true);
string name = reader.ReadString(StringCoding.Int32CharCount);
switch (type)
{ {
LibraryItemType type = reader.ReadEnum<LibraryItemType>(true); case LibraryItemType.File:
string name = reader.ReadString(StringCoding.Int32CharCount); Add(new LibraryItem(name, reader.ReadBytes(reader.ReadInt32())));
switch (type) break;
{ case LibraryItemType.Script:
case LibraryItemType.File: Add(new LibraryItem(name, reader.ReadString(StringCoding.Int32CharCount)));
Add(new LibraryItem(name, reader.ReadBytes(reader.ReadInt32()))); break;
break; case LibraryItemType.Weapon:
case LibraryItemType.Script: Add(new LibraryItem(name, reader.Load<Weapon>()));
Add(new LibraryItem(name, reader.ReadString(StringCoding.Int32CharCount))); break;
break;
case LibraryItemType.Weapon:
Add(new LibraryItem(name, reader.Load<Weapon>()));
break;
}
} }
} }
} }
@ -113,10 +96,8 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -125,32 +106,31 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{
// Write the header.
writer.Write(_signature);
writer.Write(Version);
// Write the items. // Write the header.
writer.Write(Count); writer.Write(_signature);
foreach (LibraryItem item in this) writer.Write(Version);
// Write the items.
writer.Write(Count);
foreach (LibraryItem item in this)
{
writer.WriteEnum(item.Type, true);
writer.Write(item.Key, StringCoding.Int32CharCount);
switch (item.Type)
{ {
writer.WriteEnum(item.Type, true); case LibraryItemType.File:
writer.Write(item.Key, StringCoding.Int32CharCount); byte[] value = (byte[])item.Value;
switch (item.Type) writer.Write(value.Length);
{ writer.WriteStructs(value);
case LibraryItemType.File: break;
byte[] value = (byte[])item.Value; case LibraryItemType.Script:
writer.Write(value.Length); writer.Write((string)item.Value, StringCoding.Int32CharCount);
writer.WriteStructs(value); break;
break; case LibraryItemType.Weapon:
case LibraryItemType.Script: writer.Save((Weapon)item.Value);
writer.Write((string)item.Value, StringCoding.Int32CharCount); break;
break;
case LibraryItemType.Weapon:
writer.Save((Weapon)item.Value);
break;
}
} }
} }
} }
@ -161,10 +141,8 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
/// <summary> /// <summary>
@ -172,27 +150,21 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// </summary> /// </summary>
/// <returns>The enumeration of attached files.</returns> /// <returns>The enumeration of attached files.</returns>
public IEnumerable<byte[]> GetFiles() public IEnumerable<byte[]> GetFiles()
{ => this.Where(x => x.Type == LibraryItemType.File).Select(x => (byte[])x.Value);
return this.Where(x => x.Type == LibraryItemType.File).Select(x => (byte[])x.Value);
}
/// <summary> /// <summary>
/// Gets all attached scripts. /// Gets all attached scripts.
/// </summary> /// </summary>
/// <returns>The enumeration of attached scripts.</returns> /// <returns>The enumeration of attached scripts.</returns>
public IEnumerable<string> GetScripts() public IEnumerable<string> GetScripts()
{ => this.Where(x => x.Type == LibraryItemType.Script).Select(x => (string)x.Value);
return this.Where(x => x.Type == LibraryItemType.Script).Select(x => (string)x.Value);
}
/// <summary> /// <summary>
/// Gets all attached weapons. /// Gets all attached weapons.
/// </summary> /// </summary>
/// <returns>The enumeration of attached weapons.</returns> /// <returns>The enumeration of attached weapons.</returns>
public IEnumerable<Weapon> GetWeapons() public IEnumerable<Weapon> GetWeapons()
{ => this.Where(x => x.Type == LibraryItemType.Weapon).Select(x => (Weapon)x.Value);
return this.Where(x => x.Type == LibraryItemType.Weapon).Select(x => (Weapon)x.Value);
}
} }
/// <summary> /// <summary>
@ -236,29 +208,18 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// </summary> /// </summary>
public object Value public object Value
{ {
get get => _value;
{
return _value;
}
set set
{ {
// Validate the type. // Validate the type.
if (value.GetType() == typeof(byte[])) if (value.GetType() == typeof(byte[]))
{
Type = LibraryItemType.File; Type = LibraryItemType.File;
}
else if (value.GetType() == typeof(string)) else if (value.GetType() == typeof(string))
{
Type = LibraryItemType.Script; Type = LibraryItemType.Script;
}
else if (value.GetType() == typeof(Weapon)) else if (value.GetType() == typeof(Weapon))
{
Type = LibraryItemType.Weapon; Type = LibraryItemType.Weapon;
}
else else
{
throw new ArgumentException("Invalid LibraryItemType.", nameof(value)); throw new ArgumentException("Invalid LibraryItemType.", nameof(value));
}
_value = value; _value = value;
} }
} }

View File

@ -23,28 +23,20 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Scheme"/> class. /// Initializes a new instance of the <see cref="Scheme"/> class.
/// </summary> /// </summary>
public Scheme() public Scheme() { }
{
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given /// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public Scheme(Stream stream) public Scheme(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public Scheme(string fileName) public Scheme(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -72,59 +64,52 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
// Read the header.
if (reader.ReadString(_signature.Length) != _signature)
throw new InvalidDataException("Invalid PXS file signature.");
Version = reader.ReadInt32();
// Read the scheme flags.
Flags = reader.ReadStruct<SchemeFlags>();
// Read the weapon tables.
int weaponTableCount = reader.ReadInt32();
WeaponTables = new List<Weapon[]>(weaponTableCount);
for (int i = 0; i < weaponTableCount; i++)
WeaponTables.Add(reader.Load<Weapon>(_weaponsPerTable));
// Read a placeholder array.
reader.Seek(sizeof(int));
// Read attached files.
int filesCount = reader.ReadInt32();
Files = new Dictionary<string, byte[]>(filesCount);
for (int i = 0; i < filesCount; i++)
{ {
// Read the header. string name = reader.ReadString(StringCoding.Int32CharCount);
if (reader.ReadString(_signature.Length) != _signature) int length = reader.ReadInt32();
{ Files.Add(name, reader.ReadBytes(length));
throw new InvalidDataException("Invalid PXS file signature."); }
}
Version = reader.ReadInt32();
// Read the scheme flags. // Read attached scripts.
Flags = reader.ReadStruct<SchemeFlags>(); int scriptsCount = reader.ReadInt32();
Scripts = new Dictionary<string, string>(scriptsCount);
for (int i = 0; i < scriptsCount; i++)
Scripts.Add(reader.ReadString(StringCoding.Int32CharCount),
reader.ReadString(StringCoding.Int32CharCount));
// Read the weapon tables. // Read required libraries.
int weaponTableCount = reader.ReadInt32(); int librariesCount = reader.ReadInt32();
WeaponTables = new List<Weapon[]>(weaponTableCount); Libraries = new List<string>(reader.ReadStrings(librariesCount, StringCoding.Int32CharCount));
for (int i = 0; i < weaponTableCount; i++)
{
WeaponTables.Add(reader.Load<Weapon>(_weaponsPerTable));
}
// Read a placeholder array. // Read a possibly attached scheme file.
reader.Seek(sizeof(int)); if (reader.ReadBoolean())
{
// Read attached files. reader.Seek(sizeof(int)); // Scheme length not required due to intelligent loading.
int filesCount = reader.ReadInt32(); GameScheme = reader.Load<Armageddon.Scheme>();
Files = new Dictionary<string, byte[]>(filesCount); GameSchemeName = reader.ReadString(StringCoding.Int32CharCount);
for (int i = 0; i < filesCount; i++)
{
string name = reader.ReadString(StringCoding.Int32CharCount);
int length = reader.ReadInt32();
Files.Add(name, reader.ReadBytes(length));
}
// Read attached scripts.
int scriptsCount = reader.ReadInt32();
Scripts = new Dictionary<string, string>(scriptsCount);
for (int i = 0; i < scriptsCount; i++)
{
Scripts.Add(reader.ReadString(StringCoding.Int32CharCount),
reader.ReadString(StringCoding.Int32CharCount));
}
// Read required libraries.
int librariesCount = reader.ReadInt32();
Libraries = new List<string>(reader.ReadStrings(librariesCount, StringCoding.Int32CharCount));
// Read a possibly attached scheme file.
if (reader.ReadBoolean())
{
reader.Seek(sizeof(int)); // Scheme length not required due to intelligent loading.
GameScheme = reader.Load<Armageddon.Scheme>();
GameSchemeName = reader.ReadString(StringCoding.Int32CharCount);
}
} }
} }
@ -134,10 +119,8 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -146,58 +129,55 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
// Write the header.
writer.Write(_signature, StringCoding.Raw);
writer.Write(Version);
// Write the scheme flags.
writer.WriteStruct(Flags);
// Write the weapon tables.
writer.Write(WeaponTables.Count);
foreach (Weapon[] weaponTable in WeaponTables)
writer.Save(weaponTable);
// Write a placeholder array.
writer.Write(0);
// Write attached files.
writer.Write(Files.Count);
foreach (KeyValuePair<string, byte[]> file in Files)
{ {
// Write the header. writer.Write(file.Key, StringCoding.Int32CharCount);
writer.Write(_signature, StringCoding.Raw); writer.Write(file.Value.Length);
writer.Write(Version); writer.WriteStructs(file.Value);
}
// Write the scheme flags. // Write attached scripts.
writer.WriteStruct(Flags); writer.Write(Scripts.Count);
foreach (KeyValuePair<string, string> script in Scripts)
{
writer.Write(script.Key, StringCoding.Int32CharCount);
writer.Write(script.Value, StringCoding.Int32CharCount);
}
// Write the weapon tables. // Write required libraries.
writer.Write(WeaponTables.Count); writer.Write(Libraries.Count);
foreach (Weapon[] weaponTable in WeaponTables) writer.Write(Libraries);
// Write a possibly attached scheme file.
if (GameScheme != null)
{
byte[] schemeBytes;
using (MemoryStream schemeStream = new MemoryStream())
{ {
writer.Save(weaponTable); GameScheme.Save(schemeStream);
} schemeBytes = schemeStream.ToArray();
// Write a placeholder array.
writer.Write(0);
// Write attached files.
writer.Write(Files.Count);
foreach (KeyValuePair<string, byte[]> file in Files)
{
writer.Write(file.Key, StringCoding.Int32CharCount);
writer.Write(file.Value.Length);
writer.WriteStructs(file.Value);
}
// Write attached scripts.
writer.Write(Scripts.Count);
foreach (KeyValuePair<string, string> script in Scripts)
{
writer.Write(script.Key, StringCoding.Int32CharCount);
writer.Write(script.Value, StringCoding.Int32CharCount);
}
// Write required libraries.
writer.Write(Libraries.Count);
writer.Write(Libraries);
// Write a possibly attached scheme file.
if (GameScheme != null)
{
byte[] schemeBytes;
using (MemoryStream schemeStream = new MemoryStream())
{
GameScheme.Save(schemeStream);
schemeBytes = schemeStream.ToArray();
}
writer.Write(schemeBytes.Length);
writer.Write(GameSchemeName, StringCoding.Int32CharCount);
} }
writer.Write(schemeBytes.Length);
writer.Write(GameSchemeName, StringCoding.Int32CharCount);
} }
} }
@ -207,10 +187,8 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
} }
} }

View File

@ -7,28 +7,21 @@ namespace Syroot.Worms.Armageddon.ProjectX
public class AirstrikeSubstyleConverter : IBinaryConverter public class AirstrikeSubstyleConverter : IBinaryConverter
{ {
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public object Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute, public object Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute,
ByteConverter byteConverter) ByteConverter byteConverter)
{ {
WeaponAirstrikeSubstyle airstrikeSubstyle; WeaponAirstrikeSubstyle airstrikeSubstyle = instance switch
switch (instance)
{ {
case AirstrikeStyle airstrikeStyle: AirstrikeStyle airstrikeStyle => airstrikeStyle.AirstrikeSubstyle,
airstrikeSubstyle = airstrikeStyle.AirstrikeSubstyle; _ => throw new NotImplementedException(),
break; };
default: return airstrikeSubstyle switch
throw new NotImplementedException();
}
switch (airstrikeSubstyle)
{ {
case WeaponAirstrikeSubstyle.Launcher: WeaponAirstrikeSubstyle.Launcher => stream.ReadObject<LauncherStyle>(),
return stream.ReadObject<LauncherStyle>(); WeaponAirstrikeSubstyle.Mines => stream.ReadObject<MineStyle>(),
case WeaponAirstrikeSubstyle.Mines: _ => null,
return stream.ReadObject<MineStyle>(); };
}
return null;
} }
public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value, public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value,

View File

@ -1,6 +1,4 @@
namespace Syroot.Worms.Armageddon.ProjectX namespace Syroot.Worms.Armageddon.ProjectX
{ {
public interface IStyle public interface IStyle { }
{
}
} }

View File

@ -1,24 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AssemblyName>Syroot.Worms.Armageddon-ProjectX</AssemblyName> <AssemblyName>Syroot.Worms.Armageddon-ProjectX</AssemblyName>
<Authors>Syroot</Authors> <Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright> <Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library for loading and modifying files of Worms Armageddon ProjectX.</Description> <Description>.NET library for loading and modifying files of Worms Armageddon ProjectX.</Description>
<GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile> <GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl> <PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl>
<PackageId>Syroot.Worms.Armageddon.ProjectX</PackageId> <PackageId>Syroot.Worms.Armageddon.ProjectX</PackageId>
<PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl> <PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes> <PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<PackageTags>worms;team17</PackageTags> <PackageTags>worms;team17</PackageTags>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl> <RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks> <TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>2.0.0-alpha1</Version> <Version>2.0.0-alpha1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" /> <ProjectReference Include="..\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,6 +1,4 @@
namespace Syroot.Worms.Armageddon.ProjectX namespace Syroot.Worms.Armageddon.ProjectX
{ {
public interface ITarget public interface ITarget { }
{
}
} }

View File

@ -11,24 +11,17 @@ namespace Syroot.Worms.Armageddon.ProjectX
public object Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute, public object Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute,
ByteConverter byteConverter) ByteConverter byteConverter)
{ {
ExplosionTarget explosionTarget; ExplosionTarget explosionTarget = instance switch
switch (instance)
{ {
case LauncherStyle launcherStyle: LauncherStyle launcherStyle => launcherStyle.ExplosionTarget,
explosionTarget = launcherStyle.ExplosionTarget; _ => throw new NotImplementedException(),
break; };
default: return explosionTarget switch
throw new NotImplementedException();
}
switch (explosionTarget)
{ {
case ExplosionTarget.Clusters: ExplosionTarget.Clusters => stream.ReadObject<ClusterTarget>(),
return stream.ReadObject<ClusterTarget>(); ExplosionTarget.Fire => stream.ReadObject<FireTarget>(),
case ExplosionTarget.Fire: _ => null,
return stream.ReadObject<FireTarget>(); };
}
return null;
} }
public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value, public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value,

View File

@ -2,7 +2,6 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Syroot.BinaryData; using Syroot.BinaryData;
using Syroot.Worms.Core;
using Syroot.Worms.Core.IO; using Syroot.Worms.Core.IO;
namespace Syroot.Worms.Armageddon.ProjectX namespace Syroot.Worms.Armageddon.ProjectX
@ -114,168 +113,165 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
// Read the header.
long offset = reader.Position;
Version = reader.ReadEnum<WeaponVersion>(true);
Checksum = reader.ReadInt64();
// Read general settings.
TableRow = reader.ReadInt32();
Remembered = reader.ReadBoolean(BooleanCoding.Dword);
UsableInCavern = reader.ReadBoolean(BooleanCoding.Dword);
Shots = reader.ReadInt32();
ShotEndsTurn = reader.ReadBoolean(BooleanCoding.Dword);
RetreatTime = reader.ReadInt32();
Unknown1 = reader.ReadInt32();
CrateChance = reader.ReadInt32();
CrateCount = reader.ReadInt32();
Unknown2 = reader.ReadInt32();
// Read the activation and the corresponding weapon settings.
Activation = reader.ReadEnum<WeaponActivation>(false);
switch (Activation)
{ {
// Read the header. case WeaponActivation.Airstrike:
long offset = reader.Position; AirstrikeSubtype = reader.ReadInt32();
Version = reader.ReadEnum<WeaponVersion>(true); Style = reader.ReadObject<AirstrikeStyle>();
Checksum = reader.ReadInt64(); break;
case WeaponActivation.Crosshair:
// Read general settings. NotUsed = reader.ReadInt32();
TableRow = reader.ReadInt32(); CrosshairAction = reader.ReadEnum<WeaponCrosshairAction>(false);
Remembered = reader.ReadBoolean(BooleanCoding.Dword); switch (CrosshairAction)
UsableInCavern = reader.ReadBoolean(BooleanCoding.Dword); {
Shots = reader.ReadInt32(); case WeaponCrosshairAction.Bow:
ShotEndsTurn = reader.ReadBoolean(BooleanCoding.Dword); Style = reader.ReadObject<BowStyle>();
RetreatTime = reader.ReadInt32(); break;
Unknown1 = reader.ReadInt32(); case WeaponCrosshairAction.Flamethrower:
CrateChance = reader.ReadInt32(); Style = reader.ReadObject<FlamethrowerStyle>();
CrateCount = reader.ReadInt32(); break;
Unknown2 = reader.ReadInt32(); case WeaponCrosshairAction.Gun:
Style = reader.ReadObject<GunStyle>();
// Read the activation and the corresponding weapon settings. break;
Activation = reader.ReadEnum<WeaponActivation>(false); case WeaponCrosshairAction.Launcher:
switch (Activation) Style = reader.ReadObject<LauncherStyle>();
{ break;
case WeaponActivation.Airstrike: }
AirstrikeSubtype = reader.ReadInt32(); break;
Style = reader.ReadObject<AirstrikeStyle>(); case WeaponActivation.Spacebar:
break; SpacebarAction = reader.ReadEnum<WeaponSpacebarAction>(false);
case WeaponActivation.Crosshair: switch (SpacebarAction)
NotUsed = reader.ReadInt32(); {
CrosshairAction = reader.ReadEnum<WeaponCrosshairAction>(false); case WeaponSpacebarAction.Armageddon:
switch (CrosshairAction) Style = reader.ReadObject<LauncherStyle>();
{ break;
case WeaponCrosshairAction.Bow: case WeaponSpacebarAction.BaseballBat:
Style = reader.ReadObject<BowStyle>(); Style = reader.ReadObject<BaseballBatStyle>();
break; break;
case WeaponCrosshairAction.Flamethrower: case WeaponSpacebarAction.BattleAxe:
Style = reader.ReadObject<FlamethrowerStyle>(); Style = reader.ReadObject<BattleAxeStyle>();
break; break;
case WeaponCrosshairAction.Gun: case WeaponSpacebarAction.Blowtorch:
Style = reader.ReadObject<GunStyle>(); Style = reader.ReadObject<BlowtorchStyle>();
break; break;
case WeaponCrosshairAction.Launcher: case WeaponSpacebarAction.Dragonball:
Style = reader.ReadObject<LauncherStyle>(); Style = reader.ReadObject<DragonballStyle>();
break; break;
} case WeaponSpacebarAction.Firepunch:
break; Style = reader.ReadObject<FirepunchStyle>();
case WeaponActivation.Spacebar: break;
SpacebarAction = reader.ReadEnum<WeaponSpacebarAction>(false); case WeaponSpacebarAction.Jetpack:
switch (SpacebarAction) Style = reader.ReadObject<JetpackStyle>();
{ break;
case WeaponSpacebarAction.Armageddon: case WeaponSpacebarAction.Kamikaze:
Style = reader.ReadObject<LauncherStyle>(); Style = reader.ReadObject<KamikazeStyle>();
break; break;
case WeaponSpacebarAction.BaseballBat: case WeaponSpacebarAction.NinjaRope:
Style = reader.ReadObject<BaseballBatStyle>(); Style = reader.ReadObject<NinjaRopeStyle>();
break; break;
case WeaponSpacebarAction.BattleAxe: case WeaponSpacebarAction.NuclearTest:
Style = reader.ReadObject<BattleAxeStyle>(); Style = reader.ReadObject<NuclearTestStyle>();
break; break;
case WeaponSpacebarAction.Blowtorch: case WeaponSpacebarAction.Parachute:
Style = reader.ReadObject<BlowtorchStyle>(); Style = reader.ReadObject<ParachuteStyle>();
break; break;
case WeaponSpacebarAction.Dragonball: case WeaponSpacebarAction.PneumaticDrill:
Style = reader.ReadObject<DragonballStyle>(); Style = reader.ReadObject<PneumaticDrillStyle>();
break; break;
case WeaponSpacebarAction.Firepunch: case WeaponSpacebarAction.Prod:
Style = reader.ReadObject<FirepunchStyle>(); Style = reader.ReadObject<ProdStyle>();
break; break;
case WeaponSpacebarAction.Jetpack: case WeaponSpacebarAction.SuicideBomber:
Style = reader.ReadObject<JetpackStyle>(); Style = reader.ReadObject<SuicideBomberStyle>();
break; break;
case WeaponSpacebarAction.Kamikaze: case WeaponSpacebarAction.Bungee:
Style = reader.ReadObject<KamikazeStyle>(); case WeaponSpacebarAction.Earthquake:
break; case WeaponSpacebarAction.Freeze:
case WeaponSpacebarAction.NinjaRope: case WeaponSpacebarAction.Girder:
Style = reader.ReadObject<NinjaRopeStyle>(); case WeaponSpacebarAction.ScalesOfJustice:
break; case WeaponSpacebarAction.SelectWorm:
case WeaponSpacebarAction.NuclearTest: case WeaponSpacebarAction.SkipGo:
Style = reader.ReadObject<NuclearTestStyle>(); case WeaponSpacebarAction.Surrender:
break; case WeaponSpacebarAction.Teleport:
case WeaponSpacebarAction.Parachute: case WeaponSpacebarAction.Utility:
Style = reader.ReadObject<ParachuteStyle>(); Style = null;
break; break;
case WeaponSpacebarAction.PneumaticDrill: }
Style = reader.ReadObject<PneumaticDrillStyle>(); break;
break; case WeaponActivation.Throw:
case WeaponSpacebarAction.Prod: ThrowHerdCount = reader.ReadInt32();
Style = reader.ReadObject<ProdStyle>(); ThrowAction = reader.ReadEnum<WeaponThrowAction>(false);
break; switch (ThrowAction)
case WeaponSpacebarAction.SuicideBomber: {
Style = reader.ReadObject<SuicideBomberStyle>(); case WeaponThrowAction.Canister:
break; Style = reader.ReadObject<CanisterStyle>();
case WeaponSpacebarAction.Bungee: break;
case WeaponSpacebarAction.Earthquake: case WeaponThrowAction.Launcher:
case WeaponSpacebarAction.Freeze: Style = reader.ReadObject<LauncherStyle>();
case WeaponSpacebarAction.Girder: break;
case WeaponSpacebarAction.ScalesOfJustice: case WeaponThrowAction.Mine:
case WeaponSpacebarAction.SelectWorm: Style = reader.ReadObject<MineStyle>();
case WeaponSpacebarAction.SkipGo: break;
case WeaponSpacebarAction.Surrender: }
case WeaponSpacebarAction.Teleport: break;
case WeaponSpacebarAction.Utility:
Style = null;
break;
}
break;
case WeaponActivation.Throw:
ThrowHerdCount = reader.ReadInt32();
ThrowAction = reader.ReadEnum<WeaponThrowAction>(false);
switch (ThrowAction)
{
case WeaponThrowAction.Canister:
Style = reader.ReadObject<CanisterStyle>();
break;
case WeaponThrowAction.Launcher:
Style = reader.ReadObject<LauncherStyle>();
break;
case WeaponThrowAction.Mine:
Style = reader.ReadObject<MineStyle>();
break;
}
break;
}
// Read additional settings.
reader.Position = offset + 468;
AmmunitionOverride = reader.ReadBoolean(BooleanCoding.Dword);
Ammunition = reader.ReadInt32();
Unknown3 = reader.ReadInt32();
WeaponSprite = reader.ReadInt32();
NameLong = reader.ReadString(StringCoding.Int32CharCount);
Name = reader.ReadString(StringCoding.Int32CharCount);
GridImageFile = reader.ReadString(StringCoding.Int32CharCount);
GfxDirectoryFile = reader.ReadString(StringCoding.Int32CharCount);
SpriteNames = reader.ReadStrings(5, StringCoding.Int32CharCount);
DelayOverride = reader.ReadBoolean(BooleanCoding.Dword);
Delay = reader.ReadInt32();
UseLibrary = reader.ReadBoolean();
if (UseLibrary)
{
LibraryName = reader.ReadString(StringCoding.Int32CharCount);
LibraryWeaponName = reader.ReadString(StringCoding.Int32CharCount);
}
AimSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
AimSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
AimSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
PickSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
PickSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
PickSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
FireSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
FireSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
FireSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
AimSpriteOverride = reader.ReadBoolean();
PickSpriteOverride = reader.ReadBoolean();
FireSpriteOverride = reader.ReadBoolean();
if (Version == WeaponVersion.Version_0_8_0)
{
Utility = reader.ReadBoolean();
}
} }
// Read additional settings.
reader.Position = offset + 468;
AmmunitionOverride = reader.ReadBoolean(BooleanCoding.Dword);
Ammunition = reader.ReadInt32();
Unknown3 = reader.ReadInt32();
WeaponSprite = reader.ReadInt32();
NameLong = reader.ReadString(StringCoding.Int32CharCount);
Name = reader.ReadString(StringCoding.Int32CharCount);
GridImageFile = reader.ReadString(StringCoding.Int32CharCount);
GfxDirectoryFile = reader.ReadString(StringCoding.Int32CharCount);
SpriteNames = reader.ReadStrings(5, StringCoding.Int32CharCount);
DelayOverride = reader.ReadBoolean(BooleanCoding.Dword);
Delay = reader.ReadInt32();
UseLibrary = reader.ReadBoolean();
if (UseLibrary)
{
LibraryName = reader.ReadString(StringCoding.Int32CharCount);
LibraryWeaponName = reader.ReadString(StringCoding.Int32CharCount);
}
AimSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
AimSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
AimSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
PickSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
PickSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
PickSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
FireSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
FireSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
FireSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
AimSpriteOverride = reader.ReadBoolean();
PickSpriteOverride = reader.ReadBoolean();
FireSpriteOverride = reader.ReadBoolean();
if (Version == WeaponVersion.Version_0_8_0)
Utility = reader.ReadBoolean();
} }
/// <summary> /// <summary>
@ -284,111 +280,104 @@ namespace Syroot.Worms.Armageddon.ProjectX
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
public void Save(Stream stream) public void Save(Stream stream)
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
// Write the header.
long offset = writer.Position;
writer.WriteEnum(Version, true);
writer.Write(Checksum);
// Write the general settings.
writer.Write(TableRow);
writer.Write(Remembered, BooleanCoding.Dword);
writer.Write(UsableInCavern, BooleanCoding.Dword);
writer.Write(Shots);
writer.Write(ShotEndsTurn, BooleanCoding.Dword);
writer.Write(RetreatTime);
writer.Write(Unknown1);
writer.Write(CrateChance);
writer.Write(CrateCount);
writer.Write(Unknown2);
// Write the activation and the corresponding weapon settings.
writer.WriteEnum(Activation, true);
switch (Activation)
{ {
// Write the header. case WeaponActivation.Airstrike:
long offset = writer.Position; writer.Write(AirstrikeSubtype);
writer.WriteEnum(Version, true); writer.WriteObject(Style);
writer.Write(Checksum); break;
case WeaponActivation.Crosshair:
// Write the general settings. writer.Write(NotUsed);
writer.Write(TableRow); writer.WriteEnum(CrosshairAction, true);
writer.Write(Remembered, BooleanCoding.Dword); if (CrosshairAction != WeaponCrosshairAction.None)
writer.Write(UsableInCavern, BooleanCoding.Dword);
writer.Write(Shots);
writer.Write(ShotEndsTurn, BooleanCoding.Dword);
writer.Write(RetreatTime);
writer.Write(Unknown1);
writer.Write(CrateChance);
writer.Write(CrateCount);
writer.Write(Unknown2);
// Write the activation and the corresponding weapon settings.
writer.WriteEnum(Activation, true);
switch (Activation)
{
case WeaponActivation.Airstrike:
writer.Write(AirstrikeSubtype);
writer.WriteObject(Style); writer.WriteObject(Style);
break; break;
case WeaponActivation.Crosshair: case WeaponActivation.Spacebar:
writer.Write(NotUsed); writer.WriteEnum(SpacebarAction, true);
writer.WriteEnum(CrosshairAction, true); switch (SpacebarAction)
if (CrosshairAction != WeaponCrosshairAction.None) {
{ case WeaponSpacebarAction.Armageddon:
case WeaponSpacebarAction.BaseballBat:
case WeaponSpacebarAction.BattleAxe:
case WeaponSpacebarAction.Blowtorch:
case WeaponSpacebarAction.Dragonball:
case WeaponSpacebarAction.Firepunch:
case WeaponSpacebarAction.Jetpack:
case WeaponSpacebarAction.Kamikaze:
case WeaponSpacebarAction.NinjaRope:
case WeaponSpacebarAction.NuclearTest:
case WeaponSpacebarAction.Parachute:
case WeaponSpacebarAction.PneumaticDrill:
case WeaponSpacebarAction.Prod:
case WeaponSpacebarAction.SuicideBomber:
writer.WriteObject(Style); writer.WriteObject(Style);
} break;
break; }
case WeaponActivation.Spacebar: break;
writer.WriteEnum(SpacebarAction, true); case WeaponActivation.Throw:
switch (SpacebarAction) writer.Write(ThrowHerdCount);
{ writer.WriteEnum(ThrowAction, true);
case WeaponSpacebarAction.Armageddon: if (ThrowAction != WeaponThrowAction.None)
case WeaponSpacebarAction.BaseballBat: writer.WriteObject(Style);
case WeaponSpacebarAction.BattleAxe: break;
case WeaponSpacebarAction.Blowtorch:
case WeaponSpacebarAction.Dragonball:
case WeaponSpacebarAction.Firepunch:
case WeaponSpacebarAction.Jetpack:
case WeaponSpacebarAction.Kamikaze:
case WeaponSpacebarAction.NinjaRope:
case WeaponSpacebarAction.NuclearTest:
case WeaponSpacebarAction.Parachute:
case WeaponSpacebarAction.PneumaticDrill:
case WeaponSpacebarAction.Prod:
case WeaponSpacebarAction.SuicideBomber:
writer.WriteObject(Style);
break;
}
break;
case WeaponActivation.Throw:
writer.Write(ThrowHerdCount);
writer.WriteEnum(ThrowAction, true);
if (ThrowAction != WeaponThrowAction.None)
{
writer.WriteObject(Style);
}
break;
}
// Write additional settings.
writer.Position = offset + 468;
writer.Write(AmmunitionOverride, BooleanCoding.Dword);
writer.Write(Ammunition);
writer.Write(Unknown3);
writer.Write(WeaponSprite);
writer.Write(NameLong, StringCoding.Int32CharCount);
writer.Write(Name, StringCoding.Int32CharCount);
writer.Write(GridImageFile, StringCoding.Int32CharCount);
writer.Write(GfxDirectoryFile, StringCoding.Int32CharCount);
writer.Write(SpriteNames, StringCoding.Int32CharCount);
writer.Write(DelayOverride, BooleanCoding.Dword);
writer.Write(Delay);
writer.Write(UseLibrary);
if (UseLibrary)
{
writer.Write(LibraryName, StringCoding.Int32CharCount);
writer.Write(LibraryWeaponName, StringCoding.Int32CharCount);
}
writer.Write(AimSpriteEven, StringCoding.Int32CharCount);
writer.Write(AimSpriteUphill, StringCoding.Int32CharCount);
writer.Write(AimSpriteDownhill, StringCoding.Int32CharCount);
writer.Write(PickSpriteEven, StringCoding.Int32CharCount);
writer.Write(PickSpriteUphill, StringCoding.Int32CharCount);
writer.Write(PickSpriteDownhill, StringCoding.Int32CharCount);
writer.Write(FireSpriteEven, StringCoding.Int32CharCount);
writer.Write(FireSpriteUphill, StringCoding.Int32CharCount);
writer.Write(FireSpriteDownhill, StringCoding.Int32CharCount);
writer.Write(AimSpriteOverride);
writer.Write(PickSpriteOverride);
writer.Write(FireSpriteOverride);
if (Version == WeaponVersion.Version_0_8_0)
{
writer.Write(Utility);
}
} }
// Write additional settings.
writer.Position = offset + 468;
writer.Write(AmmunitionOverride, BooleanCoding.Dword);
writer.Write(Ammunition);
writer.Write(Unknown3);
writer.Write(WeaponSprite);
writer.Write(NameLong, StringCoding.Int32CharCount);
writer.Write(Name, StringCoding.Int32CharCount);
writer.Write(GridImageFile, StringCoding.Int32CharCount);
writer.Write(GfxDirectoryFile, StringCoding.Int32CharCount);
writer.Write(SpriteNames, StringCoding.Int32CharCount);
writer.Write(DelayOverride, BooleanCoding.Dword);
writer.Write(Delay);
writer.Write(UseLibrary);
if (UseLibrary)
{
writer.Write(LibraryName, StringCoding.Int32CharCount);
writer.Write(LibraryWeaponName, StringCoding.Int32CharCount);
}
writer.Write(AimSpriteEven, StringCoding.Int32CharCount);
writer.Write(AimSpriteUphill, StringCoding.Int32CharCount);
writer.Write(AimSpriteDownhill, StringCoding.Int32CharCount);
writer.Write(PickSpriteEven, StringCoding.Int32CharCount);
writer.Write(PickSpriteUphill, StringCoding.Int32CharCount);
writer.Write(PickSpriteDownhill, StringCoding.Int32CharCount);
writer.Write(FireSpriteEven, StringCoding.Int32CharCount);
writer.Write(FireSpriteUphill, StringCoding.Int32CharCount);
writer.Write(FireSpriteDownhill, StringCoding.Int32CharCount);
writer.Write(AimSpriteOverride);
writer.Write(PickSpriteOverride);
writer.Write(FireSpriteOverride);
if (Version == WeaponVersion.Version_0_8_0)
writer.Write(Utility);
} }
} }

View File

@ -16,28 +16,20 @@ namespace Syroot.Worms.Armageddon
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GeneratedMap"/> class. /// Initializes a new instance of the <see cref="GeneratedMap"/> class.
/// </summary> /// </summary>
public GeneratedMap() public GeneratedMap() { }
{
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GeneratedMap"/> class, loading the data from the given /// Initializes a new instance of the <see cref="GeneratedMap"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public GeneratedMap(Stream stream) public GeneratedMap(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GeneratedMap"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="GeneratedMap"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public GeneratedMap(string fileName) public GeneratedMap(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -54,10 +46,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{ Settings = reader.ReadStruct<MapGeneratorSettings>();
Settings = reader.ReadStruct<MapGeneratorSettings>();
}
} }
/// <summary> /// <summary>
@ -66,10 +56,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -78,10 +66,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{ writer.WriteStruct(Settings);
writer.WriteStruct(Settings);
}
} }
/// <summary> /// <summary>
@ -90,10 +76,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
} }
} }

View File

@ -28,19 +28,13 @@ namespace Syroot.Worms.Armageddon
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public LandData(Stream stream) public LandData(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public LandData(string fileName) public LandData(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -102,31 +96,30 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadInt32() != _signature)
throw new InvalidDataException("Invalid LND file signature.");
int fileSize = reader.ReadInt32();
// Read the data. // Read the header.
Size = reader.ReadStruct<Size>(); if (reader.ReadInt32() != _signature)
TopBorder = reader.ReadBoolean(BooleanCoding.Dword); throw new InvalidDataException("Invalid LND file signature.");
WaterHeight = reader.ReadInt32(); int fileSize = reader.ReadInt32();
Unknown = reader.ReadInt32();
// Read the possible object coordinate array. // Read the data.
ObjectLocations = reader.ReadStructs<Point>(reader.ReadInt32()); Size = reader.ReadStruct<Size>();
TopBorder = reader.ReadBoolean(BooleanCoding.Dword);
WaterHeight = reader.ReadInt32();
Unknown = reader.ReadInt32();
// Read the image data. // Read the possible object coordinate array.
Foreground = reader.Load<Img>(); ObjectLocations = reader.ReadStructs<Point>(reader.ReadInt32());
CollisionMask = reader.Load<Img>();
Background = reader.Load<Img>();
// Read the file paths. // Read the image data.
LandTexturePath = reader.ReadString(StringCoding.ByteCharCount); Foreground = reader.Load<Img>();
WaterDirPath = reader.ReadString(StringCoding.ByteCharCount); CollisionMask = reader.Load<Img>();
} Background = reader.Load<Img>();
// Read the file paths.
LandTexturePath = reader.ReadString(StringCoding.ByteCharCount);
WaterDirPath = reader.ReadString(StringCoding.ByteCharCount);
} }
/// <summary> /// <summary>
@ -135,8 +128,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream); Load(stream);
} }
/// <summary> /// <summary>
@ -145,33 +138,32 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{
// Write the header.
writer.Write(_signature);
uint fileSizeOffset = writer.ReserveOffset();
// Write the data. // Write the header.
writer.WriteStruct(Size); writer.Write(_signature);
writer.Write(TopBorder, BooleanCoding.Dword); uint fileSizeOffset = writer.ReserveOffset();
writer.Write(WaterHeight);
writer.Write(Unknown);
// Write the possible object coordinate array. // Write the data.
writer.Write(ObjectLocations.Length); writer.WriteStruct(Size);
writer.WriteStructs(ObjectLocations); writer.Write(TopBorder, BooleanCoding.Dword);
writer.Write(WaterHeight);
writer.Write(Unknown);
// Write the image data. // Write the possible object coordinate array.
Foreground.Save(writer.BaseStream); writer.Write(ObjectLocations.Length);
CollisionMask.Save(writer.BaseStream); writer.WriteStructs(ObjectLocations);
Background.Save(writer.BaseStream);
// Write the file paths. // Write the image data.
writer.Write(LandTexturePath, StringCoding.ByteCharCount); Foreground.Save(writer.BaseStream);
writer.Write(WaterDirPath, StringCoding.ByteCharCount); CollisionMask.Save(writer.BaseStream);
Background.Save(writer.BaseStream);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position); // Write the file paths.
} writer.Write(LandTexturePath, StringCoding.ByteCharCount);
writer.Write(WaterDirPath, StringCoding.ByteCharCount);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position);
} }
/// <summary> /// <summary>
@ -180,8 +172,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
Save(stream); Save(stream);
} }
} }
} }

View File

@ -99,19 +99,13 @@ namespace Syroot.Worms.Armageddon
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public Scheme(Stream stream) public Scheme(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public Scheme(string fileName) public Scheme(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -229,16 +223,11 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public byte MineDelay public byte MineDelay
{ {
get get => _mineDelay;
{
return _mineDelay;
}
set set
{ {
if (value == 4 || value > 0x7F) if (value == 4 || value > 0x7F)
{
throw new ArgumentException("Mine delay must be between 0-127 and not be 4.", nameof(value)); throw new ArgumentException("Mine delay must be between 0-127 and not be 4.", nameof(value));
}
_mineDelay = value; _mineDelay = value;
} }
} }
@ -270,16 +259,11 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public byte TurnTime public byte TurnTime
{ {
get get => _turnTime;
{
return _turnTime;
}
set set
{ {
if (value > 0x7F) if (value > 0x7F)
{
throw new ArgumentException("Turn time must be between 0-127.", nameof(value)); throw new ArgumentException("Turn time must be between 0-127.", nameof(value));
}
_turnTime = value; _turnTime = value;
} }
} }
@ -295,16 +279,11 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public byte RoundTimeMinutes public byte RoundTimeMinutes
{ {
get get => _roundTimeMinutes;
{
return _roundTimeMinutes;
}
set set
{ {
if (value > 0x7F) if (value > 0x7F)
{
throw new ArgumentException("Round time must be between 0-127 minutes.", nameof(value)); throw new ArgumentException("Round time must be between 0-127 minutes.", nameof(value));
}
_roundTimeMinutes = value; _roundTimeMinutes = value;
} }
} }
@ -315,16 +294,11 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public byte RoundTimeSeconds public byte RoundTimeSeconds
{ {
get get => _roundTimeSeconds;
{
return _roundTimeSeconds;
}
set set
{ {
if (value > 0x80) if (value > 0x80)
{
throw new ArgumentException("Round time must be between 0-128 seconds.", nameof(value)); throw new ArgumentException("Round time must be between 0-128 seconds.", nameof(value));
}
_roundTimeSeconds = value; _roundTimeSeconds = value;
} }
} }
@ -334,16 +308,11 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public byte NumberOfWins public byte NumberOfWins
{ {
get get => _numberOfWins;
{
return _numberOfWins;
}
set set
{ {
if (value == 0) if (value == 0)
{
throw new ArgumentException("Number of wins must not be 0.", nameof(value)); throw new ArgumentException("Number of wins must not be 0.", nameof(value));
}
_numberOfWins = value; _numberOfWins = value;
} }
} }
@ -486,10 +455,7 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public sbyte RwGravity public sbyte RwGravity
{ {
get get => _rwGravity;
{
return _rwGravity;
}
set set
{ {
if (value != 0) if (value != 0)
@ -507,10 +473,7 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public sbyte RwGravityConstBlackHole public sbyte RwGravityConstBlackHole
{ {
get get => _rwGravityConstBlackHole;
{
return _rwGravityConstBlackHole;
}
set set
{ {
if (value != 0) if (value != 0)
@ -529,10 +492,7 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public sbyte RwGravityPropBlackHole public sbyte RwGravityPropBlackHole
{ {
get get => _rwGravityPropBlackHole;
{
return _rwGravityPropBlackHole;
}
set set
{ {
if (value != 0) if (value != 0)
@ -550,16 +510,11 @@ namespace Syroot.Worms.Armageddon
/// </summary> /// </summary>
public byte RwKaosMod public byte RwKaosMod
{ {
get get => _rwKaosMod;
{
return _rwKaosMod;
}
set set
{ {
if (value > 0xF) if (value > 0xF)
{
throw new ArgumentException("Kaos mod must not be greater than 15."); throw new ArgumentException("Kaos mod must not be greater than 15.");
}
_rwKaosMod = value; _rwKaosMod = value;
} }
} }
@ -650,66 +605,61 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadString(_signature.Length) != _signature)
{
throw new InvalidDataException("Invalid WSC file signature.");
}
Version = reader.ReadEnum<SchemeVersion>(true);
// Read the options. // Read the header.
HotSeatDelay = reader.Read1Byte(); if (reader.ReadString(_signature.Length) != _signature)
RetreatTime = reader.Read1Byte(); throw new InvalidDataException("Invalid WSC file signature.");
RetreatTimeRope = reader.Read1Byte(); Version = reader.ReadEnum<SchemeVersion>(true);
ShowRoundTime = reader.ReadBoolean();
AutomaticReplays = reader.ReadBoolean();
FallDamage = (SchemeFallDamage)(reader.ReadByte() * 50 % 0x100 * 2);
ArtilleryMode = reader.ReadBoolean();
SchemeEditor = reader.ReadEnum<SchemeEditor>(false);
StockpilingMode = reader.ReadEnum<SchemeStockpiling>(true);
WormSelectMode = reader.ReadEnum<SchemeWormSelect>(true);
SuddenDeathEvent = reader.ReadEnum<SchemeSuddenDeathEvent>(true);
WaterRiseRate = (SchemeWaterRise)(Math.Pow(reader.ReadByte(), 2) * 5 % 0x100);
WeaponCrateProbability = reader.ReadSByte();
DonorCards = reader.ReadBoolean();
HealthCrateProbability = reader.ReadSByte();
HealthCrateEnergy = reader.Read1Byte();
UtilityCrateProbability = reader.ReadSByte();
LoadObjectTypesAndCount(reader);
LoadMineDelayConfig(reader);
DudMines = reader.ReadBoolean();
ManualWormPlacement = reader.ReadBoolean();
WormEnergy = reader.Read1Byte();
LoadTurnTimeConfig(reader);
LoadRoundTimeConfig(reader);
NumberOfWins = (byte)Math.Max(1, reader.ReadByte());
Blood = reader.ReadBoolean();
AquaSheep = reader.ReadBoolean();
SheepHeaven = reader.ReadBoolean();
GodWorms = reader.ReadBoolean();
IndestructibleLand = reader.ReadBoolean();
UpgradedGrenade = reader.ReadBoolean();
UpgradedShotgun = reader.ReadBoolean();
UpgradedCluster = reader.ReadBoolean();
UpgradedLongbow = reader.ReadBoolean();
EnableTeamWeapons = reader.ReadBoolean();
EnableSuperWeapons = reader.ReadBoolean();
// Read the weapon settings. Old versions do not store super weapon settings. // Read the options.
Weapons = new SchemeWeaponSetting[64]; HotSeatDelay = reader.Read1Byte();
int weaponCount = GetWeaponCount(); RetreatTime = reader.Read1Byte();
for (int i = 0; i < weaponCount; i++) RetreatTimeRope = reader.Read1Byte();
{ ShowRoundTime = reader.ReadBoolean();
Weapons[i] = reader.ReadStruct<SchemeWeaponSetting>(); AutomaticReplays = reader.ReadBoolean();
} FallDamage = (SchemeFallDamage)(reader.ReadByte() * 50 % 0x100 * 2);
ArtilleryMode = reader.ReadBoolean();
SchemeEditor = reader.ReadEnum<SchemeEditor>(false);
StockpilingMode = reader.ReadEnum<SchemeStockpiling>(true);
WormSelectMode = reader.ReadEnum<SchemeWormSelect>(true);
SuddenDeathEvent = reader.ReadEnum<SchemeSuddenDeathEvent>(true);
WaterRiseRate = (SchemeWaterRise)(Math.Pow(reader.ReadByte(), 2) * 5 % 0x100);
WeaponCrateProbability = reader.ReadSByte();
DonorCards = reader.ReadBoolean();
HealthCrateProbability = reader.ReadSByte();
HealthCrateEnergy = reader.Read1Byte();
UtilityCrateProbability = reader.ReadSByte();
LoadObjectTypesAndCount(reader);
LoadMineDelayConfig(reader);
DudMines = reader.ReadBoolean();
ManualWormPlacement = reader.ReadBoolean();
WormEnergy = reader.Read1Byte();
LoadTurnTimeConfig(reader);
LoadRoundTimeConfig(reader);
NumberOfWins = (byte)Math.Max(1, reader.ReadByte());
Blood = reader.ReadBoolean();
AquaSheep = reader.ReadBoolean();
SheepHeaven = reader.ReadBoolean();
GodWorms = reader.ReadBoolean();
IndestructibleLand = reader.ReadBoolean();
UpgradedGrenade = reader.ReadBoolean();
UpgradedShotgun = reader.ReadBoolean();
UpgradedCluster = reader.ReadBoolean();
UpgradedLongbow = reader.ReadBoolean();
EnableTeamWeapons = reader.ReadBoolean();
EnableSuperWeapons = reader.ReadBoolean();
// Ignore possible unknown WWP trash at the end of the file. // Read the weapon settings. Old versions do not store super weapon settings.
Weapons = new SchemeWeaponSetting[64];
int weaponCount = GetWeaponCount();
for (int i = 0; i < weaponCount; i++)
Weapons[i] = reader.ReadStruct<SchemeWeaponSetting>();
// Parse the RubberWorm settings. // Ignore possible unknown WWP trash at the end of the file.
LoadRubberWormSettings();
} // Parse the RubberWorm settings.
LoadRubberWormSettings();
} }
/// <summary> /// <summary>
@ -718,20 +668,15 @@ namespace Syroot.Worms.Armageddon
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
/// Saves the data into the given <paramref name="stream"/>. /// Saves the data into the given <paramref name="stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
public void Save(Stream stream) public void Save(Stream stream) => Save(stream, SchemeSaveFormat.ExtendedWithObjectCount);
{
Save(stream, SchemeSaveFormat.ExtendedWithObjectCount);
}
/// <summary> /// <summary>
/// Saves the data into the given <paramref name="stream"/> with the specified <paramref name="format"/>. /// Saves the data into the given <paramref name="stream"/> with the specified <paramref name="format"/>.
@ -740,72 +685,64 @@ namespace Syroot.Worms.Armageddon
/// <param name="format">The <see cref="SchemeSaveFormat"/> to respect when storing the settings.</param> /// <param name="format">The <see cref="SchemeSaveFormat"/> to respect when storing the settings.</param>
public void Save(Stream stream, SchemeSaveFormat format) public void Save(Stream stream, SchemeSaveFormat format)
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII)) using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII);
{
// Write the header.
writer.Write(_signature, StringCoding.Raw);
writer.Write((byte)Version);
// Write the options. // Write the header.
writer.Write(HotSeatDelay); writer.Write(_signature, StringCoding.Raw);
writer.Write(RetreatTime); writer.Write((byte)Version);
writer.Write(RetreatTimeRope);
writer.Write(ShowRoundTime);
writer.Write(AutomaticReplays);
writer.Write((byte)((int)FallDamage / 4 * 41 % 0x80));
writer.Write(ArtilleryMode);
writer.WriteEnum(SchemeEditor, false);
writer.WriteEnum(StockpilingMode, true);
writer.WriteEnum(WormSelectMode, true);
writer.WriteEnum(SuddenDeathEvent, true);
writer.Write(_mapWaterRiseToRaw[(byte)WaterRiseRate]);
writer.Write(WeaponCrateProbability);
writer.Write(DonorCards);
writer.Write(HealthCrateProbability);
writer.Write(HealthCrateEnergy);
writer.Write(UtilityCrateProbability);
SaveObjectTypesAndCount(writer, format);
SaveMineDelayConfig(writer);
writer.Write(DudMines);
writer.Write(ManualWormPlacement);
writer.Write(WormEnergy);
SaveTurnTimeConfig(writer);
SaveRoundTimeConfig(writer);
writer.Write(NumberOfWins);
writer.Write(Blood);
writer.Write(AquaSheep);
writer.Write(SheepHeaven);
writer.Write(GodWorms);
writer.Write(IndestructibleLand);
writer.Write(UpgradedGrenade);
writer.Write(UpgradedShotgun);
writer.Write(UpgradedCluster);
writer.Write(UpgradedLongbow);
writer.Write(EnableTeamWeapons);
writer.Write(EnableSuperWeapons);
// Transfer the RubberWorm settings to unused weapon configuration. // Write the options.
SaveRubberWormSettings(); writer.Write(HotSeatDelay);
writer.Write(RetreatTime);
writer.Write(RetreatTimeRope);
writer.Write(ShowRoundTime);
writer.Write(AutomaticReplays);
writer.Write((byte)((int)FallDamage / 4 * 41 % 0x80));
writer.Write(ArtilleryMode);
writer.WriteEnum(SchemeEditor, false);
writer.WriteEnum(StockpilingMode, true);
writer.WriteEnum(WormSelectMode, true);
writer.WriteEnum(SuddenDeathEvent, true);
writer.Write(_mapWaterRiseToRaw[(byte)WaterRiseRate]);
writer.Write(WeaponCrateProbability);
writer.Write(DonorCards);
writer.Write(HealthCrateProbability);
writer.Write(HealthCrateEnergy);
writer.Write(UtilityCrateProbability);
SaveObjectTypesAndCount(writer, format);
SaveMineDelayConfig(writer);
writer.Write(DudMines);
writer.Write(ManualWormPlacement);
writer.Write(WormEnergy);
SaveTurnTimeConfig(writer);
SaveRoundTimeConfig(writer);
writer.Write(NumberOfWins);
writer.Write(Blood);
writer.Write(AquaSheep);
writer.Write(SheepHeaven);
writer.Write(GodWorms);
writer.Write(IndestructibleLand);
writer.Write(UpgradedGrenade);
writer.Write(UpgradedShotgun);
writer.Write(UpgradedCluster);
writer.Write(UpgradedLongbow);
writer.Write(EnableTeamWeapons);
writer.Write(EnableSuperWeapons);
// Write the weapon settings. Old versions do not store super weapon settings. // Transfer the RubberWorm settings to unused weapon configuration.
int weaponCount = GetWeaponCount(); SaveRubberWormSettings();
foreach (SchemeWeaponSetting weapon in Weapons)
{
writer.WriteStruct(weapon);
}
// Ignore possible unknown WWP trash at the end of the file. // Write the weapon settings. Old versions do not store super weapon settings.
} int weaponCount = GetWeaponCount();
foreach (SchemeWeaponSetting weapon in Weapons)
writer.WriteStruct(weapon);
} }
/// <summary> /// <summary>
/// Saves the data in the given file. /// Saves the data in the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName) => Save(fileName, SchemeSaveFormat.ExtendedWithObjectCount);
{
Save(fileName, SchemeSaveFormat.ExtendedWithObjectCount);
}
/// <summary> /// <summary>
/// Saves the data in the given file with the specified <paramref name="format"/>. /// Saves the data in the given file with the specified <paramref name="format"/>.
@ -814,10 +751,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="format">The <see cref="SchemeSaveFormat"/> to respect when storing the settings.</param> /// <param name="format">The <see cref="SchemeSaveFormat"/> to respect when storing the settings.</param>
public void Save(string fileName, SchemeSaveFormat format) public void Save(string fileName, SchemeSaveFormat format)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream, format);
Save(stream, format);
}
} }
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
@ -942,13 +877,9 @@ namespace Syroot.Worms.Armageddon
if (mailStrikeProb.GetBit(7)) if (mailStrikeProb.GetBit(7))
{ {
if (mailStrikeProb.GetBit(6)) if (mailStrikeProb.GetBit(6))
{
RwGravityPropBlackHole = mailStrikeProb.DecodeSByte(6); RwGravityPropBlackHole = mailStrikeProb.DecodeSByte(6);
}
else else
{
RwGravityConstBlackHole = mailStrikeProb.DecodeSByte(6); RwGravityConstBlackHole = mailStrikeProb.DecodeSByte(6);
}
} }
else else
{ {
@ -1019,37 +950,25 @@ namespace Syroot.Worms.Armageddon
private void SaveMineDelayConfig(BinaryStream writer) private void SaveMineDelayConfig(BinaryStream writer)
{ {
if (MineDelayRandom) if (MineDelayRandom)
{
writer.Write((byte)4); writer.Write((byte)4);
}
else else
{
writer.Write(MineDelay); writer.Write(MineDelay);
}
} }
private void SaveTurnTimeConfig(BinaryStream writer) private void SaveTurnTimeConfig(BinaryStream writer)
{ {
if (TurnTimeInfinite) if (TurnTimeInfinite)
{
writer.Write((byte)0xFF); writer.Write((byte)0xFF);
}
else else
{
writer.Write(TurnTime); writer.Write(TurnTime);
}
} }
private void SaveRoundTimeConfig(BinaryStream writer) private void SaveRoundTimeConfig(BinaryStream writer)
{ {
if (RoundTimeSeconds > 0) if (RoundTimeSeconds > 0)
{
writer.Write((byte)(0xFF - (RoundTimeSeconds - 1))); writer.Write((byte)(0xFF - (RoundTimeSeconds - 1)));
}
else else
{
writer.Write(RoundTimeMinutes); writer.Write(RoundTimeMinutes);
}
} }
private void SaveRubberWormSettings() private void SaveRubberWormSettings()

View File

@ -1,23 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AssemblyName>Syroot.Worms.Armageddon</AssemblyName> <AssemblyName>Syroot.Worms.Armageddon</AssemblyName>
<Authors>Syroot</Authors> <Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright> <Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library for loading and modifying files of Team17's Worms Armageddon.</Description> <Description>.NET library for loading and modifying files of Team17's Worms Armageddon.</Description>
<GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile> <GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl> <PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl>
<PackageId>Syroot.Worms.Armageddon</PackageId> <PackageId>Syroot.Worms.Armageddon</PackageId>
<PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl> <PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes> <PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<PackageTags>worms;team17</PackageTags> <PackageTags>worms;team17</PackageTags>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl> <RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks> <TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>2.0.0-alpha1</Version> <Version>2.0.0-alpha1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -196,59 +196,58 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
Name = reader.ReadString(17);
WormNames = reader.ReadStrings(8, 17);
CpuLevel = reader.Read1Byte();
SoundBankName = reader.ReadString(0x20);
SoundBankLocation = reader.Read1Byte();
FanfareName = reader.ReadString(0x20);
UseCustomFanfare = reader.Read1Byte();
GraveSprite = reader.ReadSByte();
if (GraveSprite < 0)
{ {
Name = reader.ReadString(17); GraveFileName = reader.ReadString(0x20);
WormNames = reader.ReadStrings(8, 17); Grave = new RawBitmap()
CpuLevel = reader.Read1Byte();
SoundBankName = reader.ReadString(0x20);
SoundBankLocation = reader.Read1Byte();
FanfareName = reader.ReadString(0x20);
UseCustomFanfare = reader.Read1Byte();
GraveSprite = reader.ReadSByte();
if (GraveSprite < 0)
{
GraveFileName = reader.ReadString(0x20);
Grave = new RawBitmap()
{
BitsPerPixel = 8,
Size = new Size(24, 32),
Palette = reader.ReadStructs<Color>(256),
Data = reader.ReadBytes(24 * 32)
};
}
TeamWeapon = reader.ReadEnum<TeamWeapon>(true);
GamesLost = reader.ReadInt32();
DeathmatchesLost = reader.ReadInt32();
GamesWon = reader.ReadInt32();
DeathmatchesWon = reader.ReadInt32();
GamesDrawn = reader.ReadInt32();
DeathmatchesDrawn = reader.ReadInt32();
Kills = reader.ReadInt32();
DeathmatchKills = reader.ReadInt32();
Deaths = reader.ReadInt32();
DeathmatchDeaths = reader.ReadInt32();
MissionStatuses = reader.ReadStructs<TeamMissionStatus>(_missionCount);
FlagFileName = reader.ReadString(0x20);
Flag = new RawBitmap()
{ {
BitsPerPixel = 8, BitsPerPixel = 8,
Size = new Size(20, 17), Size = new Size(24, 32),
Palette = reader.ReadStructs<Color>(256), Palette = reader.ReadStructs<Color>(256),
Data = reader.ReadBytes(20 * 17) Data = reader.ReadBytes(24 * 32)
}; };
DeathmatchRank = reader.Read1Byte();
TrainingMissionTimes = reader.ReadInt32s(_trainingMissionCount);
Unknown1 = reader.ReadInt32s(10);
TrainingMissionMedals = reader.ReadBytes(_trainingMissionCount);
Unknown2 = reader.ReadBytes(10);
Unknown3 = reader.ReadInt32s(7);
Unknown4 = reader.Read1Byte();
} }
TeamWeapon = reader.ReadEnum<TeamWeapon>(true);
GamesLost = reader.ReadInt32();
DeathmatchesLost = reader.ReadInt32();
GamesWon = reader.ReadInt32();
DeathmatchesWon = reader.ReadInt32();
GamesDrawn = reader.ReadInt32();
DeathmatchesDrawn = reader.ReadInt32();
Kills = reader.ReadInt32();
DeathmatchKills = reader.ReadInt32();
Deaths = reader.ReadInt32();
DeathmatchDeaths = reader.ReadInt32();
MissionStatuses = reader.ReadStructs<TeamMissionStatus>(_missionCount);
FlagFileName = reader.ReadString(0x20);
Flag = new RawBitmap()
{
BitsPerPixel = 8,
Size = new Size(20, 17),
Palette = reader.ReadStructs<Color>(256),
Data = reader.ReadBytes(20 * 17)
};
DeathmatchRank = reader.Read1Byte();
TrainingMissionTimes = reader.ReadInt32s(_trainingMissionCount);
Unknown1 = reader.ReadInt32s(10);
TrainingMissionMedals = reader.ReadBytes(_trainingMissionCount);
Unknown2 = reader.ReadBytes(10);
Unknown3 = reader.ReadInt32s(7);
Unknown4 = reader.Read1Byte();
} }
/// <summary> /// <summary>
@ -257,49 +256,48 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
public void Save(Stream stream) public void Save(Stream stream)
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
writer.WriteString(Name, 17);
writer.WriteStrings(WormNames, 17);
writer.Write(CpuLevel);
writer.WriteString(SoundBankName, 0x20);
writer.Write(SoundBankLocation);
writer.WriteString(FanfareName, 0x20);
writer.Write(UseCustomFanfare);
writer.Write(GraveSprite);
if (GraveSprite < 0)
{ {
writer.WriteString(Name, 17); writer.WriteString(GraveFileName, 0x20);
writer.WriteStrings(WormNames, 17); writer.WriteStructs(Grave.Palette);
writer.Write(CpuLevel); writer.Write(Grave.Data);
writer.WriteString(SoundBankName, 0x20);
writer.Write(SoundBankLocation);
writer.WriteString(FanfareName, 0x20);
writer.Write(UseCustomFanfare);
writer.Write(GraveSprite);
if (GraveSprite < 0)
{
writer.WriteString(GraveFileName, 0x20);
writer.WriteStructs(Grave.Palette);
writer.Write(Grave.Data);
}
writer.WriteEnum(TeamWeapon, true);
writer.Write(GamesLost);
writer.Write(DeathmatchesLost);
writer.Write(GamesWon);
writer.Write(DeathmatchesWon);
writer.Write(GamesDrawn);
writer.Write(DeathmatchesDrawn);
writer.Write(Kills);
writer.Write(DeathmatchKills);
writer.Write(Deaths);
writer.Write(DeathmatchDeaths);
writer.WriteStructs(MissionStatuses);
writer.WriteString(FlagFileName, 0x20);
writer.WriteStructs(Flag.Palette);
writer.Write(Flag.Data);
writer.Write(DeathmatchRank);
writer.Write(TrainingMissionTimes);
writer.Write(Unknown1);
writer.Write(TrainingMissionMedals);
writer.Write(Unknown2);
writer.Write(Unknown3);
writer.Write(Unknown4);
} }
writer.WriteEnum(TeamWeapon, true);
writer.Write(GamesLost);
writer.Write(DeathmatchesLost);
writer.Write(GamesWon);
writer.Write(DeathmatchesWon);
writer.Write(GamesDrawn);
writer.Write(DeathmatchesDrawn);
writer.Write(Kills);
writer.Write(DeathmatchKills);
writer.Write(Deaths);
writer.Write(DeathmatchDeaths);
writer.WriteStructs(MissionStatuses);
writer.WriteString(FlagFileName, 0x20);
writer.WriteStructs(Flag.Palette);
writer.Write(Flag.Data);
writer.Write(DeathmatchRank);
writer.Write(TrainingMissionTimes);
writer.Write(Unknown1);
writer.Write(TrainingMissionMedals);
writer.Write(Unknown2);
writer.Write(Unknown3);
writer.Write(Unknown4);
} }
} }

View File

@ -22,29 +22,20 @@ namespace Syroot.Worms.Armageddon
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class. /// Initializes a new instance of the <see cref="TeamContainer"/> class.
/// </summary> /// </summary>
public TeamContainer() public TeamContainer() => Teams = new List<Team>();
{
Teams = new List<Team>();
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given /// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public TeamContainer(Stream stream) public TeamContainer(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public TeamContainer(string fileName) public TeamContainer(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -76,23 +67,20 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadString(StringCoding.ZeroTerminated) != _signature)
{
throw new InvalidDataException("Invalid WGT file signature.");
}
Version = reader.Read1Byte(); // Really version?
// Read global settings. // Read the header.
byte teamCount = reader.Read1Byte(); if (reader.ReadString(StringCoding.ZeroTerminated) != _signature)
UnlockedFeatures = reader.ReadEnum<UnlockedFeatures>(false); throw new InvalidDataException("Invalid WGT file signature.");
Unknown = reader.Read1Byte(); Version = reader.Read1Byte(); // Really version?
// Read the teams. // Read global settings.
Teams = new List<Team>(reader.Load<Team>(teamCount)); byte teamCount = reader.Read1Byte();
} UnlockedFeatures = reader.ReadEnum<UnlockedFeatures>(false);
Unknown = reader.Read1Byte();
// Read the teams.
Teams = new List<Team>(reader.Load<Team>(teamCount));
} }
/// <summary> /// <summary>
@ -101,10 +89,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -113,23 +99,20 @@ namespace Syroot.Worms.Armageddon
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{
// Write the header.
writer.Write(_signature, StringCoding.ZeroTerminated);
writer.Write(Version);
// Write global settings. // Write the header.
writer.Write((byte)Teams.Count); writer.Write(_signature, StringCoding.ZeroTerminated);
writer.WriteEnum(UnlockedFeatures, false); writer.Write(Version);
writer.Write(Unknown);
// Write the teams. // Write global settings.
foreach (Team team in Teams) writer.Write((byte)Teams.Count);
{ writer.WriteEnum(UnlockedFeatures, false);
team.Save(writer.BaseStream); writer.Write(Unknown);
}
} // Write the teams.
foreach (Team team in Teams)
team.Save(writer.BaseStream);
} }
/// <summary> /// <summary>
@ -138,10 +121,8 @@ namespace Syroot.Worms.Armageddon
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
} }

View File

@ -3,13 +3,14 @@ using System.Drawing;
using System.IO; using System.IO;
using Syroot.BinaryData; using Syroot.BinaryData;
using Syroot.Worms.Core; using Syroot.Worms.Core;
using Syroot.Worms.Core.IO;
namespace Syroot.Worms.Mgame namespace Syroot.Worms.Mgame
{ {
/// <summary> /// <summary>
/// Represents an IGD image container. /// Represents an IGD image container.
/// </summary> /// </summary>
public class Igd public class Igd : ILoadableFile
{ {
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
@ -18,20 +19,14 @@ namespace Syroot.Worms.Mgame
/// <paramref name="fileName"/>. /// <paramref name="fileName"/>.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public Igd(string fileName) public Igd(string fileName) => Load(fileName);
{
Load(fileName);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Igd"/> class, loading data from the given /// Initializes a new instance of the <see cref="Igd"/> class, loading data from the given
/// <paramref name="stream"/>. /// <paramref name="stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public Igd(Stream stream) public Igd(Stream stream) => Load(stream);
{
Load(stream);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -50,8 +45,8 @@ namespace Syroot.Worms.Mgame
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream); Load(stream);
} }
/// <summary> /// <summary>

View File

@ -23,10 +23,7 @@ namespace Syroot.Worms.Mgame
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
/// <param name="palette">The color palette which is indexed by the image data.</param> /// <param name="palette">The color palette which is indexed by the image data.</param>
public Ksf(string fileName, Palette palette) public Ksf(string fileName, Palette palette) => Load(fileName, palette);
{
Load(fileName, palette);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Ksf"/> class, loading data from the given /// Initializes a new instance of the <see cref="Ksf"/> class, loading data from the given
@ -34,10 +31,7 @@ namespace Syroot.Worms.Mgame
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
/// <param name="palette">The color palette which is indexed by the image data.</param> /// <param name="palette">The color palette which is indexed by the image data.</param>
public Ksf(Stream stream, Palette palette) public Ksf(Stream stream, Palette palette) => Load(stream, palette);
{
Load(stream, palette);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -56,8 +50,8 @@ namespace Syroot.Worms.Mgame
/// <param name="palette">The color palette which is indexed by the image data.</param> /// <param name="palette">The color palette which is indexed by the image data.</param>
public void Load(string fileName, Palette palette) public void Load(string fileName, Palette palette)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream, palette); Load(stream, palette);
} }
/// <summary> /// <summary>
@ -69,7 +63,7 @@ namespace Syroot.Worms.Mgame
public void Load(Stream stream, Palette palette) public void Load(Stream stream, Palette palette)
{ {
int imageCount = stream.ReadInt32(); // Includes terminator. int imageCount = stream.ReadInt32(); // Includes terminator.
int dataSize = stream.ReadInt32(); _ = stream.ReadInt32(); // data size
// Read image headers. Terminating image is of 0 size and data offset at end of data block. // Read image headers. Terminating image is of 0 size and data offset at end of data block.
KsfImage[] images = new KsfImage[imageCount]; KsfImage[] images = new KsfImage[imageCount];

View File

@ -2,13 +2,14 @@
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using Syroot.BinaryData; using Syroot.BinaryData;
using Syroot.Worms.Core.IO;
namespace Syroot.Worms.Mgame namespace Syroot.Worms.Mgame
{ {
/// <summary> /// <summary>
/// Represents an LPD layout description file used in Worms World Party Aqua. /// Represents an LPD layout description file used in Worms World Party Aqua.
/// </summary> /// </summary>
public class Lpd public class Lpd : ILoadableFile
{ {
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
@ -17,20 +18,14 @@ namespace Syroot.Worms.Mgame
/// <paramref name="fileName"/>. /// <paramref name="fileName"/>.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public Lpd(string fileName) public Lpd(string fileName) => Load(fileName);
{
Load(fileName);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Lpd"/> class, loading data from the given /// Initializes a new instance of the <see cref="Lpd"/> class, loading data from the given
/// <paramref name="stream"/>. /// <paramref name="stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public Lpd(Stream stream) public Lpd(Stream stream) => Load(stream);
{
Load(stream);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -47,8 +42,8 @@ namespace Syroot.Worms.Mgame
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream); Load(stream);
} }
/// <summary> /// <summary>

View File

@ -19,17 +19,12 @@ namespace Syroot.Worms.Mgame
{ {
// ---- FIELDS ------------------------------------------------------------------------------------------------- // ---- FIELDS -------------------------------------------------------------------------------------------------
private static int _numBytesTransferred = 0;
private static int _field_4 = 4;
private static int _field_8 = 0; private static int _field_8 = 0;
private static int _field_C = 0;
private static int _field_10 = 0; private static int _field_10 = 0;
private static readonly int[] _bufferDwords = new int[512]; private static readonly int[] _bufferDwords = new int[512];
private static byte[] _buffer = new byte[256]; private static readonly byte[] _buffer = new byte[256];
private static int _bufferCursor = 0; private static int _bufferCursor = 0;
// ---- METHODS (INTERNAL) ------------------------------------------------------------------------------------- // ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
@ -102,7 +97,6 @@ namespace Syroot.Worms.Mgame
compressor.Shift(shiftValue1, 8); compressor.Shift(shiftValue1, 8);
compressor.Shift(idxDword - 18, 8); compressor.Shift(idxDword - 18, 8);
field_10 = _field_10; field_10 = _field_10;
++_field_C;
_field_10 = idxDword - 3 + field_10; _field_10 = idxDword - 3 + field_10;
} }
else else
@ -110,7 +104,6 @@ namespace Syroot.Worms.Mgame
compressor.Shift(idxDword - 2, 4); compressor.Shift(idxDword - 2, 4);
compressor.Shift(shiftValue1 - 1, 8); compressor.Shift(shiftValue1 - 1, 8);
field_8 = _field_8; field_8 = _field_8;
++_field_4;
_field_8 = idxDword - 2 + field_8; _field_8 = idxDword - 2 + field_8;
} }
idx += idxDword; idx += idxDword;
@ -209,7 +202,6 @@ namespace Syroot.Worms.Mgame
bufferCursor = _bufferCursor; bufferCursor = _bufferCursor;
if (bufferCursor != 0) if (bufferCursor != 0)
{ {
_numBytesTransferred += bufferCursor;
compressor.Compress(false); compressor.Compress(false);
compressor.Shift(_bufferCursor - 1, 8); compressor.Shift(_bufferCursor - 1, 8);
for (i = 0; i < _bufferCursor; ++i) for (i = 0; i < _bufferCursor; ++i)

View File

@ -54,8 +54,8 @@ namespace Syroot.Worms.Mgame
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream); Load(stream);
} }
/// <summary> /// <summary>

View File

@ -37,29 +37,27 @@ namespace Syroot.Worms.Mgame
/// <returns>The encrypted text.</returns> /// <returns>The encrypted text.</returns>
public static string Encrypt(string data, uint key) public static string Encrypt(string data, uint key)
{ {
using (MemoryStream inStream = new MemoryStream(new byte[_bufferSize])) using MemoryStream inStream = new MemoryStream(new byte[_bufferSize]);
// Write input into a buffer. Required to loop over the input password end.
inStream.WriteString(data, StringCoding.ZeroTerminated, Encodings.Korean);
inStream.Position = 0;
using MemoryStream outStream = new MemoryStream(new byte[_bufferSize]);
// Encrypt the contents character by character.
while (inStream.Position < data.Length)
{ {
// Write input into a buffer. Required to loop over the input password end. // Begin a new dword value at every 7th index.
inStream.WriteString(data, StringCoding.ZeroTerminated, Encodings.Korean); uint dword = TransformDword(inStream.ReadUInt32() + key, true);
inStream.Position = 0; for (int j = 0; j < 7; j++)
using (MemoryStream outStream = new MemoryStream(new byte[_bufferSize]))
{ {
// Encrypt the contents character by character. outStream.WriteByte((byte)_encryptCharacters[(int)(dword % _encryptCharacters.Length)]);
while (inStream.Position < data.Length) dword /= (uint)_encryptCharacters.Length;
{
// Begin a new dword value at every 7th index.
uint dword = TransformDword(inStream.ReadUInt32() + key, true);
for (int j = 0; j < 7; j++)
{
outStream.WriteByte((byte)_encryptCharacters[(int)(dword % _encryptCharacters.Length)]);
dword /= (uint)_encryptCharacters.Length;
}
}
// Return the encrypted password as a zero-terminated ASCII string.
outStream.Position = 0;
return outStream.ReadString(StringCoding.ZeroTerminated, Encodings.Korean);
} }
} }
// Return the encrypted password as a zero-terminated ASCII string.
outStream.Position = 0;
return outStream.ReadString(StringCoding.ZeroTerminated, Encodings.Korean);
} }
/// <summary> /// <summary>
@ -70,32 +68,30 @@ namespace Syroot.Worms.Mgame
/// <returns>The decrypted text.</returns> /// <returns>The decrypted text.</returns>
public static string Decrypt(string data, uint key) public static string Decrypt(string data, uint key)
{ {
using (MemoryStream inStream = new MemoryStream(new byte[_bufferSize])) using MemoryStream inStream = new MemoryStream(new byte[_bufferSize]);
// Write input into a buffer. Required to loop over the input password end.
inStream.WriteString(data, StringCoding.Raw, Encodings.Korean);
inStream.Position = 0;
using MemoryStream outStream = new MemoryStream(new byte[_bufferSize]);
// Decrypt the contents character by character.
for (int i = 0; i < data.Length; i += 7)
{ {
// Write input into a buffer. Required to loop over the input password end. uint dword = 0;
inStream.WriteString(data, StringCoding.Raw, Encodings.Korean); for (int j = 0; j < 7; j++)
inStream.Position = 0;
using (MemoryStream outStream = new MemoryStream(new byte[_bufferSize]))
{ {
// Decrypt the contents character by character. byte b = inStream.Read1Byte();
for (int i = 0; i < data.Length; i += 7) uint op1 = (uint)Math.Pow(_encryptCharacters.Length, j);
{ uint op2 = (uint)(b < '0' || b > '9' ? b - '7' : b - '0');
uint dword = 0; dword += op1 * op2;
for (int j = 0; j < 7; j++)
{
byte b = inStream.Read1Byte();
uint op1 = (uint)Math.Pow(_encryptCharacters.Length, j);
uint op2 = (uint)(b < '0' || b > '9' ? b - '7' : b - '0');
dword += op1 * op2;
}
// Finalize a new dword value at every 7th index.
outStream.WriteUInt32(TransformDword(dword, false) - key);
}
// Return the decrypted password as a zero-terminated ASCII string.
outStream.Position = 0;
return outStream.ReadString(StringCoding.ZeroTerminated, Encodings.Korean);
} }
// Finalize a new dword value at every 7th index.
outStream.WriteUInt32(TransformDword(dword, false) - key);
} }
// Return the decrypted password as a zero-terminated ASCII string.
outStream.Position = 0;
return outStream.ReadString(StringCoding.ZeroTerminated, Encodings.Korean);
} }
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------

View File

@ -1,23 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AssemblyName>Syroot.Worms.Mgame</AssemblyName> <AssemblyName>Syroot.Worms.Mgame</AssemblyName>
<Authors>Syroot</Authors> <Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright> <Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library for loading and modifying files of Mgame Worms clients.</Description> <Description>.NET library for loading and modifying files of Mgame Worms clients.</Description>
<GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile> <GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl> <PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl>
<PackageId>Syroot.Worms.Mgame</PackageId> <PackageId>Syroot.Worms.Mgame</PackageId>
<PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl> <PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes> <PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<PackageTags>worms;team17</PackageTags> <PackageTags>worms;team17</PackageTags>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl> <RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks> <TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>2.0.0-alpha1</Version> <Version>2.0.0-alpha1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -91,30 +91,29 @@ namespace Syroot.Worms.WorldParty
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadInt32() != _signature)
throw new InvalidDataException("Invalid LND file signature.");
int fileSize = reader.ReadInt32();
// Read the data. // Read the header.
Size = reader.ReadStruct<Size>(); if (reader.ReadInt32() != _signature)
TopBorder = reader.ReadBoolean(BooleanCoding.Dword); throw new InvalidDataException("Invalid LND file signature.");
WaterHeight = reader.ReadInt32(); int fileSize = reader.ReadInt32();
// Read the possible object coordinate array. // Read the data.
ObjectLocations = reader.ReadStructs<Point>(reader.ReadInt32()); Size = reader.ReadStruct<Size>();
TopBorder = reader.ReadBoolean(BooleanCoding.Dword);
WaterHeight = reader.ReadInt32();
// Read the image data. // Read the possible object coordinate array.
Foreground = new Img(stream, true); ObjectLocations = reader.ReadStructs<Point>(reader.ReadInt32());
CollisionMask = new Img(stream, true);
Background = new Img(stream, true);
// Read the file paths. // Read the image data.
LandTexturePath = reader.ReadString(StringCoding.ByteCharCount); Foreground = new Img(stream, true);
WaterDirPath = reader.ReadString(StringCoding.ByteCharCount); CollisionMask = new Img(stream, true);
} Background = new Img(stream, true);
// Read the file paths.
LandTexturePath = reader.ReadString(StringCoding.ByteCharCount);
WaterDirPath = reader.ReadString(StringCoding.ByteCharCount);
} }
/// <summary> /// <summary>
@ -123,8 +122,8 @@ namespace Syroot.Worms.WorldParty
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream); Load(stream);
} }
/// <summary> /// <summary>
@ -133,32 +132,31 @@ namespace Syroot.Worms.WorldParty
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{
// Write the header.
writer.Write(_signature);
uint fileSizeOffset = writer.ReserveOffset();
// Write the data. // Write the header.
writer.WriteStruct(Size); writer.Write(_signature);
writer.Write(TopBorder, BooleanCoding.Dword); uint fileSizeOffset = writer.ReserveOffset();
writer.Write(WaterHeight);
// Write the possible object coordinate array. // Write the data.
writer.Write(ObjectLocations.Length); writer.WriteStruct(Size);
writer.WriteStructs(ObjectLocations); writer.Write(TopBorder, BooleanCoding.Dword);
writer.Write(WaterHeight);
// Write the image data. // Write the possible object coordinate array.
Foreground.Save(writer.BaseStream, false, true); writer.Write(ObjectLocations.Length);
CollisionMask.Save(writer.BaseStream, false, true); writer.WriteStructs(ObjectLocations);
Background.Save(writer.BaseStream, false, true);
// Write the file paths. // Write the image data.
writer.Write(LandTexturePath, StringCoding.ByteCharCount); Foreground.Save(writer.BaseStream, false, true);
writer.Write(WaterDirPath, StringCoding.ByteCharCount); CollisionMask.Save(writer.BaseStream, false, true);
Background.Save(writer.BaseStream, false, true);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position); // Write the file paths.
} writer.Write(LandTexturePath, StringCoding.ByteCharCount);
writer.Write(WaterDirPath, StringCoding.ByteCharCount);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position);
} }
/// <summary> /// <summary>
@ -167,8 +165,8 @@ namespace Syroot.Worms.WorldParty
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
Save(stream); Save(stream);
} }
} }
} }

View File

@ -1,23 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AssemblyName>Syroot.Worms.WorldParty</AssemblyName> <AssemblyName>Syroot.Worms.WorldParty</AssemblyName>
<Authors>Syroot</Authors> <Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright> <Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library for loading and modifying files of Team17's Worms World Party.</Description> <Description>.NET library for loading and modifying files of Team17's Worms World Party.</Description>
<GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile> <GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl> <PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl>
<PackageId>Syroot.Worms.WorldParty</PackageId> <PackageId>Syroot.Worms.WorldParty</PackageId>
<PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl> <PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes> <PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<PackageTags>worms;team17</PackageTags> <PackageTags>worms;team17</PackageTags>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl> <RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks> <TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>2.0.0-alpha1</Version> <Version>2.0.0-alpha1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -195,58 +195,57 @@ namespace Syroot.Worms.WorldParty
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
Name = reader.ReadString(17);
WormNames = reader.ReadStrings(8, 17);
CpuLevel = reader.Read1Byte();
SoundBankName = reader.ReadString(0x20);
SoundBankLocation = reader.Read1Byte();
FanfareName = reader.ReadString(0x20);
UseCustomFanfare = reader.Read1Byte();
GraveSprite = reader.ReadSByte();
if (GraveSprite < 0)
{ {
Name = reader.ReadString(17); GraveFileName = reader.ReadString(0x20);
WormNames = reader.ReadStrings(8, 17); Grave = new RawBitmap()
CpuLevel = reader.Read1Byte();
SoundBankName = reader.ReadString(0x20);
SoundBankLocation = reader.Read1Byte();
FanfareName = reader.ReadString(0x20);
UseCustomFanfare = reader.Read1Byte();
GraveSprite = reader.ReadSByte();
if (GraveSprite < 0)
{
GraveFileName = reader.ReadString(0x20);
Grave = new RawBitmap()
{
BitsPerPixel = 8,
Size = new Size(24, 32),
Palette = reader.ReadStructs<Color>(256),
Data = reader.ReadBytes(24 * 32)
};
}
TeamWeapon = reader.ReadEnum<TeamWeapon>(true);
GamesLost = reader.ReadInt32();
DeathmatchesLost = reader.ReadInt32();
GamesWon = reader.ReadInt32();
DeathmatchesWon = reader.ReadInt32();
GamesDrawn = reader.ReadInt32();
DeathmatchesDrawn = reader.ReadInt32();
Kills = reader.ReadInt32();
DeathmatchKills = reader.ReadInt32();
Deaths = reader.ReadInt32();
DeathmatchDeaths = reader.ReadInt32();
MissionStatuses = reader.ReadStructs<TeamMissionStatus>(_missionCount);
FlagFileName = reader.ReadString(0x20);
Flag = new RawBitmap()
{ {
BitsPerPixel = 8, BitsPerPixel = 8,
Size = new Size(20, 17), Size = new Size(24, 32),
Palette = reader.ReadStructs<Color>(256), Palette = reader.ReadStructs<Color>(256),
Data = reader.ReadBytes(20 * 17) Data = reader.ReadBytes(24 * 32)
}; };
Unknown1 = reader.Read1Byte();
DeathmatchRank = reader.Read1Byte();
TrainingMissionTimes = reader.ReadInt32s(_trainingMissionCount);
WeaponPoints = reader.ReadBytes(46);
Fort = reader.Read1Byte();
Unknown2 = reader.ReadInt32s(7);
} }
TeamWeapon = reader.ReadEnum<TeamWeapon>(true);
GamesLost = reader.ReadInt32();
DeathmatchesLost = reader.ReadInt32();
GamesWon = reader.ReadInt32();
DeathmatchesWon = reader.ReadInt32();
GamesDrawn = reader.ReadInt32();
DeathmatchesDrawn = reader.ReadInt32();
Kills = reader.ReadInt32();
DeathmatchKills = reader.ReadInt32();
Deaths = reader.ReadInt32();
DeathmatchDeaths = reader.ReadInt32();
MissionStatuses = reader.ReadStructs<TeamMissionStatus>(_missionCount);
FlagFileName = reader.ReadString(0x20);
Flag = new RawBitmap()
{
BitsPerPixel = 8,
Size = new Size(20, 17),
Palette = reader.ReadStructs<Color>(256),
Data = reader.ReadBytes(20 * 17)
};
Unknown1 = reader.Read1Byte();
DeathmatchRank = reader.Read1Byte();
TrainingMissionTimes = reader.ReadInt32s(_trainingMissionCount);
WeaponPoints = reader.ReadBytes(46);
Fort = reader.Read1Byte();
Unknown2 = reader.ReadInt32s(7);
} }
/// <summary> /// <summary>
@ -255,49 +254,48 @@ namespace Syroot.Worms.WorldParty
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
public void Save(Stream stream) public void Save(Stream stream)
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
writer.WriteString(Name, 17);
writer.WriteStrings(WormNames, 17);
writer.Write(CpuLevel);
writer.WriteString(SoundBankName, 0x20);
writer.Write(SoundBankLocation);
writer.WriteString(FanfareName, 0x20);
writer.Write(UseCustomFanfare);
writer.Write(GraveSprite);
if (GraveSprite < 0)
{ {
writer.WriteString(Name, 17); writer.WriteString(GraveFileName, 0x20);
writer.WriteStrings(WormNames, 17); writer.WriteStructs(Grave.Palette);
writer.Write(CpuLevel); writer.WriteStructs(Grave.Data);
writer.WriteString(SoundBankName, 0x20);
writer.Write(SoundBankLocation);
writer.WriteString(FanfareName, 0x20);
writer.Write(UseCustomFanfare);
writer.Write(GraveSprite);
if (GraveSprite < 0)
{
writer.WriteString(GraveFileName, 0x20);
writer.WriteStructs(Grave.Palette);
writer.WriteStructs(Grave.Data);
}
writer.WriteEnum(TeamWeapon, true);
writer.Write(GamesLost);
writer.Write(DeathmatchesLost);
writer.Write(GamesWon);
writer.Write(DeathmatchesWon);
writer.Write(GamesDrawn);
writer.Write(DeathmatchesDrawn);
writer.Write(Kills);
writer.Write(DeathmatchKills);
writer.Write(Deaths);
writer.Write(DeathmatchDeaths);
writer.WriteStructs(MissionStatuses);
writer.WriteString(FlagFileName, 0x20);
writer.WriteStructs(Flag.Palette);
writer.WriteStructs(Flag.Data);
writer.Write(Unknown1);
writer.Write(DeathmatchRank);
writer.Write(TrainingMissionTimes);
writer.Write(UnknownTrainingMissionTime);
writer.WriteStructs(WeaponPoints);
writer.Write(Fort);
writer.Write(Unknown2);
} }
writer.WriteEnum(TeamWeapon, true);
writer.Write(GamesLost);
writer.Write(DeathmatchesLost);
writer.Write(GamesWon);
writer.Write(DeathmatchesWon);
writer.Write(GamesDrawn);
writer.Write(DeathmatchesDrawn);
writer.Write(Kills);
writer.Write(DeathmatchKills);
writer.Write(Deaths);
writer.Write(DeathmatchDeaths);
writer.WriteStructs(MissionStatuses);
writer.WriteString(FlagFileName, 0x20);
writer.WriteStructs(Flag.Palette);
writer.WriteStructs(Flag.Data);
writer.Write(Unknown1);
writer.Write(DeathmatchRank);
writer.Write(TrainingMissionTimes);
writer.Write(UnknownTrainingMissionTime);
writer.WriteStructs(WeaponPoints);
writer.Write(Fort);
writer.Write(Unknown2);
} }
} }

View File

@ -21,29 +21,20 @@ namespace Syroot.Worms.WorldParty
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class. /// Initializes a new instance of the <see cref="TeamContainer"/> class.
/// </summary> /// </summary>
public TeamContainer() public TeamContainer() => Teams = new List<Team>();
{
Teams = new List<Team>();
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given /// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public TeamContainer(Stream stream) public TeamContainer(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public TeamContainer(string fileName) public TeamContainer(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -80,24 +71,21 @@ namespace Syroot.Worms.WorldParty
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadString(StringCoding.ZeroTerminated) != _signature)
{
throw new InvalidDataException("Invalid WWP file signature.");
}
Version = reader.Read1Byte(); // Really version?
// Read global settings. // Read the header.
byte teamCount = reader.Read1Byte(); if (reader.ReadString(StringCoding.ZeroTerminated) != _signature)
Unknown1 = reader.Read1Byte(); throw new InvalidDataException("Invalid WWP file signature.");
Unknown2 = reader.Read1Byte(); Version = reader.Read1Byte(); // Really version?
Unknown3 = reader.ReadBytes(840);
// Read the teams. // Read global settings.
Teams = new List<Team>(reader.Load<Team>(teamCount)); byte teamCount = reader.Read1Byte();
} Unknown1 = reader.Read1Byte();
Unknown2 = reader.Read1Byte();
Unknown3 = reader.ReadBytes(840);
// Read the teams.
Teams = new List<Team>(reader.Load<Team>(teamCount));
} }
/// <summary> /// <summary>
@ -106,10 +94,8 @@ namespace Syroot.Worms.WorldParty
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -118,24 +104,21 @@ namespace Syroot.Worms.WorldParty
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{
// Write the header.
writer.Write(_signature, StringCoding.ZeroTerminated);
writer.Write(Version);
// Write global settings. // Write the header.
writer.Write((byte)Teams.Count); writer.Write(_signature, StringCoding.ZeroTerminated);
writer.Write(Unknown1); writer.Write(Version);
writer.Write(Unknown2);
writer.WriteStructs(Unknown3);
// Write the teams. // Write global settings.
foreach (Team team in Teams) writer.Write((byte)Teams.Count);
{ writer.Write(Unknown1);
team.Save(writer.BaseStream); writer.Write(Unknown2);
} writer.WriteStructs(Unknown3);
}
// Write the teams.
foreach (Team team in Teams)
team.Save(writer.BaseStream);
} }
/// <summary> /// <summary>
@ -144,10 +127,8 @@ namespace Syroot.Worms.WorldParty
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
} }
} }

View File

@ -96,31 +96,30 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadInt32() != _signature)
throw new InvalidDataException("Invalid LND file signature.");
int fileSize = reader.ReadInt32();
// Read the data. // Read the header.
Size = reader.ReadStruct<Size>(); if (reader.ReadInt32() != _signature)
TopBorder = reader.ReadBoolean(BooleanCoding.Dword); throw new InvalidDataException("Invalid LND file signature.");
int fileSize = reader.ReadInt32();
// Read the possible object coordinate array. // Read the data.
ObjectLocations = reader.ReadStructs<Point>(reader.ReadInt32()); Size = reader.ReadStruct<Size>();
Unknown = reader.ReadInt32(); TopBorder = reader.ReadBoolean(BooleanCoding.Dword);
// Read the image data. // Read the possible object coordinate array.
Foreground = reader.Load<Img>(); ObjectLocations = reader.ReadStructs<Point>(reader.ReadInt32());
CollisionMask = reader.Load<Img>(); Unknown = reader.ReadInt32();
Background = reader.Load<Img>();
UnknownImage = reader.Load<Img>();
// Read the file paths. // Read the image data.
LandTexturePath = reader.ReadString(StringCoding.ByteCharCount); Foreground = reader.Load<Img>();
WaterDirPath = reader.ReadString(StringCoding.ByteCharCount); CollisionMask = reader.Load<Img>();
} Background = reader.Load<Img>();
UnknownImage = reader.Load<Img>();
// Read the file paths.
LandTexturePath = reader.ReadString(StringCoding.ByteCharCount);
WaterDirPath = reader.ReadString(StringCoding.ByteCharCount);
} }
/// <summary> /// <summary>
@ -129,8 +128,8 @@ namespace Syroot.Worms.Worms2
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream); Load(stream);
} }
/// <summary> /// <summary>
@ -139,33 +138,32 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{
// Write the header.
writer.Write(_signature);
uint fileSizeOffset = writer.ReserveOffset();
// Write the data. // Write the header.
writer.WriteStruct(Size); writer.Write(_signature);
writer.Write(TopBorder, BooleanCoding.Dword); uint fileSizeOffset = writer.ReserveOffset();
// Write the possible object coordinate array. // Write the data.
writer.Write(ObjectLocations.Length); writer.WriteStruct(Size);
writer.WriteStructs(ObjectLocations); writer.Write(TopBorder, BooleanCoding.Dword);
writer.Write(Unknown);
// Write the image data. // Write the possible object coordinate array.
Foreground.Save(writer.BaseStream); writer.Write(ObjectLocations.Length);
CollisionMask.Save(writer.BaseStream); writer.WriteStructs(ObjectLocations);
Background.Save(writer.BaseStream); writer.Write(Unknown);
UnknownImage.Save(writer.BaseStream);
// Write the file paths. // Write the image data.
writer.Write(LandTexturePath, StringCoding.ByteCharCount); Foreground.Save(writer.BaseStream);
writer.Write(WaterDirPath, StringCoding.ByteCharCount); CollisionMask.Save(writer.BaseStream);
Background.Save(writer.BaseStream);
UnknownImage.Save(writer.BaseStream);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position); // Write the file paths.
} writer.Write(LandTexturePath, StringCoding.ByteCharCount);
writer.Write(WaterDirPath, StringCoding.ByteCharCount);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position);
} }
/// <summary> /// <summary>
@ -174,8 +172,8 @@ namespace Syroot.Worms.Worms2
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
Save(stream); Save(stream);
} }
} }
} }

View File

@ -26,7 +26,6 @@ namespace Syroot.Worms.Worms2
Manual = 3 Manual = 3
} }
/// <summary> /// <summary>
/// Represents the weapons in the game. /// Represents the weapons in the game.
/// </summary> /// </summary>
@ -136,7 +135,7 @@ namespace Syroot.Worms.Worms2
/// The Napalm Strike weapon. /// The Napalm Strike weapon.
/// </summary> /// </summary>
NapalmStrike, NapalmStrike,
/// <summary> /// <summary>
/// The Mail Strike weapon. /// The Mail Strike weapon.
/// </summary> /// </summary>

View File

@ -20,28 +20,20 @@ namespace Syroot.Worms.Worms2
/// <summary> /// <summary>
/// Initializs a new instance of the <see cref="SchemeOptions"/> class. /// Initializs a new instance of the <see cref="SchemeOptions"/> class.
/// </summary> /// </summary>
public SchemeOptions() public SchemeOptions() { }
{
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SchemeOptions"/> class, loading the data from the given /// Initializes a new instance of the <see cref="SchemeOptions"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public SchemeOptions(Stream stream) public SchemeOptions(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SchemeOptions"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="SchemeOptions"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public SchemeOptions(string fileName) public SchemeOptions(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -221,52 +213,47 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadString(_signature.Length) != _signature)
{
throw new InvalidDataException("Invalid OPT file signature.");
}
// Read the options. // Read the header.
RoundTime = reader.ReadInt32(); if (reader.ReadString(_signature.Length) != _signature)
TurnTime = reader.ReadInt32(); throw new InvalidDataException("Invalid OPT file signature.");
RetreatTime = reader.ReadInt32();
RetreatTimeRope = reader.ReadInt32(); // Read the options.
ObjectCount = reader.ReadInt32(); RoundTime = reader.ReadInt32();
MineDelay = reader.ReadInt32(); TurnTime = reader.ReadInt32();
DudMines = reader.ReadBoolean(BooleanCoding.Dword); RetreatTime = reader.ReadInt32();
WindPower = reader.ReadInt32(); RetreatTimeRope = reader.ReadInt32();
Friction = reader.ReadInt32(); ObjectCount = reader.ReadInt32();
ReplayRequiredKills = reader.ReadInt32(); MineDelay = reader.ReadInt32();
ReplayRequiredDamage = reader.ReadInt32(); DudMines = reader.ReadBoolean(BooleanCoding.Dword);
AutomaticReplays = reader.ReadBoolean(BooleanCoding.Dword); WindPower = reader.ReadInt32();
FallDamage = reader.ReadInt32(); Friction = reader.ReadInt32();
RopeSwings = reader.ReadInt32(); ReplayRequiredKills = reader.ReadInt32();
ShowRoundTime = reader.ReadBoolean(BooleanCoding.Dword); ReplayRequiredDamage = reader.ReadInt32();
WaterRiseRate = reader.ReadInt32(); AutomaticReplays = reader.ReadBoolean(BooleanCoding.Dword);
SuddenDeathHealthDrop = reader.ReadBoolean(BooleanCoding.Dword); FallDamage = reader.ReadInt32();
IndestructibleBorder = reader.ReadBoolean(BooleanCoding.Dword); RopeSwings = reader.ReadInt32();
RestrictGirders = reader.ReadBoolean(BooleanCoding.Dword); ShowRoundTime = reader.ReadBoolean(BooleanCoding.Dword);
WormSelectMode = reader.ReadEnum<SchemeWormSelect>(true); WaterRiseRate = reader.ReadInt32();
ExtendedChatControls = reader.ReadBoolean(BooleanCoding.Dword); SuddenDeathHealthDrop = reader.ReadBoolean(BooleanCoding.Dword);
HotSeatDelay = reader.ReadInt32(); IndestructibleBorder = reader.ReadBoolean(BooleanCoding.Dword);
EnableStockpiling = reader.ReadBoolean(BooleanCoding.Dword); RestrictGirders = reader.ReadBoolean(BooleanCoding.Dword);
CrateProbability = reader.ReadInt32(); WormSelectMode = reader.ReadEnum<SchemeWormSelect>(true);
CrateIntelligence = reader.ReadInt32(); ExtendedChatControls = reader.ReadBoolean(BooleanCoding.Dword);
HealthCrateEnergy = reader.ReadInt32(); HotSeatDelay = reader.ReadInt32();
BoobyTraps = reader.ReadBoolean(BooleanCoding.Dword); EnableStockpiling = reader.ReadBoolean(BooleanCoding.Dword);
EnableSuperWeapons = reader.ReadBoolean(BooleanCoding.Dword); CrateProbability = reader.ReadInt32();
WormEnergy = reader.ReadInt32(); CrateIntelligence = reader.ReadInt32();
ArtilleryMode = reader.ReadBoolean(BooleanCoding.Dword); HealthCrateEnergy = reader.ReadInt32();
SuddenDeathDisableWormSelect = reader.ReadBoolean(BooleanCoding.Dword); BoobyTraps = reader.ReadBoolean(BooleanCoding.Dword);
// The following option does not exist in all schemes. EnableSuperWeapons = reader.ReadBoolean(BooleanCoding.Dword);
if (!reader.EndOfStream) WormEnergy = reader.ReadInt32();
{ ArtilleryMode = reader.ReadBoolean(BooleanCoding.Dword);
UseOilDrums = reader.ReadBoolean(BooleanCoding.Dword); SuddenDeathDisableWormSelect = reader.ReadBoolean(BooleanCoding.Dword);
} // The following option does not exist in all schemes.
} if (!reader.EndOfStream)
UseOilDrums = reader.ReadBoolean(BooleanCoding.Dword);
} }
/// <summary> /// <summary>
@ -275,10 +262,8 @@ namespace Syroot.Worms.Worms2
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -287,45 +272,44 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{
// Write the header.
writer.Write(_signature, StringCoding.Raw);
// Write the options. // Write the header.
writer.Write(RoundTime); writer.Write(_signature, StringCoding.Raw);
writer.Write(TurnTime);
writer.Write(RetreatTime); // Write the options.
writer.Write(RetreatTimeRope); writer.Write(RoundTime);
writer.Write(ObjectCount); writer.Write(TurnTime);
writer.Write(MineDelay); writer.Write(RetreatTime);
writer.Write(DudMines, BooleanCoding.Dword); writer.Write(RetreatTimeRope);
writer.Write(WindPower); writer.Write(ObjectCount);
writer.Write(Friction); writer.Write(MineDelay);
writer.Write(ReplayRequiredKills); writer.Write(DudMines, BooleanCoding.Dword);
writer.Write(ReplayRequiredDamage); writer.Write(WindPower);
writer.Write(AutomaticReplays, BooleanCoding.Dword); writer.Write(Friction);
writer.Write(FallDamage); writer.Write(ReplayRequiredKills);
writer.Write(RopeSwings); writer.Write(ReplayRequiredDamage);
writer.Write(ShowRoundTime, BooleanCoding.Dword); writer.Write(AutomaticReplays, BooleanCoding.Dword);
writer.Write(WaterRiseRate); writer.Write(FallDamage);
writer.Write(SuddenDeathHealthDrop, BooleanCoding.Dword); writer.Write(RopeSwings);
writer.Write(IndestructibleBorder, BooleanCoding.Dword); writer.Write(ShowRoundTime, BooleanCoding.Dword);
writer.Write(RestrictGirders, BooleanCoding.Dword); writer.Write(WaterRiseRate);
writer.WriteEnum(WormSelectMode, true); writer.Write(SuddenDeathHealthDrop, BooleanCoding.Dword);
writer.Write(ExtendedChatControls, BooleanCoding.Dword); writer.Write(IndestructibleBorder, BooleanCoding.Dword);
writer.Write(HotSeatDelay); writer.Write(RestrictGirders, BooleanCoding.Dword);
writer.Write(EnableStockpiling, BooleanCoding.Dword); writer.WriteEnum(WormSelectMode, true);
writer.Write(CrateProbability); writer.Write(ExtendedChatControls, BooleanCoding.Dword);
writer.Write(CrateIntelligence); writer.Write(HotSeatDelay);
writer.Write(HealthCrateEnergy); writer.Write(EnableStockpiling, BooleanCoding.Dword);
writer.Write(BoobyTraps, BooleanCoding.Dword); writer.Write(CrateProbability);
writer.Write(EnableSuperWeapons, BooleanCoding.Dword); writer.Write(CrateIntelligence);
writer.Write(WormEnergy); writer.Write(HealthCrateEnergy);
writer.Write(ArtilleryMode, BooleanCoding.Dword); writer.Write(BoobyTraps, BooleanCoding.Dword);
writer.Write(SuddenDeathDisableWormSelect, BooleanCoding.Dword); writer.Write(EnableSuperWeapons, BooleanCoding.Dword);
writer.Write(UseOilDrums, BooleanCoding.Dword); writer.Write(WormEnergy);
} writer.Write(ArtilleryMode, BooleanCoding.Dword);
writer.Write(SuddenDeathDisableWormSelect, BooleanCoding.Dword);
writer.Write(UseOilDrums, BooleanCoding.Dword);
} }
/// <summary> /// <summary>
@ -334,10 +318,8 @@ namespace Syroot.Worms.Worms2
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
} }
} }

View File

@ -22,29 +22,20 @@ namespace Syroot.Worms.Worms2
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SchemeWeapons"/> class. /// Initializes a new instance of the <see cref="SchemeWeapons"/> class.
/// </summary> /// </summary>
public SchemeWeapons() public SchemeWeapons() => Weapons = new SchemeWeaponSetting[_weaponCount];
{
Weapons = new SchemeWeaponSetting[_weaponCount];
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SchemeWeapons"/> class, loading the data from the given /// Initializes a new instance of the <see cref="SchemeWeapons"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public SchemeWeapons(Stream stream) public SchemeWeapons(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SchemeWeapons"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="SchemeWeapons"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public SchemeWeapons(string fileName) public SchemeWeapons(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -62,22 +53,17 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
reader.Seek(_trashLength);
if (reader.ReadString(StringCoding.ZeroTerminated) != _signature)
{
throw new InvalidDataException("Invalid WEP file signature.");
}
// Read the weapon settings. // Read the header.
Weapons = new SchemeWeaponSetting[_weaponCount]; reader.Seek(_trashLength);
for (int i = 0; i < _weaponCount; i++) if (reader.ReadString(StringCoding.ZeroTerminated) != _signature)
{ throw new InvalidDataException("Invalid WEP file signature.");
Weapons[i] = reader.ReadStruct<SchemeWeaponSetting>();
} // Read the weapon settings.
} Weapons = new SchemeWeaponSetting[_weaponCount];
for (int i = 0; i < _weaponCount; i++)
Weapons[i] = reader.ReadStruct<SchemeWeaponSetting>();
} }
/// <summary> /// <summary>
@ -86,10 +72,8 @@ namespace Syroot.Worms.Worms2
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -98,18 +82,15 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{
// Write the header.
writer.WriteStructs(new byte[_trashLength]);
writer.Write(_signature, StringCoding.ZeroTerminated);
// Write the weapon settings. // Write the header.
foreach (SchemeWeaponSetting weapon in Weapons) writer.WriteStructs(new byte[_trashLength]);
{ writer.Write(_signature, StringCoding.ZeroTerminated);
writer.WriteStruct(weapon);
} // Write the weapon settings.
} foreach (SchemeWeaponSetting weapon in Weapons)
writer.WriteStruct(weapon);
} }
/// <summary> /// <summary>
@ -118,10 +99,8 @@ namespace Syroot.Worms.Worms2
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
} }
} }

View File

@ -1,23 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AssemblyName>Syroot.Worms.Worms2</AssemblyName> <AssemblyName>Syroot.Worms.Worms2</AssemblyName>
<Authors>Syroot</Authors> <Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright> <Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library for loading and modifying files of Team17's Worms 2.</Description> <Description>.NET library for loading and modifying files of Team17's Worms 2.</Description>
<GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile> <GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl> <PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl>
<PackageId>Syroot.Worms.Worms2</PackageId> <PackageId>Syroot.Worms.Worms2</PackageId>
<PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl> <PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes> <PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<PackageTags>worms;team17</PackageTags> <PackageTags>worms;team17</PackageTags>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl> <RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks> <TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>2.0.0-alpha1</Version> <Version>2.0.0-alpha1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -109,50 +109,48 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{ Unknown1 = reader.ReadInt16();
Unknown1 = reader.ReadInt16(); Name = reader.ReadString(66);
Name = reader.ReadString(66); SoundBankName = reader.ReadString(36);
SoundBankName = reader.ReadString(36); WormNames = reader.ReadStrings(8, 20);
WormNames = reader.ReadStrings(8, 20); Unknown2 = reader.ReadInt32();
Unknown2 = reader.ReadInt32(); Unknown3 = reader.ReadInt32();
Unknown3 = reader.ReadInt32(); Unknown4 = reader.ReadInt32();
Unknown4 = reader.ReadInt32(); Unknown5 = reader.ReadInt32();
Unknown5 = reader.ReadInt32(); Unknown6 = reader.ReadInt32();
Unknown6 = reader.ReadInt32(); Unknown7 = reader.ReadInt32();
Unknown7 = reader.ReadInt32(); Unknown8 = reader.ReadInt32();
Unknown8 = reader.ReadInt32(); Unknown9 = reader.ReadInt32();
Unknown9 = reader.ReadInt32(); Unknown10 = reader.ReadInt32();
Unknown10 = reader.ReadInt32(); Unknown11 = reader.ReadInt32();
Unknown11 = reader.ReadInt32(); Unknown12 = reader.ReadInt32();
Unknown12 = reader.ReadInt32(); Unknown13 = reader.ReadInt32();
Unknown13 = reader.ReadInt32(); Unknown14 = reader.ReadInt32();
Unknown14 = reader.ReadInt32(); Unknown15 = reader.ReadInt32();
Unknown15 = reader.ReadInt32(); Unknown16 = reader.ReadInt32();
Unknown16 = reader.ReadInt32(); Unknown17 = reader.ReadInt32();
Unknown17 = reader.ReadInt32(); Unknown18 = reader.ReadInt32();
Unknown18 = reader.ReadInt32(); Unknown19 = reader.ReadInt32();
Unknown19 = reader.ReadInt32(); Unknown20 = reader.ReadInt32();
Unknown20 = reader.ReadInt32(); Unknown21 = reader.ReadInt32();
Unknown21 = reader.ReadInt32(); Unknown22 = reader.ReadInt32();
Unknown22 = reader.ReadInt32(); Unknown23 = reader.ReadInt32();
Unknown23 = reader.ReadInt32(); Unknown24 = reader.ReadInt32();
Unknown24 = reader.ReadInt32(); Unknown25 = reader.ReadInt32();
Unknown25 = reader.ReadInt32(); GamesLost = reader.ReadInt32();
GamesLost = reader.ReadInt32(); GamesWon = reader.ReadInt32();
GamesWon = reader.ReadInt32(); Unknown26 = reader.ReadInt32();
Unknown26 = reader.ReadInt32(); Unknown27 = reader.ReadInt32();
Unknown27 = reader.ReadInt32(); Kills = reader.ReadInt32();
Kills = reader.ReadInt32(); Deaths = reader.ReadInt32();
Deaths = reader.ReadInt32(); CpuLevel = reader.ReadInt32();
CpuLevel = reader.ReadInt32(); Unknown28 = reader.ReadInt32();
Unknown28 = reader.ReadInt32(); Unknown29 = reader.ReadInt32();
Unknown29 = reader.ReadInt32(); Unknown30 = reader.ReadInt32();
Unknown30 = reader.ReadInt32(); Difference = reader.ReadInt32();
Difference = reader.ReadInt32(); GamesPlayed = reader.ReadInt32();
GamesPlayed = reader.ReadInt32(); Points = reader.ReadInt32();
Points = reader.ReadInt32();
}
} }
/// <summary> /// <summary>
@ -161,52 +159,50 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
public void Save(Stream stream) public void Save(Stream stream)
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{ writer.Write(Unknown1);
writer.Write(Unknown1); writer.WriteString(Name, 66);
writer.WriteString(Name, 66); writer.WriteString(SoundBankName, 36);
writer.WriteString(SoundBankName, 36); writer.WriteStrings(WormNames, 20);
writer.WriteStrings(WormNames, 20); writer.Write(Unknown2);
writer.Write(Unknown2); writer.Write(Unknown3);
writer.Write(Unknown3); writer.Write(Unknown4);
writer.Write(Unknown4); writer.Write(Unknown5);
writer.Write(Unknown5); writer.Write(Unknown6);
writer.Write(Unknown6); writer.Write(Unknown7);
writer.Write(Unknown7); writer.Write(Unknown8);
writer.Write(Unknown8); writer.Write(Unknown9);
writer.Write(Unknown9); writer.Write(Unknown10);
writer.Write(Unknown10); writer.Write(Unknown11);
writer.Write(Unknown11); writer.Write(Unknown12);
writer.Write(Unknown12); writer.Write(Unknown13);
writer.Write(Unknown13); writer.Write(Unknown14);
writer.Write(Unknown14); writer.Write(Unknown15);
writer.Write(Unknown15); writer.Write(Unknown16);
writer.Write(Unknown16); writer.Write(Unknown17);
writer.Write(Unknown17); writer.Write(Unknown18);
writer.Write(Unknown18); writer.Write(Unknown19);
writer.Write(Unknown19); writer.Write(Unknown20);
writer.Write(Unknown20); writer.Write(Unknown21);
writer.Write(Unknown21); writer.Write(Unknown22);
writer.Write(Unknown22); writer.Write(Unknown23);
writer.Write(Unknown23); writer.Write(Unknown24);
writer.Write(Unknown24); writer.Write(Unknown25);
writer.Write(Unknown25); writer.Write(GamesLost);
writer.Write(GamesLost); writer.Write(GamesWon);
writer.Write(GamesWon); writer.Write(Unknown26);
writer.Write(Unknown26); writer.Write(Unknown27);
writer.Write(Unknown27); writer.Write(Kills);
writer.Write(Kills); writer.Write(Deaths);
writer.Write(Deaths); writer.Write(CpuLevel);
writer.Write(CpuLevel); writer.Write(Unknown28);
writer.Write(Unknown28); writer.Write(Unknown29);
writer.Write(Unknown29); writer.Write(Unknown30);
writer.Write(Unknown30); writer.Write(Kills);
writer.Write(Kills); writer.Write(Deaths);
writer.Write(Deaths); writer.Write(Difference);
writer.Write(Difference); writer.Write(GamesPlayed);
writer.Write(GamesPlayed); writer.Write(Points);
writer.Write(Points);
}
} }
} }
} }

View File

@ -17,29 +17,20 @@ namespace Syroot.Worms.Worms2
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class. /// Initializes a new instance of the <see cref="TeamContainer"/> class.
/// </summary> /// </summary>
public TeamContainer() public TeamContainer() => Teams = new List<Team>();
{
Teams = new List<Team>();
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given /// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public TeamContainer(Stream stream) public TeamContainer(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public TeamContainer(string fileName) public TeamContainer(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -56,14 +47,10 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{ Teams = new List<Team>();
Teams = new List<Team>(); while (!reader.EndOfStream)
while (!reader.EndOfStream) Teams.Add(reader.Load<Team>());
{
Teams.Add(reader.Load<Team>());
}
}
} }
/// <summary> /// <summary>
@ -72,10 +59,8 @@ namespace Syroot.Worms.Worms2
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -84,13 +69,9 @@ namespace Syroot.Worms.Worms2
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
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);
{ foreach (Team team in Teams)
foreach (Team team in Teams) team.Save(writer.BaseStream);
{
team.Save(writer.BaseStream);
}
}
} }
/// <summary> /// <summary>
@ -99,10 +80,8 @@ namespace Syroot.Worms.Worms2
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
} }
} }

View File

@ -28,28 +28,20 @@ namespace Syroot.Worms
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Archive"/> class. /// Initializes a new instance of the <see cref="Archive"/> class.
/// </summary> /// </summary>
public Archive() public Archive() { }
{
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Archive"/> class, loading the data from the given /// Initializes a new instance of the <see cref="Archive"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public Archive(Stream stream) public Archive(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Archive"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="Archive"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public Archive(string fileName) public Archive(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
@ -60,49 +52,40 @@ namespace Syroot.Worms
public void Load(Stream stream) public void Load(Stream stream)
{ {
if (!stream.CanSeek) if (!stream.CanSeek)
{
throw new ArgumentException("Stream requires to be seekable.", nameof(stream)); throw new ArgumentException("Stream requires to be seekable.", nameof(stream));
}
Clear(); Clear();
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the header.
if (reader.ReadInt32() != _signature)
{
throw new InvalidDataException("Invalid DIR file signature.");
}
int fileSize = reader.ReadInt32();
int tocOffset = reader.ReadInt32();
// Read the table of contents. // Read the header.
reader.Position = tocOffset; if (reader.ReadInt32() != _signature)
int tocSignature = reader.ReadInt32(); throw new InvalidDataException("Invalid DIR file signature.");
if (tocSignature != _tocSignature) int fileSize = reader.ReadInt32();
int tocOffset = reader.ReadInt32();
// Read the table of contents.
reader.Position = tocOffset;
int tocSignature = reader.ReadInt32();
if (tocSignature != _tocSignature)
throw new InvalidDataException("Invalid DIR table of contents signature.");
// Generate a data dictionary out of the hash table and file entries.
int[] hashTable = reader.ReadInt32s(_hashSize);
foreach (int entryOffset in hashTable)
{
// If the hash is not 0, it points to a list of files which have a hash being the hash table index.
if (entryOffset > 0)
{ {
throw new InvalidDataException("Invalid DIR table of contents signature."); int nextEntryOffset = entryOffset;
} do
// Generate a data dictionary out of the hash table and file entries.
int[] hashTable = reader.ReadInt32s(_hashSize);
foreach (int entryOffset in hashTable)
{
// If the hash is not 0, it points to a list of files which have a hash being the hash table index.
if (entryOffset > 0)
{ {
int nextEntryOffset = entryOffset; reader.Position = tocOffset + nextEntryOffset;
do nextEntryOffset = reader.ReadInt32();
{ int offset = reader.ReadInt32();
reader.Position = tocOffset + nextEntryOffset; int length = reader.ReadInt32();
nextEntryOffset = reader.ReadInt32(); string name = reader.ReadString(StringCoding.ZeroTerminated);
int offset = reader.ReadInt32(); using (reader.TemporarySeek(offset, SeekOrigin.Begin))
int length = reader.ReadInt32(); Add(name, reader.ReadBytes(length));
string name = reader.ReadString(StringCoding.ZeroTerminated); } while (nextEntryOffset != 0);
using (reader.TemporarySeek(offset, SeekOrigin.Begin))
{
Add(name, reader.ReadBytes(length));
}
} while (nextEntryOffset != 0);
}
} }
} }
} }
@ -113,10 +96,8 @@ namespace Syroot.Worms
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
@ -125,71 +106,66 @@ namespace Syroot.Worms
/// <param name="stream">The <see cref="Stream"/> to save the data in.</param> /// <param name="stream">The <see cref="Stream"/> to save the data in.</param>
public void Save(Stream stream) public void Save(Stream stream)
{ {
using (BinaryStream writer = new BinaryStream(stream)) using BinaryStream writer = new BinaryStream(stream);
// Write the header.
writer.Write(_signature);
uint fileSizeOffset = writer.ReserveOffset();
uint tocOffset = writer.ReserveOffset();
// Write the data and build the hash table and file entries.
List<HashTableEntry>[] hashTable = new List<HashTableEntry>[_hashSize];
foreach (KeyValuePair<string, byte[]> item in this)
{ {
// Write the header. HashTableEntry entry = new HashTableEntry()
writer.Write(_signature);
uint fileSizeOffset = writer.ReserveOffset();
uint tocOffset = writer.ReserveOffset();
// Write the data and build the hash table and file entries.
List<HashTableEntry>[] hashTable = new List<HashTableEntry>[_hashSize];
foreach (KeyValuePair<string, byte[]> item in this)
{ {
HashTableEntry entry = new HashTableEntry() Name = item.Key,
{ Offset = (int)writer.Position,
Name = item.Key, Length = item.Value.Length
Offset = (int)writer.Position, };
Length = item.Value.Length writer.WriteStructs(item.Value);
};
writer.WriteStructs(item.Value);
int hash = CalculateHash(item.Key); int hash = CalculateHash(item.Key);
if (hashTable[hash] == null) if (hashTable[hash] == null)
{ hashTable[hash] = new List<HashTableEntry>();
hashTable[hash] = new List<HashTableEntry>(); hashTable[hash].Add(entry);
}
hashTable[hash].Add(entry);
}
// Write the hash table and file entries.
int tocStart = (int)writer.Position;
int fileEntryOffset = sizeof(int) + _hashSize * sizeof(int);
writer.SatisfyOffset(tocOffset, tocStart);
writer.Write(_tocSignature);
for (int i = 0; i < _hashSize; i++)
{
List<HashTableEntry> entries = hashTable[i];
if (entries == null)
{
writer.Write(0);
}
else
{
// Write the entries resolving to the current hash.
writer.Write(fileEntryOffset);
using (writer.TemporarySeek(tocStart + fileEntryOffset, SeekOrigin.Begin))
{
for (int j = 0; j < entries.Count; j++)
{
HashTableEntry entry = entries[j];
uint nextEntryOffset = writer.ReserveOffset();
writer.Write(entry.Offset);
writer.Write(entry.Length);
writer.Write(entry.Name, StringCoding.ZeroTerminated);
writer.Align(4);
if (j < entries.Count - 1)
{
writer.SatisfyOffset(nextEntryOffset, (int)writer.Position - tocStart);
}
}
fileEntryOffset = (int)writer.Position - tocStart;
}
}
}
writer.SatisfyOffset(fileSizeOffset, tocStart + fileEntryOffset - 1);
} }
// Write the hash table and file entries.
int tocStart = (int)writer.Position;
int fileEntryOffset = sizeof(int) + _hashSize * sizeof(int);
writer.SatisfyOffset(tocOffset, tocStart);
writer.Write(_tocSignature);
for (int i = 0; i < _hashSize; i++)
{
List<HashTableEntry> entries = hashTable[i];
if (entries == null)
{
writer.Write(0);
}
else
{
// Write the entries resolving to the current hash.
writer.Write(fileEntryOffset);
using (writer.TemporarySeek(tocStart + fileEntryOffset, SeekOrigin.Begin))
{
for (int j = 0; j < entries.Count; j++)
{
HashTableEntry entry = entries[j];
uint nextEntryOffset = writer.ReserveOffset();
writer.Write(entry.Offset);
writer.Write(entry.Length);
writer.Write(entry.Name, StringCoding.ZeroTerminated);
writer.Align(4);
if (j < entries.Count - 1)
writer.SatisfyOffset(nextEntryOffset, (int)writer.Position - tocStart);
}
fileEntryOffset = (int)writer.Position - tocStart;
}
}
}
writer.SatisfyOffset(fileSizeOffset, tocStart + fileEntryOffset - 1);
} }
/// <summary> /// <summary>
@ -198,10 +174,8 @@ namespace Syroot.Worms
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------

View File

@ -5,6 +5,8 @@
/// </summary> /// </summary>
public static class Algebra public static class Algebra
{ {
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary> /// <summary>
/// Gets the nearest, bigger <paramref name="multiple"/> of the given <paramref name="value"/>. /// Gets the nearest, bigger <paramref name="multiple"/> of the given <paramref name="value"/>.
/// </summary> /// </summary>

View File

@ -65,9 +65,7 @@ namespace Syroot.Worms.Core
/// <param name="enable"><c>true</c> to enable the bit; otherwise <c>false</c>.</param> /// <param name="enable"><c>true</c> to enable the bit; otherwise <c>false</c>.</param>
/// <returns>The current byte with the bit enabled or disabled.</returns> /// <returns>The current byte with the bit enabled or disabled.</returns>
public static byte SetBit(this byte self, int index, bool enable) public static byte SetBit(this byte self, int index, bool enable)
{ => enable ? EnableBit(self, index) : DisableBit(self, index);
return enable ? EnableBit(self, index) : DisableBit(self, index);
}
/// <summary> /// <summary>
/// Returns the current byte with the bit at the <paramref name="index"/> enabled when it is disabled or /// Returns the current byte with the bit at the <paramref name="index"/> enabled when it is disabled or
@ -77,9 +75,7 @@ namespace Syroot.Worms.Core
/// <param name="index">The 0-based index of the bit to toggle.</param> /// <param name="index">The 0-based index of the bit to toggle.</param>
/// <returns>The current byte with the bit toggled.</returns> /// <returns>The current byte with the bit toggled.</returns>
public static byte ToggleBit(this byte self, int index) public static byte ToggleBit(this byte self, int index)
{ => GetBit(self, index) ? DisableBit(self, index) : EnableBit(self, index);
return GetBit(self, index) ? DisableBit(self, index) : EnableBit(self, index);
}
/// <summary> /// <summary>
/// Returns an <see cref="Byte"/> instance represented by the given number of <paramref name="bits"/>. /// Returns an <see cref="Byte"/> instance represented by the given number of <paramref name="bits"/>.
@ -100,10 +96,7 @@ namespace Syroot.Worms.Core
/// <param name="firstBit">The first bit of the encoded value.</param> /// <param name="firstBit">The first bit of the encoded value.</param>
/// <returns>The decoded <see cref="Byte"/>.</returns> /// <returns>The decoded <see cref="Byte"/>.</returns>
public static byte DecodeByte(this byte self, int bits, int firstBit) public static byte DecodeByte(this byte self, int bits, int firstBit)
{ => (byte)((self >> firstBit) & ((1 << bits) - 1)); // shift to the first bit and keep only required bits
// Shift to the first bit and keep only the required bits.
return (byte)((self >> firstBit) & ((1 << bits) - 1));
}
/// <summary> /// <summary>
/// Returns an <see cref="SByte"/> instance represented by the given number of <paramref name="bits"/>. /// Returns an <see cref="SByte"/> instance represented by the given number of <paramref name="bits"/>.

View File

@ -15,10 +15,7 @@ namespace Syroot.Worms.Core
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
public DisposableGCHandle(object value, GCHandleType type) public DisposableGCHandle(object value, GCHandleType type) => _handle = GCHandle.Alloc(value, type);
{
_handle = GCHandle.Alloc(value, GCHandleType.Pinned);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -26,26 +23,22 @@ namespace Syroot.Worms.Core
// ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public void Dispose() public void Dispose() => Dispose(true);
{
// Do not change this code. Put cleanup code in Dispose(bool disposing).
Dispose(true);
}
// ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------ // ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (!_disposed) if (_disposed)
{ return;
if (disposing)
{
if (_handle.IsAllocated)
_handle.Free();
}
_disposed = true; if (disposing)
{
if (_handle.IsAllocated)
_handle.Free();
} }
_disposed = true;
} }
} }
} }

View File

@ -22,24 +22,23 @@ namespace Syroot.Worms.Core.Graphics
/// <returns>The <see cref="Bitmap"/> instance.</returns> /// <returns>The <see cref="Bitmap"/> instance.</returns>
public static Bitmap CreateIndexed(Size size, IList<Color> palette, byte[] data) public static Bitmap CreateIndexed(Size size, IList<Color> palette, byte[] data)
{ {
using (DisposableGCHandle dataPin = new DisposableGCHandle(data, GCHandleType.Pinned)) using DisposableGCHandle dataPin = new DisposableGCHandle(data, GCHandleType.Pinned);
{
// Transfer the pixel data, respecting power-of-2 strides.
Bitmap bitmap = new Bitmap(size.Width, size.Height, PixelFormat.Format8bppIndexed);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, size.Width, size.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
for (int y = 0; y < size.Height; y++)
Marshal.Copy(data, y * size.Width, bitmapData.Scan0 + y * bitmapData.Stride, size.Width);
bitmap.UnlockBits(bitmapData);
// Transfer the palette. // Transfer the pixel data, respecting power-of-2 strides.
ColorPalette bitmapPalette = bitmap.Palette; Bitmap bitmap = new Bitmap(size.Width, size.Height, PixelFormat.Format8bppIndexed);
for (int i = 0; i < palette.Count; i++) BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, size.Width, size.Height),
bitmapPalette.Entries[i] = palette[i]; ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
bitmap.Palette = bitmapPalette; for (int y = 0; y < size.Height; y++)
Marshal.Copy(data, y * size.Width, bitmapData.Scan0 + y * bitmapData.Stride, size.Width);
bitmap.UnlockBits(bitmapData);
return bitmap; // Transfer the palette.
} ColorPalette bitmapPalette = bitmap.Palette;
for (int i = 0; i < palette.Count; i++)
bitmapPalette.Entries[i] = palette[i];
bitmap.Palette = bitmapPalette;
return bitmap;
} }
} }
} }

View File

@ -41,24 +41,23 @@ namespace Syroot.Worms
/// <returns>The <see cref="Bitmap"/> created from the raw data.</returns> /// <returns>The <see cref="Bitmap"/> created from the raw data.</returns>
public Bitmap ToBitmap() public Bitmap ToBitmap()
{ {
using (DisposableGCHandle dataPin = new DisposableGCHandle(Data, GCHandleType.Pinned)) using DisposableGCHandle dataPin = new DisposableGCHandle(Data, GCHandleType.Pinned);
{
// Transfer the pixel data, respecting power-of-2 strides.
Bitmap bitmap = new Bitmap(Size.Width, Size.Height, PixelFormat.Format8bppIndexed);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
for (int y = 0; y < Size.Height; y++)
Marshal.Copy(Data, y * Size.Width, bitmapData.Scan0 + y * bitmapData.Stride, Size.Width);
bitmap.UnlockBits(bitmapData);
// Transfer the palette. // Transfer the pixel data, respecting power-of-2 strides.
ColorPalette bitmapPalette = bitmap.Palette; Bitmap bitmap = new Bitmap(Size.Width, Size.Height, PixelFormat.Format8bppIndexed);
for (int i = 0; i < Palette.Count; i++) BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
bitmapPalette.Entries[i] = Palette[i]; ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
bitmap.Palette = bitmapPalette; for (int y = 0; y < Size.Height; y++)
Marshal.Copy(Data, y * Size.Width, bitmapData.Scan0 + y * bitmapData.Stride, Size.Width);
bitmap.UnlockBits(bitmapData);
return bitmap; // Transfer the palette.
} ColorPalette bitmapPalette = bitmap.Palette;
for (int i = 0; i < Palette.Count; i++)
bitmapPalette.Entries[i] = Palette[i];
bitmap.Palette = bitmapPalette;
return bitmap;
} }
} }
} }

View File

@ -87,11 +87,9 @@ namespace Syroot.Worms.Core.IO
byte[] bytes = self.ReadBytes(Marshal.SizeOf<T>()); byte[] bytes = self.ReadBytes(Marshal.SizeOf<T>());
// Convert them to a structure instance and return it. // Convert them to a structure instance and return it.
using (DisposableGCHandle handle = new DisposableGCHandle(bytes, GCHandleType.Pinned)) using DisposableGCHandle handle = new DisposableGCHandle(bytes, GCHandleType.Pinned);
{ T instance = Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject);
T instance = Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject); return instance;
return instance;
}
} }
/// <summary> /// <summary>

View File

@ -16,10 +16,7 @@ namespace Syroot.Worms.Core.Riff
/// <paramref name="identifier"/>. /// <paramref name="identifier"/>.
/// </summary> /// </summary>
/// <param name="identifier">The chunk identifier required to invoke this method for loading it.</param> /// <param name="identifier">The chunk identifier required to invoke this method for loading it.</param>
internal RiffChunkLoadAttribute(string identifier) internal RiffChunkLoadAttribute(string identifier) => Identifier = identifier;
{
Identifier = identifier;
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------

View File

@ -16,10 +16,7 @@ namespace Syroot.Worms.Core.Riff
/// <paramref name="identifier"/>. /// <paramref name="identifier"/>.
/// </summary> /// </summary>
/// <param name="identifier">The chunk identifier saved in the file.</param> /// <param name="identifier">The chunk identifier saved in the file.</param>
internal RiffChunkSaveAttribute(string identifier) internal RiffChunkSaveAttribute(string identifier) => Identifier = identifier;
{
Identifier = identifier;
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------

View File

@ -21,17 +21,14 @@ namespace Syroot.Worms.Core.Riff
private static readonly Dictionary<Type, TypeData> _typeDataCache = new Dictionary<Type, TypeData>(); private static readonly Dictionary<Type, TypeData> _typeDataCache = new Dictionary<Type, TypeData>();
private TypeData _typeData; private readonly TypeData _typeData;
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RiffFile"/> class. /// Initializes a new instance of the <see cref="RiffFile"/> class.
/// </summary> /// </summary>
protected RiffFile() protected RiffFile() => _typeData = GetTypeData();
{
_typeData = GetTypeData();
}
// ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------ // ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------
@ -41,35 +38,26 @@ namespace Syroot.Worms.Core.Riff
/// <param name="stream">The <see cref="Stream"/> to load the RIFF data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the RIFF data from.</param>
protected void LoadRiff(Stream stream) protected void LoadRiff(Stream stream)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
{
// Read the file header.
if (reader.ReadString(_signature.Length) != _signature)
{
throw new InvalidDataException("Invalid RIFF file signature.");
}
int fileSize = reader.ReadInt32();
string fileIdentifier = reader.ReadString(4);
if (fileIdentifier != _typeData.FileIdentifier)
{
throw new InvalidDataException("Invalid RIFF file identifier.");
}
// Read the chunks. // Read the file header.
while (!reader.EndOfStream) if (reader.ReadString(_signature.Length) != _signature)
{ throw new InvalidDataException("Invalid RIFF file signature.");
string chunkIdentifier = reader.ReadString(4); int fileSize = reader.ReadInt32();
int chunkLength = reader.ReadInt32(); string fileIdentifier = reader.ReadString(4);
// Invoke a loader method if matching the identifier or skip the chunk. if (fileIdentifier != _typeData.FileIdentifier)
if (_typeData.ChunkLoaders.TryGetValue(chunkIdentifier, out MethodInfo loader)) throw new InvalidDataException("Invalid RIFF file identifier.");
{
loader.Invoke(this, new object[] { reader, chunkLength }); // Read the chunks.
} while (!reader.EndOfStream)
else {
{ string chunkIdentifier = reader.ReadString(4);
reader.Seek(chunkLength); int chunkLength = reader.ReadInt32();
} // Invoke a loader method if matching the identifier or skip the chunk.
} if (_typeData.ChunkLoaders.TryGetValue(chunkIdentifier, out MethodInfo loader))
loader.Invoke(this, new object[] { reader, chunkLength });
else
reader.Seek(chunkLength);
} }
} }
@ -79,26 +67,25 @@ namespace Syroot.Worms.Core.Riff
/// <param name="stream">The <see cref="Stream"/> to save the RIFF data in.</param> /// <param name="stream">The <see cref="Stream"/> to save the RIFF data in.</param>
protected void SaveRiff(Stream stream) protected void SaveRiff(Stream stream)
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII)) using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII);
// Write the header.
writer.Write(_signature, StringCoding.Raw);
uint fileSizeOffset = writer.ReserveOffset();
writer.Write(_typeData.FileIdentifier, StringCoding.Raw);
// Write the chunks.
foreach (KeyValuePair<string, MethodInfo> chunkSaver in _typeData.ChunkSavers)
{ {
// Write the header. writer.Write(chunkSaver.Key, StringCoding.Raw);
writer.Write(_signature, StringCoding.Raw); uint chunkSizeOffset = writer.ReserveOffset();
uint fileSizeOffset = writer.ReserveOffset();
writer.Write(_typeData.FileIdentifier, StringCoding.Raw);
// Write the chunks. chunkSaver.Value.Invoke(this, new object[] { writer });
foreach (KeyValuePair<string, MethodInfo> chunkSaver in _typeData.ChunkSavers)
{
writer.Write(chunkSaver.Key, StringCoding.Raw);
uint chunkSizeOffset = writer.ReserveOffset();
chunkSaver.Value.Invoke(this, new object[] { writer }); writer.SatisfyOffset(chunkSizeOffset, (int)(writer.Position - chunkSizeOffset - 4));
writer.SatisfyOffset(chunkSizeOffset, (int)(writer.Position - chunkSizeOffset - 4));
}
writer.SatisfyOffset(fileSizeOffset, (int)(writer.Position - 8));
} }
writer.SatisfyOffset(fileSizeOffset, (int)(writer.Position - 8));
} }
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
@ -135,11 +122,8 @@ namespace Syroot.Worms.Core.Riff
if (saveAttribute != null) if (saveAttribute != null)
{ {
ParameterInfo[] parameters = method.GetParameters(); ParameterInfo[] parameters = method.GetParameters();
if (parameters.Length == 1 if (parameters.Length == 1 && parameters[0].ParameterType == typeof(BinaryStream))
&& parameters[0].ParameterType == typeof(BinaryStream))
{
typeData.ChunkSavers.Add(saveAttribute.Identifier, method); typeData.ChunkSavers.Add(saveAttribute.Identifier, method);
}
continue; continue;
} }
} }

View File

@ -15,10 +15,7 @@ namespace Syroot.Worms.Core.Riff
/// <paramref name="identifier"/>. /// <paramref name="identifier"/>.
/// </summary> /// </summary>
/// <param name="identifier">The file identifier in the RIFF file header which will be validated.</param> /// <param name="identifier">The file identifier in the RIFF file header which will be validated.</param>
internal RiffFileAttribute(string identifier) internal RiffFileAttribute(string identifier) => Identifier = identifier;
{
Identifier = identifier;
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------

View File

@ -18,9 +18,7 @@ namespace Syroot.Worms.Core
/// <param name="bytes">The data to compress.</param> /// <param name="bytes">The data to compress.</param>
/// <returns>The compressed data.</returns> /// <returns>The compressed data.</returns>
internal static byte[] Compress(byte[] bytes) internal static byte[] Compress(byte[] bytes)
{ => throw new NotImplementedException("Compressing data has not been implemented yet.");
throw new NotImplementedException("Compressing data has not been implemented yet.");
}
/// <summary> /// <summary>
/// Decompresses the data available in the given <paramref name="stream"/> into the provided /// Decompresses the data available in the given <paramref name="stream"/> into the provided

View File

@ -67,8 +67,8 @@ namespace Syroot.Worms
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream); Load(stream);
} }
/// <summary> /// <summary>
@ -78,61 +78,60 @@ namespace Syroot.Worms
/// <param name="alignData"><c>true</c> to align the data array by 4 bytes.</param> /// <param name="alignData"><c>true</c> to align the data array by 4 bytes.</param>
public void Load(Stream stream, bool alignData) public void Load(Stream stream, bool alignData)
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
// Read the header.
if (reader.ReadInt32() != _signature)
throw new InvalidDataException("Invalid IMG file signature.");
int fileSize = reader.ReadInt32();
// Read an optional string describing the image contents and the bits per pixel.
BitsPerPixel = reader.Read1Byte();
if (BitsPerPixel == 0)
{ {
// Read the header. Description = String.Empty;
if (reader.ReadInt32() != _signature)
throw new InvalidDataException("Invalid IMG file signature.");
int fileSize = reader.ReadInt32();
// Read an optional string describing the image contents and the bits per pixel.
BitsPerPixel = reader.Read1Byte(); BitsPerPixel = reader.Read1Byte();
if (BitsPerPixel == 0)
{
Description = String.Empty;
BitsPerPixel = reader.Read1Byte();
}
else if (BitsPerPixel > 32)
{
Description = (char)BitsPerPixel + reader.ReadString(StringCoding.ZeroTerminated);
BitsPerPixel = reader.Read1Byte();
}
else
{
Description = null;
}
// Read image flags describing the format and availability of the following contents.
Flags flags = (Flags)reader.ReadByte();
// Read the image palette if available. The first color of the palette is implicitly black.
if (flags.HasFlag(Flags.Palettized))
{
int colorCount = reader.ReadInt16();
Palette = new Color[colorCount + 1];
Palette[0] = Color.Black;
for (int i = 1; i <= colorCount; i++)
Palette[i] = Color.FromArgb(reader.Read1Byte(), reader.Read1Byte(), reader.Read1Byte());
}
else
{
Palette = null;
}
// Read the image size.
Size = new Size(reader.ReadInt16(), reader.ReadInt16());
// Read the data byte array, which might be compressed or aligned.
if (alignData)
reader.Align(4);
byte[] data = new byte[Size.Width * Size.Height * BitsPerPixel / 8];
if (flags.HasFlag(Flags.Compressed))
Team17Compression.Decompress(reader.BaseStream, data);
else
data = reader.ReadBytes(data.Length);
Data = data;
} }
else if (BitsPerPixel > 32)
{
Description = (char)BitsPerPixel + reader.ReadString(StringCoding.ZeroTerminated);
BitsPerPixel = reader.Read1Byte();
}
else
{
Description = null;
}
// Read image flags describing the format and availability of the following contents.
Flags flags = (Flags)reader.ReadByte();
// Read the image palette if available. The first color of the palette is implicitly black.
if (flags.HasFlag(Flags.Palettized))
{
int colorCount = reader.ReadInt16();
Palette = new Color[colorCount + 1];
Palette[0] = Color.Black;
for (int i = 1; i <= colorCount; i++)
Palette[i] = Color.FromArgb(reader.Read1Byte(), reader.Read1Byte(), reader.Read1Byte());
}
else
{
Palette = null;
}
// Read the image size.
Size = new Size(reader.ReadInt16(), reader.ReadInt16());
// Read the data byte array, which might be compressed or aligned.
if (alignData)
reader.Align(4);
byte[] data = new byte[Size.Width * Size.Height * BitsPerPixel / 8];
if (flags.HasFlag(Flags.Compressed))
Team17Compression.Decompress(reader.BaseStream, data);
else
data = reader.ReadBytes(data.Length);
Data = data;
} }
/// <summary> /// <summary>
@ -142,8 +141,8 @@ namespace Syroot.Worms
/// <param name="alignData"><c>true</c> to align the data array by 4 bytes.</param> /// <param name="alignData"><c>true</c> to align the data array by 4 bytes.</param>
public void Load(string fileName, bool alignData) public void Load(string fileName, bool alignData)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Load(stream); Load(stream, alignData);
} }
/// <summary> /// <summary>
@ -181,52 +180,51 @@ namespace Syroot.Worms
/// <param name="alignData"><c>true</c> to align the data array by 4 bytes.</param> /// <param name="alignData"><c>true</c> to align the data array by 4 bytes.</param>
public void Save(Stream stream, bool compress, bool alignData) public void Save(Stream stream, bool compress, bool alignData)
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII)) using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII);
// Write the header.
writer.Write(_signature);
uint fileSizeOffset = writer.ReserveOffset();
// Write an optional string describing the image contents and the bits per pixel.
if (Description != null)
writer.Write(Description, StringCoding.ZeroTerminated);
writer.Write(BitsPerPixel);
// Write image flags describing the format and availability of the following contents.
Flags flags = Flags.None;
if (Palette != null)
flags |= Flags.Palettized;
if (compress)
flags |= Flags.Compressed;
writer.WriteEnum(flags, true);
// Write the image palette if available. The first color of the palette is implicitly black.
if (Palette != null)
{ {
// Write the header. writer.Write((short)(Palette.Count - 1));
writer.Write(_signature); for (int i = 1; i < Palette.Count; i++)
uint fileSizeOffset = writer.ReserveOffset();
// Write an optional string describing the image contents and the bits per pixel.
if (Description != null)
writer.Write(Description, StringCoding.ZeroTerminated);
writer.Write(BitsPerPixel);
// Write image flags describing the format and availability of the following contents.
Flags flags = Flags.None;
if (Palette != null)
flags |= Flags.Palettized;
if (compress)
flags |= Flags.Compressed;
writer.WriteEnum(flags, true);
// Write the image palette if available. The first color of the palette is implicitly black.
if (Palette != null)
{ {
writer.Write((short)(Palette.Count - 1)); Color color = Palette[i];
for (int i = 1; i < Palette.Count; i++) writer.Write(color.R);
{ writer.Write(color.G);
Color color = Palette[i]; writer.Write(color.B);
writer.Write(color.R);
writer.Write(color.G);
writer.Write(color.B);
}
} }
// Write the image size.
writer.Write((short)Size.Width);
writer.Write((short)Size.Height);
// Write the data byte array, which might be compressed or aligned.
if (alignData)
writer.Align(4);
byte[] data = Data;
if (compress)
data = Team17Compression.Compress(data);
writer.WriteStructs(data);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position);
} }
// Write the image size.
writer.Write((short)Size.Width);
writer.Write((short)Size.Height);
// Write the data byte array, which might be compressed or aligned.
if (alignData)
writer.Align(4);
byte[] data = Data;
if (compress)
data = Team17Compression.Compress(data);
writer.WriteStructs(data);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position);
} }
/// <summary> /// <summary>
@ -237,8 +235,8 @@ namespace Syroot.Worms
/// <param name="alignData"><c>true</c> to align the data array by 4 bytes.</param> /// <param name="alignData"><c>true</c> to align the data array by 4 bytes.</param>
public void Save(string fileName, bool compress, bool alignData) public void Save(string fileName, bool compress, bool alignData)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
Save(stream, compress, alignData); Save(stream, compress, alignData);
} }
// ---- ENUMERATIONS ------------------------------------------------------------------------------------------- // ---- ENUMERATIONS -------------------------------------------------------------------------------------------

View File

@ -23,29 +23,20 @@ namespace Syroot.Worms
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RiffPalette"/> class. /// Initializes a new instance of the <see cref="RiffPalette"/> class.
/// </summary> /// </summary>
public RiffPalette() public RiffPalette() => Version = _version;
{
Version = _version;
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RiffPalette"/> class, loading the data from the given /// Initializes a new instance of the <see cref="RiffPalette"/> class, loading the data from the given
/// <see cref="Stream"/>. /// <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public RiffPalette(Stream stream) public RiffPalette(Stream stream) => Load(stream);
{
Load(stream);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RiffPalette"/> class, loading the data from the given file. /// Initializes a new instance of the <see cref="RiffPalette"/> class, loading the data from the given file.
/// </summary> /// </summary>
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public RiffPalette(string fileName) public RiffPalette(string fileName) => Load(fileName);
{
Load(fileName);
}
// ---- PROPERTIES --------------------------------------------------------------------------------------------- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -80,10 +71,7 @@ namespace Syroot.Worms
/// Loads the data from the given <see cref="Stream"/>. /// Loads the data from the given <see cref="Stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param> /// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream) public void Load(Stream stream) => LoadRiff(stream);
{
LoadRiff(stream);
}
/// <summary> /// <summary>
/// Loads the data from the given file. /// Loads the data from the given file.
@ -91,20 +79,15 @@ namespace Syroot.Worms
/// <param name="fileName">The name of the file to load the data from.</param> /// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName) public void Load(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
{ Load(stream);
Load(stream);
}
} }
/// <summary> /// <summary>
/// Saves the data into the given <paramref name="stream"/>. /// Saves the data into the given <paramref name="stream"/>.
/// </summary> /// </summary>
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
public void Save(Stream stream) public void Save(Stream stream) => SaveRiff(stream);
{
SaveRiff(stream);
}
/// <summary> /// <summary>
/// Saves the data in the given file. /// Saves the data in the given file.
@ -112,10 +95,8 @@ namespace Syroot.Worms
/// <param name="fileName">The name of the file to save the data in.</param> /// <param name="fileName">The name of the file to save the data in.</param>
public void Save(string fileName) public void Save(string fileName)
{ {
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
{ Save(stream);
Save(stream);
}
} }
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
@ -126,36 +107,25 @@ namespace Syroot.Worms
// Read the PAL version. // Read the PAL version.
Version = reader.ReadInt16(); Version = reader.ReadInt16();
if (Version != _version) if (Version != _version)
{
throw new InvalidDataException("Unknown PAL version."); throw new InvalidDataException("Unknown PAL version.");
}
// Read the colors. // Read the colors.
Colors = new Color[reader.ReadInt16()]; Colors = new Color[reader.ReadInt16()];
for (int i = 0; i < Colors.Length; i++) for (int i = 0; i < Colors.Length; i++)
{ {
Colors[i] = Color.FromArgb(reader.Read1Byte(), reader.Read1Byte(), reader.Read1Byte()); Colors[i] = Color.FromArgb(reader.Read1Byte(), reader.Read1Byte(), reader.Read1Byte());
int alpha = reader.ReadByte(); // Dismiss alpha, as it is not used in WA. _ = reader.ReadByte(); // Dismiss alpha, as it is not used in WA.
} }
} }
[RiffChunkLoad("offl")] [RiffChunkLoad("offl")]
private void LoadOfflChunk(BinaryStream reader, int length) private void LoadOfflChunk(BinaryStream reader, int length) => OfflData = reader.ReadBytes(length);
{
OfflData = reader.ReadBytes(length);
}
[RiffChunkLoad("tran")] [RiffChunkLoad("tran")]
private void LoadTranChunk(BinaryStream reader, int length) private void LoadTranChunk(BinaryStream reader, int length) => TranData = reader.ReadBytes(length);
{
TranData = reader.ReadBytes(length);
}
[RiffChunkLoad("unde")] [RiffChunkLoad("unde")]
private void LoadUndeChunk(BinaryStream reader, int length) private void LoadUndeChunk(BinaryStream reader, int length) => UndeData = reader.ReadBytes(length);
{
UndeData = reader.ReadBytes(length);
}
[RiffChunkSave("data")] [RiffChunkSave("data")]
private void SaveDataChunk(BinaryStream writer) private void SaveDataChunk(BinaryStream writer)
@ -176,21 +146,12 @@ namespace Syroot.Worms
} }
[RiffChunkSave("offl")] [RiffChunkSave("offl")]
private void SaveOfflChunk(BinaryStream writer) private void SaveOfflChunk(BinaryStream writer) => writer.WriteStructs(OfflData);
{
writer.WriteStructs(OfflData);
}
[RiffChunkSave("tran")] [RiffChunkSave("tran")]
private void SaveTranChunk(BinaryStream writer) private void SaveTranChunk(BinaryStream writer) => writer.WriteStructs(TranData);
{
writer.WriteStructs(TranData);
}
[RiffChunkSave("unde")] [RiffChunkSave("unde")]
private void SaveUndeChunk(BinaryStream writer) private void SaveUndeChunk(BinaryStream writer) => writer.WriteStructs(UndeData);
{
writer.WriteStructs(UndeData);
}
} }
} }

View File

@ -1,26 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AssemblyName>Syroot.Worms</AssemblyName> <AssemblyName>Syroot.Worms</AssemblyName>
<Authors>Syroot</Authors> <Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright> <Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>.NET library for loading and modifying files of Team17 Worms games.</Description> <Description>.NET library for loading and modifying files of Team17 Worms games.</Description>
<GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile> <GenerateDocumentationFile Condition="'$(Configuration)'=='Release'">true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl> <PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl>
<PackageId>Syroot.Worms</PackageId> <PackageId>Syroot.Worms</PackageId>
<PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl>
<PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl> <PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes> <PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<PackageTags>worms;team17</PackageTags> <PackageTags>worms;team17</PackageTags>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl> <RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks> <TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>2.0.0-alpha1</Version> <Version>2.0.0</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Syroot.BinaryData.Serialization" Version="5.0.0" /> <PackageReference Include="Syroot.BinaryData.Serialization" Version="5.2.0" />
<PackageReference Include="Syroot.BinaryData" Version="5.1.0" /> <PackageReference Include="Syroot.BinaryData" Version="5.2.0" />
<PackageReference Include="System.Drawing.Common" Version="4.5.1" /> <PackageReference Include="System.Drawing.Common" Version="4.6.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="4.6.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<ProjectReference Include="..\..\library\Syroot.Worms.Armageddon.ProjectX\Syroot.Worms.Armageddon.ProjectX.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Armageddon.ProjectX\Syroot.Worms.Armageddon.ProjectX.csproj" />
<ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" /> <ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<ProjectReference Include="..\..\library\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
<ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" /> <ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<ProjectReference Include="..\..\library\Syroot.Worms.WorldParty\Syroot.Worms.WorldParty.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.WorldParty\Syroot.Worms.WorldParty.csproj" />
<ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" /> <ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<ProjectReference Include="..\..\library\Syroot.Worms.Worms2\Syroot.Worms.Worms2.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Worms2\Syroot.Worms.Worms2.csproj" />
<ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" /> <ProjectReference Include="..\Syroot.Worms.Test\Syroot.Worms.Test.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -33,8 +33,8 @@ namespace Syroot.Worms.Mgame.GameServer
// Retrieve external IP if not yet done and given IP is invalid. // Retrieve external IP if not yet done and given IP is invalid.
if (_ipAddress == null && (IP == null || !IPAddress.TryParse(IP, out _ipAddress))) if (_ipAddress == null && (IP == null || !IPAddress.TryParse(IP, out _ipAddress)))
{ {
using (WebClient webClient = new WebClient()) using WebClient webClient = new WebClient();
_ipAddress = IPAddress.Parse(webClient.DownloadString("https://ip.syroot.com")); _ipAddress = IPAddress.Parse(webClient.DownloadString("https://ip.syroot.com"));
} }
return _ipAddress; return _ipAddress;
} }

View File

@ -91,6 +91,7 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
{ {
if (disposing) if (disposing)
TcpClient.Dispose(); TcpClient.Dispose();
_tcpStream.Dispose();
_disposed = true; _disposed = true;
} }
} }
@ -102,10 +103,8 @@ namespace Syroot.Worms.Mgame.GameServer.Packets
{ {
// Let each packet format try to serialize the data. // Let each packet format try to serialize the data.
foreach (IPacketFormat format in _packetFormatPipe) foreach (IPacketFormat format in _packetFormatPipe)
{
if (format.TrySave(_tcpStream, packet)) if (format.TrySave(_tcpStream, packet))
return; return;
}
throw new NotImplementedException("Cannot send unhandled packet format."); throw new NotImplementedException("Cannot send unhandled packet format.");
} }
catch (IOException) { } // A network error appeared, and communication should end. catch (IOException) { } // A network error appeared, and communication should end.

View File

@ -9,7 +9,7 @@ namespace Syroot.Worms.Mgame.GameServer
{ {
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
private static void Main(string[] args) private static void Main()
{ {
try try
{ {

View File

@ -1,21 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AssemblyName>Server</AssemblyName> <AssemblyName>Server</AssemblyName>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks> <TargetFrameworks>netcoreapp2.1</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" />
<PackageReference Include="Syroot.BinaryData.Memory" Version="5.2.0-alpha1" /> <PackageReference Include="Syroot.BinaryData.Memory" Version="5.2.2" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="4.6.0" />
<ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />
<ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" />
<None Update="ServerConfig.json"> <None Update="ServerConfig.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -14,7 +14,7 @@ namespace Syroot.Worms.Mgame.Launcher
{ {
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
private static void Main(string[] args) private static void Main()
{ {
try try
{ {
@ -36,23 +36,25 @@ namespace Syroot.Worms.Mgame.Launcher
using (launchConfig.CreateMappedFile(config.MappingName)) using (launchConfig.CreateMappedFile(config.MappingName))
{ {
// Create and run the process. // Create and run the process.
NativeProcess process = CreateProcess(executablePath, using (NativeProcess process = CreateProcess(executablePath,
String.Join(" ", config.MappingName, config.ExecutableArgs).TrimEnd(), String.Join(" ", config.MappingName, config.ExecutableArgs).TrimEnd(),
config.StartSuspended); config.StartSuspended))
if (config.StartSuspended)
{ {
if (ShowMessage(MessageBoxIcon.Information, if (config.StartSuspended)
"Game process has been created and is paused. Click OK to resume or Cancel to kill it.",
MessageBoxButtons.OKCancel) == DialogResult.OK)
{ {
process.Resume(); if (ShowMessage(MessageBoxIcon.Information,
} "Game process has been created and is paused. Click OK to resume or Cancel to kill it.",
else MessageBoxButtons.OKCancel) == DialogResult.OK)
{ {
process.Terminate(); process.Resume();
}
else
{
process.Terminate();
}
} }
process.WaitForExit();
} }
process.WaitForExit();
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,29 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<ApplicationIcon>Resources\Icon.ico</ApplicationIcon> <ApplicationIcon>Resources\Icon.ico</ApplicationIcon>
<ApplicationManifest>Resources\app.manifest</ApplicationManifest> <ApplicationManifest>Resources\app.manifest</ApplicationManifest>
<AssemblyName>Launcher</AssemblyName> <AssemblyName>Launcher</AssemblyName>
<AssemblyTitle>Mgame Worms Launcher</AssemblyTitle> <AssemblyTitle>Mgame Worms Launcher</AssemblyTitle>
<Authors>Syroot</Authors> <Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright> <Copyright>(c) Syroot, licensed under MIT</Copyright>
<DebugType Condition="'$(Configuration)'=='Release'">None</DebugType> <DebugType Condition="'$(Configuration)'=='Release'">None</DebugType>
<Description>Game launcher for Mgame Worms games</Description> <Description>Game launcher for Mgame Worms games</Description>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<ProductName>Online Worms Launcher</ProductName> <ProductName>Online Worms Launcher</ProductName>
<TargetFrameworks>net461</TargetFrameworks> <TargetFrameworks>net461</TargetFrameworks>
<Version>1.0.0</Version> <Version>1.0.0</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Costura.Fody" Version="3.3.0" /> <PackageReference Include="Costura.Fody" Version="4.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" />
<ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />
<ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
<None Update="LauncherConfig.json"> <None Update="LauncherConfig.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Syroot.BinaryData" Version="5.1.0" /> <PackageReference Include="Syroot.BinaryData" Version="5.2.0" />
<ProjectReference Include="..\..\library\Syroot.Worms.Armageddon.ProjectX\Syroot.Worms.Armageddon.ProjectX.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Armageddon.ProjectX\Syroot.Worms.Armageddon.ProjectX.csproj" />
<ProjectReference Include="..\..\library\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
<ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />
<ProjectReference Include="..\..\library\Syroot.Worms.WorldParty\Syroot.Worms.WorldParty.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.WorldParty\Syroot.Worms.WorldParty.csproj" />
<ProjectReference Include="..\..\library\Syroot.Worms.Worms2\Syroot.Worms.Worms2.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms.Worms2\Syroot.Worms.Worms2.csproj" />
<ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" /> <ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>