diff --git a/OpenRA.Game/FieldLoader.cs b/OpenRA.Game/FieldLoader.cs index 61ea993c39..7bd075e9f8 100644 --- a/OpenRA.Game/FieldLoader.cs +++ b/OpenRA.Game/FieldLoader.cs @@ -16,6 +16,7 @@ using System.Drawing.Imaging; using System.Globalization; using System.Linq; using System.Reflection; +using System.Runtime.Serialization; using System.Text.RegularExpressions; using OpenRA.Graphics; using OpenRA.Primitives; @@ -24,6 +25,7 @@ namespace OpenRA { public static class FieldLoader { + [Serializable] public class MissingFieldsException : YamlException { public readonly string[] Missing; @@ -42,6 +44,13 @@ namespace OpenRA Header = missing.Length > 1 ? header : headerSingle ?? header; Missing = missing; } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue("Missing", Missing); + info.AddValue("Header", Header); + } } public static Func InvalidValueAction = (s, t, f) => diff --git a/OpenRA.Game/FileSystem/InstallShieldCABExtractor.cs b/OpenRA.Game/FileSystem/InstallShieldCABExtractor.cs index 9086d90c33..8046394460 100644 --- a/OpenRA.Game/FileSystem/InstallShieldCABExtractor.cs +++ b/OpenRA.Game/FileSystem/InstallShieldCABExtractor.cs @@ -17,7 +17,7 @@ using ICSharpCode.SharpZipLib.Zip.Compression; namespace OpenRA.FileSystem { - public class InstallShieldCABExtractor : IFolder + public sealed class InstallShieldCABExtractor : IFolder { const uint FileSplit = 0x1; const uint FileObfuscated = 0x2; diff --git a/OpenRA.Game/GlobalChat.cs b/OpenRA.Game/GlobalChat.cs index 6ad2faf6c9..2e25b1d48e 100644 --- a/OpenRA.Game/GlobalChat.cs +++ b/OpenRA.Game/GlobalChat.cs @@ -66,7 +66,7 @@ namespace OpenRA.Chat } } - public class GlobalChat : IDisposable + public sealed class GlobalChat : IDisposable { readonly IrcClient client = new IrcClient(); volatile Channel channel; diff --git a/OpenRA.Game/Graphics/HardwareCursor.cs b/OpenRA.Game/Graphics/HardwareCursor.cs index f77d00aff5..0512799685 100644 --- a/OpenRA.Game/Graphics/HardwareCursor.cs +++ b/OpenRA.Game/Graphics/HardwareCursor.cs @@ -17,7 +17,7 @@ using OpenRA.Primitives; namespace OpenRA.Graphics { - public class HardwareCursor : ICursor + public sealed class HardwareCursor : ICursor { readonly Dictionary hardwareCursors = new Dictionary(); readonly CursorProvider cursorProvider; diff --git a/OpenRA.Game/Graphics/SoftwareCursor.cs b/OpenRA.Game/Graphics/SoftwareCursor.cs index 09725f1957..9be1f80b31 100644 --- a/OpenRA.Game/Graphics/SoftwareCursor.cs +++ b/OpenRA.Game/Graphics/SoftwareCursor.cs @@ -24,7 +24,7 @@ namespace OpenRA.Graphics void Tick(); } - public class SoftwareCursor : ICursor + public sealed class SoftwareCursor : ICursor { readonly HardwarePalette palette = new HardwarePalette(); readonly Cache paletteReferences; diff --git a/OpenRA.Game/Graphics/SpriteFont.cs b/OpenRA.Game/Graphics/SpriteFont.cs index 2d719d0ee6..d23bc0a728 100644 --- a/OpenRA.Game/Graphics/SpriteFont.cs +++ b/OpenRA.Game/Graphics/SpriteFont.cs @@ -17,7 +17,7 @@ using SharpFont; namespace OpenRA.Graphics { - public class SpriteFont + public sealed class SpriteFont : IDisposable { static readonly Library Library = new Library(); @@ -150,6 +150,11 @@ namespace OpenRA.Graphics return g; } + + public void Dispose() + { + face.Dispose(); + } } class GlyphInfo diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index 157362adc6..114ddbd98b 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -91,6 +91,9 @@ namespace OpenRA public void InitializeFonts(Manifest m) { + if (Fonts != null) + foreach (var font in Fonts.Values) + font.Dispose(); using (new Support.PerfTimer("SpriteFonts")) { if (fontSheetBuilder != null) @@ -175,7 +178,7 @@ namespace OpenRA public Size Resolution { get { return Device.WindowSize; } } - public interface IBatchRenderer { void Flush(); } + public interface IBatchRenderer { void Flush(); } public IBatchRenderer CurrentBatchRenderer { @@ -254,6 +257,9 @@ namespace OpenRA tempBuffer.Dispose(); if (fontSheetBuilder != null) fontSheetBuilder.Dispose(); + if (Fonts != null) + foreach (var font in Fonts.Values) + font.Dispose(); } public string GetClipboardText() diff --git a/OpenRA.Mods.Cnc/CncLoadScreen.cs b/OpenRA.Mods.Cnc/CncLoadScreen.cs index aedc046d1f..45dcb89473 100644 --- a/OpenRA.Mods.Cnc/CncLoadScreen.cs +++ b/OpenRA.Mods.Cnc/CncLoadScreen.cs @@ -124,12 +124,12 @@ namespace OpenRA.Mods.Cnc r.EndFrame(nih); } - public override void Dispose() + protected override void Dispose(bool disposing) { - if (sheet != null) + if (disposing && sheet != null) sheet.Dispose(); - base.Dispose(); + base.Dispose(disposing); } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Commands/DevCommands.cs b/OpenRA.Mods.Common/Commands/DevCommands.cs index dff76295e9..7e2e4bad79 100644 --- a/OpenRA.Mods.Common/Commands/DevCommands.cs +++ b/OpenRA.Mods.Common/Commands/DevCommands.cs @@ -125,6 +125,7 @@ namespace OpenRA.Mods.Common.Commands world.IssueOrder(new Order(command, world.LocalPlayer.PlayerActor, false)); } + [Serializable] class DevException : Exception { } } } diff --git a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs index ef0964e987..1c11bd2745 100644 --- a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs @@ -90,6 +90,12 @@ namespace OpenRA.Mods.Common.LoadScreens Game.Settings.Save(); } - public virtual void Dispose() { } + protected virtual void Dispose(bool disposing) { } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs index 150f9b65b2..429080f115 100644 --- a/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs @@ -79,12 +79,12 @@ namespace OpenRA.Mods.Common.LoadScreens r.EndFrame(new NullInputHandler()); } - public override void Dispose() + protected override void Dispose(bool disposing) { - if (sheet != null) + if (disposing && sheet != null) sheet.Dispose(); - base.Dispose(); + base.Dispose(disposing); } } } diff --git a/OpenRA.Mods.Common/Widgets/RadarWidget.cs b/OpenRA.Mods.Common/Widgets/RadarWidget.cs index 06b263be49..bc88244422 100644 --- a/OpenRA.Mods.Common/Widgets/RadarWidget.cs +++ b/OpenRA.Mods.Common/Widgets/RadarWidget.cs @@ -19,7 +19,7 @@ using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets { - public class RadarWidget : Widget + public sealed class RadarWidget : Widget, IDisposable { public string WorldInteractionController = null; public int AnimationLength = 5; @@ -447,6 +447,12 @@ namespace OpenRA.Mods.Common.Widgets base.Removed(); world.Map.MapTiles.Value.CellEntryChanged -= UpdateTerrainCell; world.Map.CustomTerrain.CellEntryChanged -= UpdateTerrainCell; + Dispose(); + } + + public void Dispose() + { + radarSheet.Dispose(); } } } diff --git a/OpenRA.Platforms.Default/OpenAlSoundEngine.cs b/OpenRA.Platforms.Default/OpenAlSoundEngine.cs index 914e507879..6d23802d8f 100644 --- a/OpenRA.Platforms.Default/OpenAlSoundEngine.cs +++ b/OpenRA.Platforms.Default/OpenAlSoundEngine.cs @@ -304,13 +304,24 @@ namespace OpenRA.Platforms.Default AL10.alListenerf(EFX.AL_METERS_PER_UNIT, .01f); } + ~OpenAlSoundEngine() + { + Game.RunAfterTick(() => Dispose(false)); + } + public void Dispose() { - if (device == IntPtr.Zero) - return; + Game.RunAfterTick(() => Dispose(true)); + GC.SuppressFinalize(this); + } - ALC10.alcCloseDevice(device); - device = IntPtr.Zero; + void Dispose(bool disposing) + { + if (device != IntPtr.Zero) + { + ALC10.alcCloseDevice(device); + device = IntPtr.Zero; + } } } diff --git a/OpenRA.Test/OpenRA.Game/CoordinateTest.cs b/OpenRA.Test/OpenRA.Game/CoordinateTest.cs index 77cc56e84f..c89a75fcab 100644 --- a/OpenRA.Test/OpenRA.Game/CoordinateTest.cs +++ b/OpenRA.Test/OpenRA.Game/CoordinateTest.cs @@ -31,14 +31,14 @@ namespace OpenRA.Test { Assert.That(cell, Is.EqualTo(cell.ToMPos(gridType).ToCPos(gridType))); } - catch (Exception e) + catch { // Known problem on isometric mods that shouldn't be visible to players as these are outside the map. if (gridType == MapGridType.RectangularIsometric && y > x) continue; Console.WriteLine("Coordinate {0} on grid type {1} failed to convert back.".F(cell, gridType)); - throw e; + throw; } } } diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs index 9c9cf976ab..82304cdeff 100644 --- a/OpenRA.Utility/Program.cs +++ b/OpenRA.Utility/Program.cs @@ -11,9 +11,11 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; namespace OpenRA.Utility { + [Serializable] public class NoSuchCommandException : Exception { public readonly string Command; @@ -22,6 +24,12 @@ namespace OpenRA.Utility { Command = command; } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue("Command", Command); + } } class Program