using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BarrkUI.ChatOverhaul;
using BarrkUI.Compat;
using BarrkUI.Configuration;
using BarrkUI.Layout;
using BarrkUI.Trading;
using BarrkUI.UI;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ServerSync;
using SharedMedia;
using SharedNet;
using SharedUI;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.TextCore;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("VikingOS")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("VikingOS - rebuild Valheim's interface. Move, resize and rotate any UI element, plus chat fixes and item sharing.")]
[assembly: AssemblyFileVersion("0.9.2.0")]
[assembly: AssemblyInformationalVersion("0.9.2+5d942492f9f4a27b0ed403480e9fc3d59ea8eb7d")]
[assembly: AssemblyProduct("VikingOS")]
[assembly: AssemblyTitle("VikingOS")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.9.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace SharedMedia
{
public static class GifDecoder
{
public sealed class Frame
{
public Color32[] Pixels;
public float DelaySeconds;
}
private sealed class Canvas
{
public int Width;
public int Height;
public Color32[] Pixels;
}
public const int MaxDimension = 512;
public const int MaxFrames = 64;
public static bool TryDecode(byte[] bytes, out int width, out int height, out List frames)
{
width = 0;
height = 0;
frames = null;
try
{
return Decode(bytes, 64, out width, out height, out frames);
}
catch
{
frames = null;
return false;
}
}
private static bool Decode(byte[] b, int maxFrames, out int width, out int height, out List frames)
{
width = 0;
height = 0;
frames = null;
if (b == null || b.Length < 13)
{
return false;
}
if (b[0] != 71 || b[1] != 73 || b[2] != 70 || b[3] != 56)
{
return false;
}
if ((b[4] != 55 && b[4] != 57) || b[5] != 97)
{
return false;
}
int num = 6;
width = b[num] | (b[num + 1] << 8);
height = b[num + 2] | (b[num + 3] << 8);
byte b2 = b[num + 4];
num += 7;
if (width <= 0 || height <= 0 || width > 512 || height > 512)
{
return false;
}
Color32[] array = null;
if ((b2 & 0x80) != 0)
{
int size = 2 << (b2 & 7);
array = ReadColourTable(b, ref num, size);
if (array == null)
{
return false;
}
}
Canvas canvas = new Canvas
{
Width = width,
Height = height,
Pixels = (Color32[])(object)new Color32[width * height]
};
frames = new List();
float delaySeconds = 0.1f;
int transparentIndex = -1;
int num2 = 0;
Color32[] array2 = null;
while (num < b.Length)
{
switch (b[num++])
{
case 33:
if (num >= b.Length)
{
return false;
}
if (b[num++] == 249)
{
if (num + 5 >= b.Length)
{
return false;
}
int num7 = b[num++];
if (num7 >= 4)
{
byte num8 = b[num];
num2 = (num8 >> 2) & 7;
int num9 = b[num + 1] | (b[num + 2] << 8);
delaySeconds = ((num9 <= 1) ? 0.1f : ((float)num9 / 100f));
transparentIndex = (((num8 & 1) != 0) ? b[num + 3] : (-1));
}
num += num7;
if (!SkipSubBlocks(b, ref num))
{
return false;
}
}
else if (!SkipSubBlocks(b, ref num))
{
return false;
}
continue;
default:
return false;
case 44:
{
if (num + 9 > b.Length)
{
return false;
}
int num3 = b[num] | (b[num + 1] << 8);
int num4 = b[num + 2] | (b[num + 3] << 8);
int num5 = b[num + 4] | (b[num + 5] << 8);
int num6 = b[num + 6] | (b[num + 7] << 8);
byte b3 = b[num + 8];
num += 9;
if (num5 <= 0 || num6 <= 0 || num3 < 0 || num4 < 0)
{
return false;
}
if (num3 + num5 > width || num4 + num6 > height)
{
return false;
}
bool interlaced = (b3 & 0x40) != 0;
Color32[] array3 = array;
if ((b3 & 0x80) != 0)
{
int size2 = 2 << (b3 & 7);
array3 = ReadColourTable(b, ref num, size2);
}
if (array3 == null)
{
return false;
}
if (num2 == 3)
{
array2 = CopyRegion(canvas, num3, num4, num5, num6);
}
byte[] array4 = DecodeLzwImage(b, ref num, num5, num6);
if (array4 == null)
{
return false;
}
DrawIndices(canvas, array4, array3, transparentIndex, num3, num4, num5, num6, interlaced);
frames.Add(new Frame
{
Pixels = (Color32[])canvas.Pixels.Clone(),
DelaySeconds = delaySeconds
});
if (frames.Count >= maxFrames)
{
break;
}
switch (num2)
{
case 2:
ClearRegion(canvas, num3, num4, num5, num6);
break;
case 3:
if (array2 != null)
{
PasteRegion(canvas, array2, num3, num4, num5, num6);
}
break;
}
delaySeconds = 0.1f;
transparentIndex = -1;
num2 = 0;
continue;
}
case 59:
break;
}
break;
}
return frames.Count > 0;
}
private static Color32[] ReadColourTable(byte[] b, ref int pos, int size)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (pos + size * 3 > b.Length)
{
return null;
}
Color32[] array = (Color32[])(object)new Color32[size];
for (int i = 0; i < size; i++)
{
array[i] = new Color32(b[pos], b[pos + 1], b[pos + 2], byte.MaxValue);
pos += 3;
}
return array;
}
private static bool SkipSubBlocks(byte[] b, ref int pos)
{
while (pos < b.Length)
{
int num = b[pos++];
if (num == 0)
{
return true;
}
pos += num;
}
return false;
}
private static byte[] DecodeLzwImage(byte[] b, ref int pos, int fw, int fh)
{
if (pos >= b.Length)
{
return null;
}
int num = b[pos++];
if (num < 2 || num > 11)
{
return null;
}
List list = new List(1024);
while (pos < b.Length)
{
int num2 = b[pos++];
if (num2 == 0)
{
break;
}
if (pos + num2 > b.Length)
{
return null;
}
for (int i = 0; i < num2; i++)
{
list.Add(b[pos + i]);
}
pos += num2;
}
int num3 = 1 << num;
int num4 = num3 + 1;
int[] array = new int[4096];
byte[] array2 = new byte[4096];
byte[] array3 = new byte[4097];
int num5 = num + 1;
int num6 = num4 + 1;
int num7 = -1;
byte[] array4 = new byte[fw * fh];
int num8 = 0;
int num9 = 0;
int j = 0;
int num10 = 0;
while (num8 < array4.Length)
{
for (; j < num5; j += 8)
{
if (num10 >= list.Count)
{
if (num8 <= 0)
{
return null;
}
return array4;
}
num9 |= list[num10++] << j;
}
int num11 = num9 & ((1 << num5) - 1);
num9 >>= num5;
j -= num5;
if (num11 == num3)
{
num5 = num + 1;
num6 = num4 + 1;
num7 = -1;
continue;
}
if (num11 == num4)
{
break;
}
int num12 = 0;
int num13 = num11;
if (num13 == num6 && num7 >= 0)
{
array3[num12++] = FirstByteOf(array, array2, num7, num3);
num13 = num7;
}
else if (num13 > num6)
{
return null;
}
while (num13 >= num3 + 2)
{
if (num12 >= array3.Length)
{
return null;
}
array3[num12++] = array2[num13];
num13 = array[num13];
}
if (num12 >= array3.Length)
{
return null;
}
array3[num12++] = (byte)num13;
while (num12 > 0 && num8 < array4.Length)
{
array4[num8++] = array3[--num12];
}
if (num7 >= 0 && num6 < 4096)
{
array[num6] = num7;
array2[num6] = FirstByteOf(array, array2, (num11 == num6) ? num7 : num11, num3);
num6++;
if (num6 == 1 << num5 && num5 < 12)
{
num5++;
}
}
num7 = num11;
}
return array4;
}
private static byte FirstByteOf(int[] prefix, byte[] suffix, int code, int clearCode)
{
int num = 0;
while (code >= clearCode + 2)
{
code = prefix[code];
if (++num > 4096)
{
return 0;
}
}
return (byte)code;
}
private static void DrawIndices(Canvas canvas, byte[] indices, Color32[] table, int transparentIndex, int left, int top, int fw, int fh, bool interlaced)
{
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
for (int i = 0; i < ((!interlaced) ? 1 : 4); i++)
{
int num2 = (interlaced ? (new int[4] { 0, 4, 2, 1 })[i] : 0);
int num3 = ((!interlaced) ? 1 : (new int[4] { 8, 8, 4, 2 })[i]);
for (int j = num2; j < fh; j += num3)
{
int num4 = num * fw;
num++;
int num5 = (top + j) * canvas.Width + left;
for (int k = 0; k < fw; k++)
{
int num6 = indices[num4 + k];
if (num6 != transparentIndex && num6 < table.Length)
{
canvas.Pixels[num5 + k] = table[num6];
}
}
}
}
}
private static Color32[] CopyRegion(Canvas canvas, int left, int top, int fw, int fh)
{
Color32[] array = (Color32[])(object)new Color32[fw * fh];
for (int i = 0; i < fh; i++)
{
Array.Copy(canvas.Pixels, (top + i) * canvas.Width + left, array, i * fw, fw);
}
return array;
}
private static void PasteRegion(Canvas canvas, Color32[] region, int left, int top, int fw, int fh)
{
for (int i = 0; i < fh; i++)
{
Array.Copy(region, i * fw, canvas.Pixels, (top + i) * canvas.Width + left, fw);
}
}
private static void ClearRegion(Canvas canvas, int left, int top, int fw, int fh)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
Color32 val = default(Color32);
for (int i = 0; i < fh; i++)
{
int num = (top + i) * canvas.Width + left;
for (int j = 0; j < fw; j++)
{
canvas.Pixels[num + j] = val;
}
}
}
}
public static class GifEncoder
{
public sealed class Frame
{
public Color32[] Pixels;
public float DelaySeconds;
}
private sealed class SubBlockWriter
{
private readonly MemoryStream _out;
private readonly byte[] _buffer = new byte[255];
private int _bufferAt;
private int _bitBuffer;
private int _bitCount;
public SubBlockWriter(MemoryStream output)
{
_out = output;
}
public void WriteBits(int value, int bits)
{
_bitBuffer |= value << _bitCount;
_bitCount += bits;
while (_bitCount >= 8)
{
WriteByte((byte)(_bitBuffer & 0xFF));
_bitBuffer >>= 8;
_bitCount -= 8;
}
}
private void WriteByte(byte b)
{
_buffer[_bufferAt++] = b;
if (_bufferAt >= 255)
{
_out.WriteByte(byte.MaxValue);
_out.Write(_buffer, 0, 255);
_bufferAt = 0;
}
}
public void Flush()
{
if (_bitCount > 0)
{
WriteByte((byte)(_bitBuffer & 0xFF));
}
if (_bufferAt > 0)
{
_out.WriteByte((byte)_bufferAt);
_out.Write(_buffer, 0, _bufferAt);
_bufferAt = 0;
}
_out.WriteByte(0);
_bitBuffer = 0;
_bitCount = 0;
}
}
private const int PaletteSize = 256;
private const int TransparentIndex = 252;
public static byte[] Encode(int width, int height, List frames)
{
if (width <= 0 || height <= 0 || frames == null || frames.Count == 0)
{
return null;
}
using MemoryStream memoryStream = new MemoryStream();
Write(memoryStream, 71, 73, 70, 56, 57, 97);
WriteU16(memoryStream, width);
WriteU16(memoryStream, height);
memoryStream.WriteByte(247);
memoryStream.WriteByte(0);
memoryStream.WriteByte(0);
WritePalette(memoryStream);
Write(memoryStream, 33, 255, 11);
string text = "NETSCAPE2.0";
foreach (char c in text)
{
memoryStream.WriteByte((byte)c);
}
Write(memoryStream, 3, 1, 0, 0, 0);
byte[] indices = new byte[width * height];
foreach (Frame frame in frames)
{
if (frame?.Pixels == null || frame.Pixels.Length < width * height)
{
return null;
}
int v = Mathf.Clamp(Mathf.RoundToInt(frame.DelaySeconds * 100f), 2, 65535);
Write(memoryStream, 33, 249, 4, 9);
WriteU16(memoryStream, v);
memoryStream.WriteByte(252);
memoryStream.WriteByte(0);
memoryStream.WriteByte(44);
WriteU16(memoryStream, 0);
WriteU16(memoryStream, 0);
WriteU16(memoryStream, width);
WriteU16(memoryStream, height);
memoryStream.WriteByte(0);
Quantise(frame.Pixels, indices);
WriteLzw(memoryStream, indices);
}
memoryStream.WriteByte(59);
return memoryStream.ToArray();
}
private static void WritePalette(MemoryStream ms)
{
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 7; j++)
{
for (int k = 0; k < 6; k++)
{
ms.WriteByte((byte)(i * 255 / 5));
ms.WriteByte((byte)(j * 255 / 6));
ms.WriteByte((byte)(k * 255 / 5));
}
}
}
for (int l = 252; l < 256; l++)
{
ms.WriteByte(0);
ms.WriteByte(0);
ms.WriteByte(0);
}
}
private static void Quantise(Color32[] pixels, byte[] indices)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < indices.Length; i++)
{
Color32 val = pixels[i];
if (val.a < 128)
{
indices[i] = 252;
continue;
}
int num = val.r * 6 / 256;
int num2 = val.g * 7 / 256;
int num3 = val.b * 6 / 256;
indices[i] = (byte)((num * 7 + num2) * 6 + num3);
}
}
private static void WriteLzw(MemoryStream ms, byte[] indices)
{
ms.WriteByte(8);
SubBlockWriter subBlockWriter = new SubBlockWriter(ms);
Dictionary dictionary = new Dictionary(4096);
int num = 9;
int num2 = 258;
subBlockWriter.WriteBits(256, num);
int num3 = indices[0];
for (int i = 1; i < indices.Length; i++)
{
int num4 = indices[i];
int key = (num3 << 8) | num4;
if (dictionary.TryGetValue(key, out var value))
{
num3 = value;
continue;
}
subBlockWriter.WriteBits(num3, num);
dictionary[key] = num2;
if (num2 == 1 << num && num < 12)
{
num++;
}
num2++;
if (num2 >= 4096)
{
subBlockWriter.WriteBits(256, num);
dictionary.Clear();
num = 9;
num2 = 258;
}
num3 = num4;
}
subBlockWriter.WriteBits(num3, num);
subBlockWriter.WriteBits(257, num);
subBlockWriter.Flush();
}
private static void Write(MemoryStream ms, params int[] bytes)
{
foreach (int num in bytes)
{
ms.WriteByte((byte)num);
}
}
private static void WriteU16(MemoryStream ms, int v)
{
ms.WriteByte((byte)(v & 0xFF));
ms.WriteByte((byte)((v >> 8) & 0xFF));
}
public static Color32[] Resize(Color32[] src, int srcW, int srcH, int dstW, int dstH)
{
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
Color32[] array = (Color32[])(object)new Color32[dstW * dstH];
if (srcW <= 0 || srcH <= 0 || dstW <= 0 || dstH <= 0)
{
return array;
}
for (int i = 0; i < dstH; i++)
{
float num = ((float)i + 0.5f) / (float)dstH * (float)srcH - 0.5f;
int num2 = Mathf.Clamp(Mathf.FloorToInt(num), 0, srcH - 1);
int num3 = Mathf.Min(num2 + 1, srcH - 1);
float t = Mathf.Clamp01(num - (float)num2);
for (int j = 0; j < dstW; j++)
{
float num4 = ((float)j + 0.5f) / (float)dstW * (float)srcW - 0.5f;
int num5 = Mathf.Clamp(Mathf.FloorToInt(num4), 0, srcW - 1);
int num6 = Mathf.Min(num5 + 1, srcW - 1);
float t2 = Mathf.Clamp01(num4 - (float)num5);
array[i * dstW + j] = Lerp(Lerp(src[num2 * srcW + num5], src[num2 * srcW + num6], t2), Lerp(src[num3 * srcW + num5], src[num3 * srcW + num6], t2), t);
}
}
return array;
}
private static Color32 Lerp(Color32 a, Color32 b, float t)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
return new Color32((byte)((float)(int)a.r + (float)(b.r - a.r) * t), (byte)((float)(int)a.g + (float)(b.g - a.g) * t), (byte)((float)(int)a.b + (float)(b.b - a.b) * t), (byte)((float)(int)a.a + (float)(b.a - a.a) * t));
}
}
}
namespace SharedNet
{
public sealed class BlobLibrary
{
public enum BlobKind : byte
{
Png,
Gif
}
public sealed class Entry
{
public string Name;
public string Hash;
public BlobKind Kind;
public int Width;
public int Height;
public int Length;
}
public sealed class Limits
{
public int MaxBytes = 98304;
public int MaxWidth = 256;
public int MaxHeight = 256;
public int MaxCount = 64;
public bool AcceptGif;
public Func OversizeRewriter;
}
private sealed class Incoming
{
public byte[][] Chunks;
public int Received;
public int Total;
public float LastChunkAt;
}
private const byte CatalogueVersion = 1;
private const int ChunkBytes = 32768;
private const float TransferTimeoutSeconds = 15f;
private readonly string _name;
private readonly string _fetchRpc;
private readonly string _chunkRpc;
private readonly string _reloadRpc;
private readonly string _reloadReplyRpc;
private readonly CustomSyncedValue _catalogue;
private readonly Func _packFolder;
private readonly string _cacheDir;
private readonly Limits _limits;
private readonly Func _sharingEnabled;
private readonly Func _host;
private readonly Action _logInfo;
private readonly Action _logWarning;
private readonly Action _logError;
private readonly Dictionary _decoded = new Dictionary(StringComparer.OrdinalIgnoreCase);
private string _decodedFrom;
private readonly List _packEntries = new List();
private readonly Dictionary _serverBlobs = new Dictionary(StringComparer.OrdinalIgnoreCase);
private bool _serverScanned;
private readonly HashSet _have = new HashSet(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary _requested = new Dictionary(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary _transfers = new Dictionary(StringComparer.OrdinalIgnoreCase);
private Coroutine _pump;
private Action _reloadReply;
public int Revision { get; private set; }
public event Action Changed;
public BlobLibrary(string name, string rpcPrefix, CustomSyncedValue catalogue, Func packFolder, string cacheDir, Limits limits, Func sharingEnabled, Func coroutineHost, Action logInfo, Action logWarning, Action logError)
{
_name = name;
_fetchRpc = rpcPrefix + "_Fetch";
_chunkRpc = rpcPrefix + "_Chunk";
_reloadRpc = rpcPrefix + "_Reload";
_reloadReplyRpc = rpcPrefix + "_Reloaded";
_catalogue = catalogue;
_packFolder = packFolder;
_cacheDir = cacheDir;
_limits = limits ?? new Limits();
_sharingEnabled = sharingEnabled ?? ((Func)(() => true));
_host = coroutineHost;
_logInfo = logInfo ?? ((Action)delegate
{
});
_logWarning = logWarning ?? ((Action)delegate
{
});
_logError = logError ?? ((Action)delegate
{
});
}
public void OnSessionStart()
{
try
{
if (ZRoutedRpc.instance == null)
{
return;
}
ZRoutedRpc.instance.Register(_fetchRpc, (Action)RPC_Fetch);
ZRoutedRpc.instance.Register(_chunkRpc, (Action)RPC_Chunk);
ZRoutedRpc.instance.Register(_reloadRpc, (Action)RPC_Reload);
ZRoutedRpc.instance.Register(_reloadReplyRpc, (Action)RPC_Reloaded);
if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
{
ScanServerPack();
Publish();
}
MonoBehaviour val = _host?.Invoke();
if ((Object)(object)val != (Object)null)
{
if (_pump != null)
{
val.StopCoroutine(_pump);
}
_pump = val.StartCoroutine(ClientPump());
}
}
catch (Exception arg)
{
_logError($"could not start the {_name} library (non-fatal, the feature idles this session). Reason: {arg}");
}
}
public void OnSessionEnd()
{
try
{
MonoBehaviour val = _host?.Invoke();
if (_pump != null && (Object)(object)val != (Object)null)
{
val.StopCoroutine(_pump);
}
_pump = null;
_decoded.Clear();
_decodedFrom = null;
_packEntries.Clear();
_serverBlobs.Clear();
_serverScanned = false;
_have.Clear();
_requested.Clear();
_transfers.Clear();
Bump();
}
catch (Exception arg)
{
_logError($"tearing down the {_name} library failed (non-fatal). Reason: {arg}");
}
}
private void Bump()
{
Revision++;
try
{
this.Changed?.Invoke();
}
catch (Exception arg)
{
_logError($"a {_name} change handler threw (non-fatal). Reason: {arg}");
}
}
public Entry Find(string name)
{
if (string.IsNullOrEmpty(name))
{
return null;
}
EnsureDecoded();
if (!_decoded.TryGetValue(name, out var value))
{
return null;
}
return value;
}
public List Entries()
{
EnsureDecoded();
return new List(_decoded.Values);
}
public bool HasBlob(string hash)
{
if (!string.IsNullOrEmpty(hash))
{
return File.Exists(CachePath(hash));
}
return false;
}
public byte[] TryReadBytes(Entry entry)
{
if (entry == null)
{
return null;
}
try
{
string path = CachePath(entry.Hash);
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
if (_serverBlobs.TryGetValue(entry.Hash, out var value) && File.Exists(value))
{
return File.ReadAllBytes(value);
}
}
catch (Exception arg)
{
_logError($"reading a cached {_name} failed (non-fatal). Reason: {arg}");
}
return null;
}
private string CachePath(string hash)
{
return Path.Combine(_cacheDir, hash + ".bin");
}
private void EnsureDecoded()
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Expected O, but got Unknown
string text = _catalogue.Value ?? "";
if (text == _decodedFrom)
{
return;
}
_decodedFrom = text;
_decoded.Clear();
try
{
if (string.IsNullOrEmpty(text))
{
Bump();
return;
}
ZPackage val = new ZPackage(text);
byte b = val.ReadByte();
if (b != 1)
{
_logWarning($"the server's {_name} catalogue is format {b}, not {(byte)1} - ignoring it.");
Bump();
return;
}
int num = val.ReadInt();
for (int i = 0; i < num; i++)
{
Entry entry = new Entry
{
Name = val.ReadString(),
Hash = val.ReadString(),
Kind = (BlobKind)val.ReadByte(),
Width = val.ReadInt(),
Height = val.ReadInt(),
Length = val.ReadInt()
};
if (!string.IsNullOrEmpty(entry.Name) && !string.IsNullOrEmpty(entry.Hash))
{
_decoded[entry.Name] = entry;
}
}
Bump();
}
catch (Exception arg)
{
_decoded.Clear();
_logError($"the server's {_name} catalogue could not be read (non-fatal). Reason: {arg}");
}
}
public int ScanServerPack()
{
_serverBlobs.Clear();
_serverScanned = true;
try
{
string text = _packFolder();
List list = new List();
if (Directory.Exists(text))
{
list.AddRange(Directory.GetFiles(text, "*.png", SearchOption.TopDirectoryOnly));
if (_limits.AcceptGif)
{
list.AddRange(Directory.GetFiles(text, "*.gif", SearchOption.TopDirectoryOnly));
}
}
list.Sort(StringComparer.OrdinalIgnoreCase);
int num = 0;
foreach (string item in list)
{
if (num >= _limits.MaxCount)
{
_logWarning($"the {_name} pack holds more than {_limits.MaxCount} files - the rest are not offered to clients.");
break;
}
if (RegisterPackFile(item))
{
num++;
}
}
_logInfo($"offering {num} {_name}(s) to clients from {text}.");
return num;
}
catch (Exception arg)
{
_logError($"could not scan the {_name} pack (non-fatal). Reason: {arg}");
return 0;
}
}
private bool RegisterPackFile(string path)
{
try
{
string name = Path.GetFileNameWithoutExtension(path);
byte[] array = File.ReadAllBytes(path);
if (!Identify(array, out var kind, out var w, out var h))
{
_logWarning("not offering '" + Path.GetFileName(path) + "' - it is not a readable PNG" + (_limits.AcceptGif ? " or GIF" : "") + ".");
return false;
}
if (array.Length > _limits.MaxBytes || w > _limits.MaxWidth || h > _limits.MaxHeight)
{
byte[] array2 = _limits.OversizeRewriter?.Invoke(path, array);
if (array2 == null || array2.Length > _limits.MaxBytes || !Identify(array2, out kind, out w, out h) || w > _limits.MaxWidth || h > _limits.MaxHeight)
{
_logWarning("not offering '" + Path.GetFileName(path) + "' - over the limits " + $"({_limits.MaxBytes / 1024} KB, {_limits.MaxWidth}x{_limits.MaxHeight}) and it could not be shrunk to fit.");
return false;
}
Directory.CreateDirectory(_cacheDir);
string text = Path.Combine(_cacheDir, "pack-" + HashOf(array2) + ".bin");
File.WriteAllBytes(text, array2);
_logInfo($"'{Path.GetFileName(path)}' was over the limits and has been shrunk to {array2.Length / 1024} KB ({w}x{h}) for transfer.");
array = array2;
path = text;
}
string text2 = HashOf(array);
_serverBlobs[text2] = path;
_packEntries.RemoveAll((Entry e) => string.Equals(e.Name, name, StringComparison.OrdinalIgnoreCase));
_packEntries.Add(new Entry
{
Name = name,
Hash = text2,
Kind = kind,
Width = w,
Height = h,
Length = array.Length
});
return true;
}
catch (Exception arg)
{
_logError($"could not read '{path}' (non-fatal, it is skipped). Reason: {arg}");
return false;
}
}
private bool Identify(byte[] bytes, out BlobKind kind, out int w, out int h)
{
if (ReadPngHeader(bytes, out w, out h))
{
kind = BlobKind.Png;
return true;
}
if (_limits.AcceptGif && ReadGifHeader(bytes, out w, out h))
{
kind = BlobKind.Gif;
return true;
}
kind = BlobKind.Png;
return false;
}
public void Publish()
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Expected O, but got Unknown
try
{
if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
{
return;
}
if (!_sharingEnabled())
{
_catalogue.Value = "";
return;
}
if (!_serverScanned)
{
ScanServerPack();
}
ZPackage val = new ZPackage();
val.Write((byte)1);
val.Write(_packEntries.Count);
foreach (Entry packEntry in _packEntries)
{
val.Write(packEntry.Name);
val.Write(packEntry.Hash);
val.Write((byte)packEntry.Kind);
val.Write(packEntry.Width);
val.Write(packEntry.Height);
val.Write(packEntry.Length);
}
_catalogue.Value = val.GetBase64();
}
catch (Exception arg)
{
_logError($"publishing the {_name} catalogue failed (non-fatal, clients keep the previous one). Reason: {arg}");
}
}
public int Reload()
{
_packEntries.Clear();
int result = ScanServerPack();
Publish();
return result;
}
public void RequestReload(Action reply)
{
_reloadReply = reply;
if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
{
int num = Reload();
reply?.Invoke($"now offering {num} {_name}(s).");
return;
}
ZRoutedRpc instance = ZRoutedRpc.instance;
if (instance != null)
{
instance.InvokeRoutedRPC(_reloadRpc, Array.Empty