Skip to content

Instantly share code, notes, and snippets.

@Thundernerd
Created February 21, 2025 17:50
Show Gist options
  • Save Thundernerd/5c12cdcc8c45aa5b8b07762e6267126f to your computer and use it in GitHub Desktop.
Save Thundernerd/5c12cdcc8c45aa5b8b07762e6267126f to your computer and use it in GitHub Desktop.
public class LevelHasher
{
private const int PresentBlockID = 2264;
private static readonly Vector3Comparer _vector3Comparer = new();
private static readonly IntSequenceComparer _intSequenceComparer = new();
private static readonly FloatSequenceComparer _floatSequenceComparer = new();
private static string Hash(ZeepLevel zeepLevel)
{
if (zeepLevel == null)
{
return null;
}
StringBuilder inputBuilder = new();
inputBuilder.AppendCLRF(zeepLevel.Skybox.ToString());
inputBuilder.AppendCLRF(zeepLevel.Ground.ToString());
List<ZeepBlock> orderedBlocks = zeepLevel.Blocks
.Where(x => x.Id != PresentBlockID)
.OrderBy(x => x.Id)
.ThenBy(x => x.Position, _vector3Comparer)
.ThenBy(x => x.Euler, _vector3Comparer)
.ThenBy(x => x.Scale, _vector3Comparer)
.ThenBy(x => x.Paints, _intSequenceComparer)
.ThenBy(x => x.Options, _floatSequenceComparer)
.ToList();
foreach (ZeepBlock block in orderedBlocks)
{
inputBuilder.AppendCLRF(block.ToString());
}
byte[] hash = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(inputBuilder.ToString()));
StringBuilder hashBuilder = new(hash.Length * 2);
foreach (byte b in hash)
{
hashBuilder.Append(b.ToString("X2"));
}
return hashBuilder.ToString();
}
}
internal class Vector3Comparer : IComparer<Vector3>
{
public int Compare(Vector3 v1, Vector3 v2)
{
int xComparison = v1.x.CompareTo(v2.x);
if (xComparison != 0)
return xComparison;
int yComparison = v1.y.CompareTo(v2.y);
if (yComparison != 0)
return yComparison;
return v1.z.CompareTo(v2.z);
}
}
internal class FloatSequenceComparer : IComparer<List<float>>
{
public int Compare(List<float> x, List<float> y)
{
if (x == null && y == null)
return 0;
if (x == null)
return -1;
if (y == null)
return 1;
int countComparison = x.Count.CompareTo(y.Count);
if (countComparison != 0)
return countComparison;
for (int i = 0; i < x.Count; i++)
{
int elementComparison = x[i].CompareTo(y[i]);
if (elementComparison != 0)
return elementComparison;
}
return 0;
}
}
internal class IntSequenceComparer : IComparer<List<int>>
{
public int Compare(List<int> x, List<int> y)
{
if (x == null && y == null)
return 0;
if (x == null)
return -1;
if (y == null)
return 1;
int countComparison = x.Count.CompareTo(y.Count);
if (countComparison != 0)
return countComparison;
for (int i = 0; i < x.Count; i++)
{
int elementComparison = x[i].CompareTo(y[i]);
if (elementComparison != 0)
return elementComparison;
}
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment