Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flag modded levels + per-user mod filtering #638

Merged
merged 15 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Refresh.Common/Helpers/ByteArrayComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Refresh.Common.Helpers;

public class ByteArrayComparer : IEqualityComparer<byte[]> {
public bool Equals(byte[]? a, byte[]? b)
{
// If either are null and they arent equal, early return
if (a == null || b == null && a != b)
return false;

if (a.Length != b.Length)
return false;

return a.SequenceEqual(b);
}

public int GetHashCode(byte[] arr)
{
uint hashCode = 0;
foreach (byte b in arr)
hashCode = ((hashCode << 23) | (hashCode >> 9)) ^ b;

return unchecked((int)hashCode);
}
}
71 changes: 71 additions & 0 deletions Refresh.Common/Helpers/HexHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Runtime.CompilerServices;

namespace Refresh.Common.Helpers;

public static class HexHelper
{
/// <summary>
/// Converts a byte array to a hex string
/// </summary>
/// <param name="data">The hex bytes</param>
/// <returns>The hex string</returns>
public static string BytesToHexString(ReadOnlySpan<byte> data)
{
Span<char> hexChars = stackalloc char[data.Length * 2];

for (int i = 0; i < data.Length; i++)
{
byte b = data[i];
hexChars[i * 2] = GetHexChar(b >> 4); // High bits
hexChars[i * 2 + 1] = GetHexChar(b & 0x0F); // Low bits
}

return new string(hexChars);
}

/// <summary>
/// Converts a hex string to a byte array
/// </summary>
/// <param name="hex"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static byte[] HexStringToBytes(string hex)
{
if (hex.Length % 2 != 0)
throw new FormatException("The hex string is invalid as it contains an odd number of bytes.");

// Two hex digits per byte
byte[] arr = new byte[hex.Length / 2];

for (int i = 0; i < arr.Length; ++i)
// The bitmasks may seem redundant, but from my testing it consistently improves perf by ~10%,
// probably because the compiler/JIT knows it can omit range checks in the byte -> int cast
arr[i] = (byte)(((GetHexVal(hex[i * 2]) << 4) & 0xF0) + (GetHexVal(hex[i * 2 + 1]) & 0x0F));

return arr;
}

/// <summary>
/// Gets the 4 bit value of the single hex digit
/// </summary>
/// <param name="hex">The hex digit</param>
/// <returns>The 4 bit value of the digit</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static int GetHexVal(char hex)
{
int val = hex;
return val - (val < 58 ? 48 : 87);
}

/// <summary>
/// Gets the hex digit for a 4-bit value
/// </summary>
/// <param name="value">The 4 bit value</param>
/// <returns>The hex digit</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static char GetHexChar(int value)
{
return (char)(value < 10 ? '0' + value : 'a' + value - 10);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
using FastAes;
using IronCompress;

namespace Refresh.GameServer.Resources;
namespace Refresh.Common.Helpers;

public static class ResourceHelper
{
public static Stream StreamFromResource(string name, Assembly? assembly = null)
{
assembly ??= Assembly.GetExecutingAssembly();
assembly ??= Assembly.GetCallingAssembly();
return assembly.GetManifestResourceStream(name)!;
}

Expand Down
37 changes: 37 additions & 0 deletions Refresh.Common/Helpers/VanillaHashChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Collections.Frozen;

namespace Refresh.Common.Helpers;

public static class VanillaHashChecker
{
// A hashset of all the vanilla hashes.
// This would be a FrozenSet<string> since we use strings for hashes everywhere else,
// but the perf was like 2x worse and it took 4x the memory,
// even with the overhead of the string -> byte[] conversion, each check is cheaper this way.
private static readonly FrozenSet<byte[]> VanillaHashes;

static VanillaHashChecker()
{
HashSet<byte[]> set = new(new ByteArrayComparer());

using Stream stream = ResourceHelper.StreamFromResource("Refresh.Common.Resources.all_hashes.txt");

StreamReader reader = new(stream);

//Read all the lines
while (reader.ReadLine() is {} line)
{
//Parse out and add each line to the set
set.Add(HexHelper.HexStringToBytes(line));
}

VanillaHashes = set.ToFrozenSet(new ByteArrayComparer());
}

public static bool IsVanillaHash(string hash)
{
byte[] hashArr = HexHelper.HexStringToBytes(hash);

return VanillaHashes.Contains(hashArr);
}
}
6 changes: 6 additions & 0 deletions Refresh.Common/Refresh.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@
<ItemGroup>
<PackageReference Include="Bunkum" Version="4.8.1" />
<PackageReference Include="Bunkum.Protocols.Http" Version="4.8.1" />
<PackageReference Include="FastAes" Version="1.0.1" />
<PackageReference Include="IronCompress" Version="1.5.2" />
<PackageReference Include="NPTicket" Version="3.1.0" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Resources\all_hashes.txt" />
</ItemGroup>

</Project>
Loading
Loading