Clean-up and re-use BinaryStream(Extensions).

This commit is contained in:
Ray Koopa 2019-01-12 20:34:26 +01:00
parent cf7e69e026
commit 4741e0f425
23 changed files with 106 additions and 194 deletions

View File

@ -8,15 +8,12 @@ namespace Syroot.Worms.OnlineWorms.Server.Net
/// <summary> /// <summary>
/// Represents a stream formatting data for being sent or received from <see cref="Packet"/> instances. /// Represents a stream formatting data for being sent or received from <see cref="Packet"/> instances.
/// </summary> /// </summary>
internal class PacketStream : Stream internal class PacketStream : BinaryStream
{ {
// ---- FIELDS ------------------------------------------------------------------------------------------------- // ---- FIELDS -------------------------------------------------------------------------------------------------
private static readonly Encoding _win949Encoding; private static readonly Encoding _win949Encoding;
private readonly Stream _baseStream;
private bool _disposed;
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
static PacketStream() static PacketStream()
@ -28,43 +25,7 @@ namespace Syroot.Worms.OnlineWorms.Server.Net
} }
internal PacketStream(Stream baseStream) internal PacketStream(Stream baseStream)
{ : base(baseStream, encoding: _win949Encoding, stringCoding: StringCoding.Int16CharCount) { }
_baseStream = baseStream;
}
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
public override bool CanRead => _baseStream.CanRead;
public override bool CanSeek => _baseStream.CanSeek;
public override bool CanWrite => _baseStream.CanWrite;
public override long Length => _baseStream.Length;
public override long Position
{
get => _baseStream.Position;
set => _baseStream.Position = value;
}
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
public override void Flush() => _baseStream.Flush();
public override int Read(byte[] buffer, int offset, int count) => _baseStream.Read(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => _baseStream.Seek(offset, origin);
public override void SetLength(long value) => _baseStream.SetLength(value);
public override void Write(byte[] buffer, int offset, int count) => _baseStream.Write(buffer, offset, count);
// ---- METHODS (PROTECTED) ------------------------------------------------------------------------------------
protected override void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
_baseStream.Dispose();
_disposed = true;
base.Dispose(disposing);
}
// ---- METHODS (INTERNAL) ------------------------------------------------------------------------------------- // ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
@ -84,43 +45,20 @@ namespace Syroot.Worms.OnlineWorms.Server.Net
while (totalRead < count) while (totalRead < count)
{ {
// Read returns 0 only when the underlying socket is closed, otherwise it blocks. // Read returns 0 only when the underlying socket is closed, otherwise it blocks.
int read = _baseStream.Read(buffer, offset + totalRead, count - totalRead); int read = BaseStream.Read(buffer, offset + totalRead, count - totalRead);
if (read == 0) if (read == 0)
throw new IOException("The underlying stream has closed, 0 bytes were retrieved."); throw new IOException("The underlying stream has closed, 0 bytes were retrieved.");
totalRead += read; totalRead += read;
} }
} }
/// <summary>
/// Reads a raw, Windows-949 encoded string using the given number of bytes.
/// </summary>
/// <param name="bufferSize">The number of bytes to use for the string.</param>
/// <returns>The read value.</returns>
internal string ReadString(int bufferSize)
{
// Ensure to not try to decode any bytes after the 0 termination.
byte[] bytes = _baseStream.ReadBytes(bufferSize);
int length = bufferSize;
while (bytes[--length] == 0 && length > 0) { }
return _win949Encoding.GetString(bytes, 0, length + 1);
}
/// <summary>
/// Reads a 2-byte length-prefixed, Windows-949 enoded string.
/// </summary>
/// <returns>The read value.</returns>
internal string ReadString()
{
return _baseStream.ReadString(StringCoding.Int16CharCount, _win949Encoding);
}
/// <summary> /// <summary>
/// Reads the remaining bytes in the buffer. /// Reads the remaining bytes in the buffer.
/// </summary> /// </summary>
/// <returns>The remaining bytes.</returns> /// <returns>The remaining bytes.</returns>
internal byte[] ReadToEnd() internal byte[] ReadToEnd()
{ {
return _baseStream.ReadBytes((int)(Length - Position)); return BaseStream.ReadBytes((int)(Length - Position));
} }
/// <summary> /// <summary>
@ -129,32 +67,10 @@ namespace Syroot.Worms.OnlineWorms.Server.Net
/// <param name="color">The <see cref="Color"/> to write.</param> /// <param name="color">The <see cref="Color"/> to write.</param>
internal void WriteColor(Color color) internal void WriteColor(Color color)
{ {
_baseStream.WriteByte(color.R); BaseStream.WriteByte(color.R);
_baseStream.WriteByte(color.G); BaseStream.WriteByte(color.G);
_baseStream.WriteByte(color.B); BaseStream.WriteByte(color.B);
_baseStream.WriteByte(0); BaseStream.WriteByte(0);
}
/// <summary>
/// Writes a raw, Windows-949 encoded string using the given number of bytes.
/// </summary>
/// <param name="value">The value to write.</param>
/// <param name="bufferSize">The number of bytes to reserve for the string.</param>
internal void WriteString(string value, int bufferSize)
{
byte[] bytes = new byte[bufferSize];
if (value != null)
_win949Encoding.GetBytes(value, 0, value.Length, bytes, 0);
_baseStream.WriteBytes(bytes);
}
/// <summary>
/// Writes a 2-byte length-prefixed, Windows-949 encoded string.
/// </summary>
/// <param name="value">The value to write.</param>
internal void WriteString(string value)
{
_baseStream.WriteString(value, StringCoding.Int16CharCount, _win949Encoding);
} }
} }
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using Syroot.BinaryData; using Syroot.BinaryData;
using Syroot.Worms.Core;
namespace Syroot.Worms.OnlineWorms.Server.Net namespace Syroot.Worms.OnlineWorms.Server.Net
{ {

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Syroot.BinaryData; using Syroot.BinaryData;
using Syroot.Worms.Core;
namespace Syroot.Worms.OnlineWorms.Server.Net namespace Syroot.Worms.OnlineWorms.Server.Net
{ {

View File

@ -142,7 +142,7 @@ namespace Syroot.Worms
Offset = (int)writer.Position, Offset = (int)writer.Position,
Length = item.Value.Length Length = item.Value.Length
}; };
writer.Write(item.Value); writer.WriteStructs(item.Value);
int hash = CalculateHash(item.Key); int hash = CalculateHash(item.Key);
if (hashTable[hash] == null) if (hashTable[hash] == null)

View File

@ -80,7 +80,7 @@ namespace Syroot.Worms.Armageddon
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII)) using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII))
{ {
writer.Write(Settings); writer.WriteStruct(Settings);
} }
} }

View File

@ -152,14 +152,14 @@ namespace Syroot.Worms.Armageddon
uint fileSizeOffset = writer.ReserveOffset(); uint fileSizeOffset = writer.ReserveOffset();
// Write the data. // Write the data.
writer.Write(Size); writer.WriteStruct(Size);
writer.Write(TopBorder, BooleanCoding.Dword); writer.Write(TopBorder, BooleanCoding.Dword);
writer.Write(WaterHeight); writer.Write(WaterHeight);
writer.Write(Unknown); writer.Write(Unknown);
// Write the possible object coordinate array. // Write the possible object coordinate array.
writer.Write(ObjectLocations.Length); writer.Write(ObjectLocations.Length);
writer.Write(ObjectLocations); writer.WriteStructs(ObjectLocations);
// Write the image data. // Write the image data.
Foreground.Save(writer.BaseStream); Foreground.Save(writer.BaseStream);

View File

@ -142,7 +142,7 @@ namespace Syroot.Worms.Armageddon.ProjectX
case LibraryItemType.File: case LibraryItemType.File:
byte[] value = (byte[])item.Value; byte[] value = (byte[])item.Value;
writer.Write(value.Length); writer.Write(value.Length);
writer.Write(value); writer.WriteStructs(value);
break; break;
case LibraryItemType.Script: case LibraryItemType.Script:
writer.Write((string)item.Value, StringCoding.Int32CharCount); writer.Write((string)item.Value, StringCoding.Int32CharCount);

View File

@ -153,7 +153,7 @@ namespace Syroot.Worms.Armageddon.ProjectX
writer.Write(Version); writer.Write(Version);
// Write the scheme flags. // Write the scheme flags.
writer.Write(Flags); writer.WriteStruct(Flags);
// Write the weapon tables. // Write the weapon tables.
writer.Write(WeaponTables.Count); writer.Write(WeaponTables.Count);
@ -171,7 +171,7 @@ namespace Syroot.Worms.Armageddon.ProjectX
{ {
writer.Write(file.Key, StringCoding.Int32CharCount); writer.Write(file.Key, StringCoding.Int32CharCount);
writer.Write(file.Value.Length); writer.Write(file.Value.Length);
writer.Write(file.Value); writer.WriteStructs(file.Value);
} }
// Write attached scripts. // Write attached scripts.

View File

@ -749,7 +749,7 @@ namespace Syroot.Worms.Armageddon
int weaponCount = GetWeaponCount(); int weaponCount = GetWeaponCount();
foreach (SchemeWeaponSetting weapon in Weapons) foreach (SchemeWeaponSetting weapon in Weapons)
{ {
writer.Write(weapon); writer.WriteStruct(weapon);
} }
// Ignore possible unknown WWP trash at the end of the file. // Ignore possible unknown WWP trash at the end of the file.

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -9,9 +10,9 @@ namespace Syroot.Worms.Core
/// Represents extension methods for <see cref="BinaryStream"/> instances. /// Represents extension methods for <see cref="BinaryStream"/> instances.
/// </summary> /// </summary>
[DebuggerStepThrough] [DebuggerStepThrough]
internal static partial class BinaryStreamExtensions public static partial class BinaryStreamExtensions
{ {
// ---- METHODS (INTERNAL) ------------------------------------------------------------------------------------- // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
// ---- Reading ---- // ---- Reading ----
@ -21,7 +22,7 @@ namespace Syroot.Worms.Core
/// <typeparam name="T">The type of the <see cref="ILoadable"/> class to instantiate.</typeparam> /// <typeparam name="T">The type of the <see cref="ILoadable"/> class to instantiate.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/>.</param>
/// <returns>The <see cref="ILoadable"/> instance.</returns> /// <returns>The <see cref="ILoadable"/> instance.</returns>
internal static T Load<T>(this BinaryStream self) where T : ILoadable, new() public static T Load<T>(this BinaryStream self) where T : ILoadable, new()
{ {
T instance = new T(); T instance = new T();
instance.Load(self.BaseStream); instance.Load(self.BaseStream);
@ -35,13 +36,11 @@ namespace Syroot.Worms.Core
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/>.</param>
/// <param name="count">The number of instances to read.</param> /// <param name="count">The number of instances to read.</param>
/// <returns>The <see cref="ILoadable"/> instances.</returns> /// <returns>The <see cref="ILoadable"/> instances.</returns>
internal static T[] Load<T>(this BinaryStream self, int count) where T : ILoadable, new() public static T[] Load<T>(this BinaryStream self, int count) where T : ILoadable, new()
{ {
T[] instances = new T[count]; T[] instances = new T[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{
instances[i] = Load<T>(self); instances[i] = Load<T>(self);
}
return instances; return instances;
} }
@ -51,11 +50,13 @@ namespace Syroot.Worms.Core
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/>.</param>
/// <param name="length">The number of bytes the fixed-size blocks takes.</param> /// <param name="length">The number of bytes the fixed-size blocks takes.</param>
/// <returns>The read string.</returns> /// <returns>The read string.</returns>
internal static string ReadFixedString(this BinaryStream self, int length) public static string ReadString(this BinaryStream self, int length)
{ {
string str = self.ReadString(StringCoding.ZeroTerminated); // TODO: This may not work with multi-byte encodings.
self.Seek(length - str.Length - 1); // Ensure to not try to decode any bytes after the 0 termination.
return str; byte[] bytes = self.ReadBytes(length);
while (bytes[--length] == 0 && length > 0) { }
return self.Encoding.GetString(bytes, 0, length + 1);
} }
/// <summary> /// <summary>
@ -66,13 +67,11 @@ namespace Syroot.Worms.Core
/// <param name="count">The number of values to read.</param> /// <param name="count">The number of values to read.</param>
/// <param name="length">The number of bytes the fixed-size blocks takes.</param> /// <param name="length">The number of bytes the fixed-size blocks takes.</param>
/// <returns>The read string.</returns> /// <returns>The read string.</returns>
internal static string[] ReadFixedStrings(this BinaryStream self, int count, int length) public static string[] ReadStrings(this BinaryStream self, int count, int length)
{ {
string[] strings = new string[count]; string[] strings = new string[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ strings[i] = ReadString(self, length);
strings[i] = ReadFixedString(self, length);
}
return strings; return strings;
} }
@ -82,17 +81,17 @@ namespace Syroot.Worms.Core
/// <typeparam name="T">The type of the structure to read.</typeparam> /// <typeparam name="T">The type of the structure to read.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <returns>The structure of type <typeparamref name="T"/>.</returns> /// <returns>The structure of type <typeparamref name="T"/>.</returns>
internal static T ReadStruct<T>(this BinaryStream self) where T : struct public static T ReadStruct<T>(this BinaryStream self) where T : struct
{ {
// Read the raw bytes of the structure. // Read the raw bytes of the structure.
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.
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); using (DisposableGCHandle handle = new DisposableGCHandle(bytes, GCHandleType.Pinned))
T instance = Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject()); {
handle.Free(); T instance = Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject);
return instance;
return instance; }
} }
/// <summary> /// <summary>
@ -102,13 +101,11 @@ namespace Syroot.Worms.Core
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="count">The number of values to read.</param> /// <param name="count">The number of values to read.</param>
/// <returns>The structures of type <typeparamref name="T"/>.</returns> /// <returns>The structures of type <typeparamref name="T"/>.</returns>
internal static T[] ReadStructs<T>(this BinaryStream self, int count) where T : struct public static T[] ReadStructs<T>(this BinaryStream self, int count) where T : struct
{ {
T[] values = new T[count]; T[] values = new T[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{
values[i] = ReadStruct<T>(self); values[i] = ReadStruct<T>(self);
}
return values; return values;
} }
@ -118,7 +115,7 @@ namespace Syroot.Worms.Core
/// </summary> /// </summary>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <returns>The address at which a 4-byte placeholder has been written to.</returns> /// <returns>The address at which a 4-byte placeholder has been written to.</returns>
internal static uint ReserveOffset(this BinaryStream self) public static uint ReserveOffset(this BinaryStream self)
{ {
uint offset = (uint)self.Position; uint offset = (uint)self.Position;
self.WriteUInt32(0); self.WriteUInt32(0);
@ -133,7 +130,7 @@ namespace Syroot.Worms.Core
/// <typeparam name="T">The type of the <see cref="ISaveable"/> class to write.</typeparam> /// <typeparam name="T">The type of the <see cref="ISaveable"/> class to write.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/>.</param>
/// <param name="value">The instance to write into the current stream.</param> /// <param name="value">The instance to write into the current stream.</param>
internal static void Save<T>(this BinaryStream self, T value) where T : ISaveable public static void Save<T>(this BinaryStream self, T value) where T : ISaveable
{ {
value.Save(self.BaseStream); value.Save(self.BaseStream);
} }
@ -144,15 +141,13 @@ namespace Syroot.Worms.Core
/// <typeparam name="T">The type of the <see cref="ISaveable"/> class to write.</typeparam> /// <typeparam name="T">The type of the <see cref="ISaveable"/> class to write.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/>.</param> /// <param name="self">The extended <see cref="BinaryStream"/>.</param>
/// <param name="values">The instances to write into the current stream.</param> /// <param name="values">The instances to write into the current stream.</param>
internal static void Save<T>(this BinaryStream self, T[] values) where T : ISaveable public static void Save<T>(this BinaryStream self, IList<T> values) where T : ISaveable
{ {
foreach (T value in values) foreach (T value in values)
{
Save(self, value); Save(self, value);
}
} }
internal static void SatisfyOffset(this BinaryStream self, uint offset, int value) public static void SatisfyOffset(this BinaryStream self, uint offset, int value)
{ {
using (self.TemporarySeek(offset, SeekOrigin.Begin)) using (self.TemporarySeek(offset, SeekOrigin.Begin))
self.WriteInt32(value); self.WriteInt32(value);
@ -164,11 +159,13 @@ namespace Syroot.Worms.Core
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="value">The string to write.</param> /// <param name="value">The string to write.</param>
/// <param name="length">The number of bytes the fixed-size block takes.</param> /// <param name="length">The number of bytes the fixed-size block takes.</param>
internal static void Write(this BinaryStream self, string value, int length) public static void WriteString(this BinaryStream self, string value, int length)
{ {
byte[] bytes = self.Encoding.GetBytes(value); // TODO: This may not work with multi-byte encodings.
self.Write(bytes); byte[] bytes = new byte[length];
self.Write(new byte[length - bytes.Length]); if (value != null)
self.Encoding.GetBytes(value, 0, value.Length, bytes, 0);
self.WriteBytes(bytes);
} }
/// <summary> /// <summary>
@ -177,12 +174,10 @@ namespace Syroot.Worms.Core
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="values">The strings to write.</param> /// <param name="values">The strings to write.</param>
/// <param name="length">The number of bytes a fixed-size block takes.</param> /// <param name="length">The number of bytes a fixed-size block takes.</param>
internal static void Write(this BinaryStream self, string[] values, int length) public static void WriteStrings(this BinaryStream self, IList<string> values, int length)
{ {
foreach (string value in values) foreach (string value in values)
{ WriteString(self, value, length);
Write(self, value, length);
}
} }
/// <summary> /// <summary>
@ -191,17 +186,16 @@ namespace Syroot.Worms.Core
/// <typeparam name="T">The type of the structure to read.</typeparam> /// <typeparam name="T">The type of the structure to read.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="value">The structure to write.</param> /// <param name="value">The structure to write.</param>
internal static void Write<T>(this BinaryStream self, T value) where T : struct public static void WriteStruct<T>(this BinaryStream self, T value) where T : struct
{ {
// Get the raw bytes of the structure instance. // Get the raw bytes of the structure instance.
byte[] bytes = new byte[Marshal.SizeOf<T>()]; byte[] bytes = new byte[Marshal.SizeOf<T>()];
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); using (DisposableGCHandle handle = new DisposableGCHandle(bytes, GCHandleType.Pinned))
Marshal.StructureToPtr(value, handle.AddrOfPinnedObject(), false); Marshal.StructureToPtr(value, handle.AddrOfPinnedObject, false);
handle.Free();
// Write the bytes to the stream. // Write the bytes to the stream.
self.Write(bytes); self.WriteStructs(bytes);
} }
/// <summary> /// <summary>
@ -210,12 +204,10 @@ namespace Syroot.Worms.Core
/// <typeparam name="T">The type of the structure to read.</typeparam> /// <typeparam name="T">The type of the structure to read.</typeparam>
/// <param name="self">The extended <see cref="BinaryStream"/> instance.</param> /// <param name="self">The extended <see cref="BinaryStream"/> instance.</param>
/// <param name="values">The structures to write.</param> /// <param name="values">The structures to write.</param>
internal static void Write<T>(this BinaryStream self, T[] values) where T : struct public static void WriteStructs<T>(this BinaryStream self, IList<T> values) where T : struct
{ {
foreach (T value in values) foreach (T value in values)
{ WriteStruct(self, value);
Write(self, value);
}
} }
} }
} }

View File

@ -1,4 +1,5 @@
using System.Drawing; using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Syroot.Worms.Core; using Syroot.Worms.Core;
@ -16,11 +17,11 @@ namespace Syroot.Worms.Graphics
/// Creates an indexed <see cref="Bitmap"/> with the given <paramref name="size"/> and /// Creates an indexed <see cref="Bitmap"/> with the given <paramref name="size"/> and
/// <paramref name="palette"/> from the provided raw <paramref name="data"/> array. /// <paramref name="palette"/> from the provided raw <paramref name="data"/> array.
/// </summary> /// </summary>
/// <param name="data">The data array storing bytes indexing the palette color array.</param>
/// <param name="size">The dimensions of the image.</param> /// <param name="size">The dimensions of the image.</param>
/// <param name="palette">The palette as a <see cref="Color"/> array.</param> /// <param name="palette">The palette as a <see cref="Color"/> array.</param>
/// <param name="data">The data array storing bytes indexing the palette color array.</param>
/// <returns>The <see cref="Bitmap"/> instance.</returns> /// <returns>The <see cref="Bitmap"/> instance.</returns>
internal static Bitmap CreateIndexed(byte[] data, Size size, Color[] palette) internal 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))
{ {
@ -34,7 +35,7 @@ namespace Syroot.Worms.Graphics
// Transfer the palette. // Transfer the palette.
ColorPalette bitmapPalette = bitmap.Palette; ColorPalette bitmapPalette = bitmap.Palette;
for (int i = 0; i < palette.Length; i++) for (int i = 0; i < palette.Count; i++)
bitmapPalette.Entries[i] = palette[i]; bitmapPalette.Entries[i] = palette[i];
bitmap.Palette = bitmapPalette; bitmap.Palette = bitmapPalette;

View File

@ -224,7 +224,7 @@ namespace Syroot.Worms
byte[] data = Data; byte[] data = Data;
if (compress) if (compress)
data = Team17Compression.Compress(data); data = Team17Compression.Compress(data);
writer.Write(data); writer.WriteStructs(data);
writer.SatisfyOffset(fileSizeOffset, (int)writer.Position); writer.SatisfyOffset(fileSizeOffset, (int)writer.Position);
} }

View File

@ -95,8 +95,8 @@ namespace Syroot.Worms.OnlineWorms
int dataSizeCompressed = stream.ReadInt32(); int dataSizeCompressed = stream.ReadInt32();
byte[] data = Decompress(stream, dataSizeCompressed, dataSize); byte[] data = Decompress(stream, dataSizeCompressed, dataSize);
// The actual image width is a multiple of 4. // The actual image width is a multiple of 4.
image.Bitmap = BitmapTools.CreateIndexed(data, image.Bitmap = BitmapTools.CreateIndexed(new Size((image.Size.Width + 4 - 1) / 4 * 4, image.Size.Height),
new Size((image.Size.Width + 4 - 1) / 4 * 4, image.Size.Height), palette); palette, data);
Images.Add(image); Images.Add(image);
} }

View File

@ -95,7 +95,7 @@ namespace Syroot.Worms.OnlineWorms
int dataLength = offsets[i + 1] - offset; int dataLength = offsets[i + 1] - offset;
Size size = sizes[i]; Size size = sizes[i];
if (!size.IsEmpty) if (!size.IsEmpty)
images[i].Bitmap = BitmapTools.CreateIndexed(stream.ReadBytes(dataLength), size, palette.Colors); images[i].Bitmap = BitmapTools.CreateIndexed(size, palette.Colors, stream.ReadBytes(dataLength));
Images.Add(images[i]); Images.Add(images[i]);
} }

View File

@ -3,6 +3,7 @@ using System.IO;
using System.IO.MemoryMappedFiles; using System.IO.MemoryMappedFiles;
using System.Net; using System.Net;
using Syroot.BinaryData; using Syroot.BinaryData;
using Syroot.Worms.Core;
namespace Syroot.Worms.OnlineWorms namespace Syroot.Worms.OnlineWorms
{ {
@ -56,7 +57,7 @@ namespace Syroot.Worms.OnlineWorms
using (BinaryStream stream = new BinaryStream(mappedFile.CreateViewStream(), using (BinaryStream stream = new BinaryStream(mappedFile.CreateViewStream(),
encoding: Encodings.Win949, stringCoding: StringCoding.ZeroTerminated)) encoding: Encodings.Win949, stringCoding: StringCoding.ZeroTerminated))
{ {
stream.Write("Online Worms Config File"); stream.WriteString("MGAME", 16);
stream.Position = 36; stream.Position = 36;
stream.Write(_passwordString); stream.Write(_passwordString);

View File

@ -177,19 +177,19 @@ namespace Syroot.Worms
[RiffChunkSave("offl")] [RiffChunkSave("offl")]
private void SaveOfflChunk(BinaryStream writer) private void SaveOfflChunk(BinaryStream writer)
{ {
writer.Write(OfflData); writer.WriteStructs(OfflData);
} }
[RiffChunkSave("tran")] [RiffChunkSave("tran")]
private void SaveTranChunk(BinaryStream writer) private void SaveTranChunk(BinaryStream writer)
{ {
writer.Write(TranData); writer.WriteStructs(TranData);
} }
[RiffChunkSave("unde")] [RiffChunkSave("unde")]
private void SaveUndeChunk(BinaryStream writer) private void SaveUndeChunk(BinaryStream writer)
{ {
writer.Write(UndeData); writer.WriteStructs(UndeData);
} }
} }
} }

View File

@ -5,7 +5,7 @@
<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>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>

View File

@ -140,13 +140,13 @@ namespace Syroot.Worms.WorldParty
uint fileSizeOffset = writer.ReserveOffset(); uint fileSizeOffset = writer.ReserveOffset();
// Write the data. // Write the data.
writer.Write(Size); writer.WriteStruct(Size);
writer.Write(TopBorder, BooleanCoding.Dword); writer.Write(TopBorder, BooleanCoding.Dword);
writer.Write(WaterHeight); writer.Write(WaterHeight);
// Write the possible object coordinate array. // Write the possible object coordinate array.
writer.Write(ObjectLocations.Length); writer.Write(ObjectLocations.Length);
writer.Write(ObjectLocations); writer.WriteStructs(ObjectLocations);
// Write the image data. // Write the image data.
Foreground.Save(writer.BaseStream, false, true); Foreground.Save(writer.BaseStream, false, true);

View File

@ -197,18 +197,18 @@ namespace Syroot.Worms.WorldParty
{ {
using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using (BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true))
{ {
Name = reader.ReadFixedString(17); Name = reader.ReadString(17);
WormNames = reader.ReadFixedStrings(8, 17); WormNames = reader.ReadStrings(8, 17);
CpuLevel = reader.Read1Byte(); CpuLevel = reader.Read1Byte();
SoundBankName = reader.ReadFixedString(0x20); SoundBankName = reader.ReadString(0x20);
SoundBankLocation = reader.Read1Byte(); SoundBankLocation = reader.Read1Byte();
FanfareName = reader.ReadFixedString(0x20); FanfareName = reader.ReadString(0x20);
UseCustomFanfare = reader.Read1Byte(); UseCustomFanfare = reader.Read1Byte();
GraveSprite = reader.ReadSByte(); GraveSprite = reader.ReadSByte();
if (GraveSprite < 0) if (GraveSprite < 0)
{ {
GraveFileName = reader.ReadFixedString(0x20); GraveFileName = reader.ReadString(0x20);
Grave = new RawBitmapData() Grave = new RawBitmapData()
{ {
BitsPerPixel = 8, BitsPerPixel = 8,
@ -231,7 +231,7 @@ namespace Syroot.Worms.WorldParty
DeathmatchDeaths = reader.ReadInt32(); DeathmatchDeaths = reader.ReadInt32();
MissionStatuses = reader.ReadStructs<TeamMissionStatus>(_missionCount); MissionStatuses = reader.ReadStructs<TeamMissionStatus>(_missionCount);
FlagFileName = reader.ReadFixedString(0x20); FlagFileName = reader.ReadString(0x20);
Flag = new RawBitmapData() Flag = new RawBitmapData()
{ {
BitsPerPixel = 8, BitsPerPixel = 8,
@ -257,20 +257,20 @@ namespace Syroot.Worms.WorldParty
{ {
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true)) using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true))
{ {
writer.Write(Name, 17); writer.WriteString(Name, 17);
writer.Write(WormNames, 17); writer.WriteStrings(WormNames, 17);
writer.Write(CpuLevel); writer.Write(CpuLevel);
writer.Write(SoundBankName, 0x20); writer.WriteString(SoundBankName, 0x20);
writer.Write(SoundBankLocation); writer.Write(SoundBankLocation);
writer.Write(FanfareName, 0x20); writer.WriteString(FanfareName, 0x20);
writer.Write(UseCustomFanfare); writer.Write(UseCustomFanfare);
writer.Write(GraveSprite); writer.Write(GraveSprite);
if (GraveSprite < 0) if (GraveSprite < 0)
{ {
writer.Write(GraveFileName, 0x20); writer.WriteString(GraveFileName, 0x20);
writer.Write(Grave.Palette); writer.WriteStructs(Grave.Palette);
writer.Write(Grave.Data); writer.WriteStructs(Grave.Data);
} }
writer.WriteEnum(TeamWeapon, true); writer.WriteEnum(TeamWeapon, true);
@ -284,17 +284,17 @@ namespace Syroot.Worms.WorldParty
writer.Write(DeathmatchKills); writer.Write(DeathmatchKills);
writer.Write(Deaths); writer.Write(Deaths);
writer.Write(DeathmatchDeaths); writer.Write(DeathmatchDeaths);
writer.Write(MissionStatuses); writer.WriteStructs(MissionStatuses);
writer.Write(FlagFileName, 0x20); writer.WriteString(FlagFileName, 0x20);
writer.Write(Flag.Palette); writer.WriteStructs(Flag.Palette);
writer.Write(Flag.Data); writer.WriteStructs(Flag.Data);
writer.Write(Unknown1); writer.Write(Unknown1);
writer.Write(DeathmatchRank); writer.Write(DeathmatchRank);
writer.Write(TrainingMissionTimes); writer.Write(TrainingMissionTimes);
writer.Write(UnknownTrainingMissionTime); writer.Write(UnknownTrainingMissionTime);
writer.Write(WeaponPoints); writer.WriteStructs(WeaponPoints);
writer.Write(Fort); writer.Write(Fort);
writer.Write(Unknown2); writer.Write(Unknown2);
} }

View File

@ -128,7 +128,7 @@ namespace Syroot.Worms.WorldParty
writer.Write((byte)Teams.Count); writer.Write((byte)Teams.Count);
writer.Write(Unknown1); writer.Write(Unknown1);
writer.Write(Unknown2); writer.Write(Unknown2);
writer.Write(Unknown3); writer.WriteStructs(Unknown3);
// Write the teams. // Write the teams.
foreach (Team team in Teams) foreach (Team team in Teams)

View File

@ -146,12 +146,12 @@ namespace Syroot.Worms.Worms2
uint fileSizeOffset = writer.ReserveOffset(); uint fileSizeOffset = writer.ReserveOffset();
// Write the data. // Write the data.
writer.Write(Size); writer.WriteStruct(Size);
writer.Write(TopBorder, BooleanCoding.Dword); writer.Write(TopBorder, BooleanCoding.Dword);
// Write the possible object coordinate array. // Write the possible object coordinate array.
writer.Write(ObjectLocations.Length); writer.Write(ObjectLocations.Length);
writer.Write(ObjectLocations); writer.WriteStructs(ObjectLocations);
writer.Write(Unknown); writer.Write(Unknown);
// Write the image data. // Write the image data.

View File

@ -101,13 +101,13 @@ namespace Syroot.Worms.Worms2
using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII)) using (BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII))
{ {
// Write the header. // Write the header.
writer.Write(new byte[_trashLength]); writer.WriteStructs(new byte[_trashLength]);
writer.Write(_signature, StringCoding.ZeroTerminated); writer.Write(_signature, StringCoding.ZeroTerminated);
// Write the weapon settings. // Write the weapon settings.
foreach (SchemeWeaponSetting weapon in Weapons) foreach (SchemeWeaponSetting weapon in Weapons)
{ {
writer.Write(weapon); writer.WriteStruct(weapon);
} }
} }
} }

View File

@ -28,7 +28,7 @@ namespace Syroot.Worms.Worms2
/// Gets or sets the 8 worm names. /// Gets or sets the 8 worm names.
/// </summary> /// </summary>
public string[] WormNames { get; set; } public string[] WormNames { get; set; }
public int Unknown2 { get; set; } public int Unknown2 { get; set; }
public int Unknown3 { get; set; } public int Unknown3 { get; set; }
public int Unknown4 { get; set; } public int Unknown4 { get; set; }
@ -53,7 +53,7 @@ namespace Syroot.Worms.Worms2
public int Unknown23 { get; set; } public int Unknown23 { get; set; }
public int Unknown24 { get; set; } public int Unknown24 { get; set; }
public int Unknown25 { get; set; } public int Unknown25 { get; set; }
/// <summary> /// <summary>
/// Gets or sets the number of games lost. /// Gets or sets the number of games lost.
/// </summary> /// </summary>
@ -85,7 +85,7 @@ namespace Syroot.Worms.Worms2
public int Unknown28 { get; set; } public int Unknown28 { get; set; }
public int Unknown29 { get; set; } public int Unknown29 { get; set; }
public int Unknown30 { get; set; } public int Unknown30 { get; set; }
/// <summary> /// <summary>
/// Gets or sets the "difference" statistics value. /// Gets or sets the "difference" statistics value.
/// </summary> /// </summary>
@ -95,7 +95,7 @@ namespace Syroot.Worms.Worms2
/// Gets or sets the number of games played, always being 0 for AI controlled teams. /// Gets or sets the number of games played, always being 0 for AI controlled teams.
/// </summary> /// </summary>
public int GamesPlayed { get; set; } public int GamesPlayed { get; set; }
/// <summary> /// <summary>
/// Gets or sets the points gained by this team. /// Gets or sets the points gained by this team.
/// </summary> /// </summary>
@ -112,9 +112,9 @@ namespace Syroot.Worms.Worms2
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.ReadFixedString(66); Name = reader.ReadString(66);
SoundBankName = reader.ReadFixedString(36); SoundBankName = reader.ReadString(36);
WormNames = reader.ReadFixedStrings(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();
@ -164,9 +164,9 @@ namespace Syroot.Worms.Worms2
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.Write(Name, 66); writer.WriteString(Name, 66);
writer.Write(SoundBankName, 36); writer.WriteString(SoundBankName, 36);
writer.Write(WormNames, 20); writer.WriteStrings(WormNames, 20);
writer.Write(Unknown2); writer.Write(Unknown2);
writer.Write(Unknown3); writer.Write(Unknown3);
writer.Write(Unknown4); writer.Write(Unknown4);