diff --git a/InfectedRose.Utilities/Checksum.cs b/InfectedRose.Utilities/Checksum.cs
index 07ec082..f5b8959 100644
--- a/InfectedRose.Utilities/Checksum.cs
+++ b/InfectedRose.Utilities/Checksum.cs
@@ -8,29 +8,6 @@ namespace InfectedRose.Utilities
{
public static class Checksum
{
- private struct ChecksumLayer
- {
- internal uint Id { get; set; }
-
- internal uint Layer { get; set; }
-
- internal uint Revision { get; set; }
-
- public void Apply(ref uint value, ref uint total)
- {
- foreach (var reference in new[] {Id, Layer, Revision})
- {
- value += reference >> 16; // Apply reference
-
- total += value; // Add to total
-
- value += reference & ushort.MaxValue; // Make ushort
-
- total += value; // Add to total
- }
- }
- }
-
///
/// Calculate the checksum for a LEGO Universe zone
///
@@ -126,6 +103,10 @@ public static uint Generate(string zone)
var lower = (ushort) ((value & ushort.MaxValue) + (value >> 16));
var upper = (ushort) ((total & ushort.MaxValue) + (total >> 16));
+ //
+ // The checksum has two parts, one for the 'total', and one for the 'value', these combine to form a 32bit value
+ //
+
return (uint) (upper << 16 | lower);
}
diff --git a/InfectedRose.Utilities/ChecksumLayer.cs b/InfectedRose.Utilities/ChecksumLayer.cs
new file mode 100644
index 0000000..934e143
--- /dev/null
+++ b/InfectedRose.Utilities/ChecksumLayer.cs
@@ -0,0 +1,25 @@
+namespace InfectedRose.Utilities
+{
+ internal struct ChecksumLayer
+ {
+ internal uint Id { get; set; }
+
+ internal uint Layer { get; set; }
+
+ internal uint Revision { get; set; }
+
+ internal void Apply(ref uint value, ref uint total)
+ {
+ foreach (var reference in new[] {Id, Layer, Revision})
+ {
+ value += reference >> 16; // Apply reference
+
+ total += value; // Add to total
+
+ value += reference & ushort.MaxValue; // Make ushort
+
+ total += value; // Add to total
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/InfectedRose.Utilities/Extensions/LuzFileExtensions.cs b/InfectedRose.Utilities/Extensions/LuzFileExtensions.cs
new file mode 100644
index 0000000..49f63e4
--- /dev/null
+++ b/InfectedRose.Utilities/Extensions/LuzFileExtensions.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using InfectedRose.Luz;
+using InfectedRose.Lvl;
+
+namespace InfectedRose.Utilities
+{
+ public static class LuzFileExtensions
+ {
+ public static uint GenerateChecksum(this LuzFile @this, List scenes)
+ {
+ if (@this.Scenes.Length != scenes.Count)
+ {
+ throw new ArgumentOutOfRangeException(nameof(scenes), "The count of scenes has to equal the count of scenes in this luz file.");
+ }
+
+ uint value = ushort.MaxValue; // For checksum calculations
+ uint total = ushort.MaxValue; // Sum of all changes applied to value
+
+ var zoneLayer = new ChecksumLayer
+ {
+ Id = uint.MaxValue,
+ Layer = default,
+ Revision = @this.RevisionNumber
+ };
+
+ zoneLayer.Apply(ref value, ref total);
+
+ for (var index = 0; index < scenes.Count; index++)
+ {
+ var scene = scenes[index];
+ var lvl = @this.Scenes[index];
+
+ //
+ // Get revision
+ //
+
+ var revision = scene.LevelInfo?.RevisionNumber ?? scene.OldLevelHeader.Revision;
+
+ //
+ // Get layer
+ //
+
+ var sceneLayer = new ChecksumLayer
+ {
+ Id = lvl.SceneId,
+ Layer = lvl.LayerId,
+ Revision = revision
+ };
+
+ sceneLayer.Apply(ref value, ref total);
+ }
+
+ //
+ // Get final checksum
+ //
+
+ var lower = (ushort) ((value & ushort.MaxValue) + (value >> 16));
+ var upper = (ushort) ((total & ushort.MaxValue) + (total >> 16));
+
+ //
+ // The checksum has two parts, one for the 'total', and one for the 'value', these combine to form a 32bit value
+ //
+
+ return (uint) (upper << 16 | lower);
+ }
+ }
+}
\ No newline at end of file
diff --git a/InfectedRose.Utilities/InfectedRose.Utilities.csproj b/InfectedRose.Utilities/InfectedRose.Utilities.csproj
index ca5cc9b..808ca48 100644
--- a/InfectedRose.Utilities/InfectedRose.Utilities.csproj
+++ b/InfectedRose.Utilities/InfectedRose.Utilities.csproj
@@ -1,4 +1,4 @@
-
+
netcoreapp3.1