using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using ChainedPuzzles;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.InteropTypes.Fields;
using MTFO.API;
using MTFO.Ext.Scans.CustomPuzzleData;
using MTFO.Ext.Scans.Dependencies;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MTFO.Ext.Scans")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+349c70f1c1d37e8182a07fdab5300ec4112b78f5")]
[assembly: AssemblyProduct("MTFO.Ext.Scans")]
[assembly: AssemblyTitle("MTFO.Ext.Scans")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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;
}
}
}
namespace MTFO.Ext.Scans
{
internal static class DinoLogger
{
private static ManualLogSource logger = Logger.CreateLogSource("MTFO.Ext.Scans");
public static void Log(string format, params object[] args)
{
Log(string.Format(format, args));
}
public static void Log(string str)
{
if (logger != null)
{
logger.Log((LogLevel)8, (object)str);
}
}
public static void Warning(string format, params object[] args)
{
Warning(string.Format(format, args));
}
public static void Warning(string str)
{
if (logger != null)
{
logger.Log((LogLevel)4, (object)str);
}
}
public static void Error(string format, params object[] args)
{
Error(string.Format(format, args));
}
public static void Error(string str)
{
if (logger != null)
{
logger.Log((LogLevel)2, (object)str);
}
}
public static void Debug(string format, params object[] args)
{
Debug(string.Format(format, args));
}
public static void Debug(string str)
{
if (logger != null)
{
logger.Log((LogLevel)32, (object)str);
}
}
}
[BepInPlugin("MTFO.Extension.Scans", "MTFO.Ext.Scans", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal sealed class EntryPoint : BasePlugin
{
public const string MODNAME = "MTFO.Ext.Scans";
public override void Load()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
if (!MTFOWrapper.HasCustomContent)
{
((BasePlugin)this).Log.LogMessage((object)"No Custom folder, not loading...");
return;
}
if (MTFOWrapper.GetCorePuzzleData == null)
{
DinoLogger.Error("Unable to find method to get CorePuzzleData, not loading...");
return;
}
ScanDataManager.Init();
new Harmony("MTFO.Ext.Scans").PatchAll();
((BasePlugin)this).Log.LogMessage((object)"Loaded MTFO.Ext.Scans");
}
}
}
namespace MTFO.Ext.Scans.Patches
{
[HarmonyPatch]
internal static class ScannerPatches
{
[HarmonyPatch(typeof(CP_PlayerScanner), "StartScan")]
[HarmonyPriority(600)]
[HarmonyPrefix]
private static void ApplyScanSpeed(CP_PlayerScanner __instance)
{
if (!SNet.IsMaster || __instance.m_scanActive || !ScanDataManager.TryGetScanData(((Component)__instance).gameObject, out ScanData data))
{
return;
}
int count = PlayerManager.PlayerAgentsInLevel.Count;
if (data.PerTeamSizeScanMultis != null && TryGetScanMultis(data.PerTeamSizeScanMultis, count, out float[] scanMultis))
{
if (scanMultis.Length > 4)
{
__instance.m_scanSpeeds = Il2CppStructArray<float>.op_Implicit(new float[scanMultis.Length]);
}
for (int i = 0; i < ((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds).Length; i++)
{
((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds)[i] = scanMultis[Math.Min(i, scanMultis.Length - 1)];
}
}
if (data.FullTeamScanMulti != 0f)
{
((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds)[count - 1] = data.FullTeamScanMulti;
}
}
private static bool TryGetScanMultis(float[][] lists, int playerCount, [MaybeNullWhen(false)] out float[] scanMultis)
{
for (int i = playerCount - 1; i < lists.Length; i++)
{
if (lists[i].Length != 0)
{
scanMultis = lists[i];
return true;
}
}
scanMultis = null;
return false;
}
}
}
namespace MTFO.Ext.Scans.Dependencies
{
internal static class MTFOWrapper
{
public const string PLUGIN_GUID = "com.dak.MTFO";
public static readonly MethodInfo GetCorePuzzleData;
public static readonly FieldInfo GetCorePuzzleDataID;
public static string GameDataPath => MTFOPathAPI.RundownPath;
public static string CustomPath => MTFOPathAPI.CustomPath;
public static bool HasCustomContent => MTFOPathAPI.HasRundownPath;
static MTFOWrapper()
{
PluginInfo val = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins["com.dak.MTFO"];
try
{
Type type = (((val == null) ? null : val.Instance?.GetType()?.Assembly) ?? throw new Exception("Assembly is missing!")).GetTypes().First((Type t) => t.Name == "CorePuzzleData");
if ((object)type == null)
{
throw new Exception("Unable to find CorePuzzleData class!");
}
GetCorePuzzleDataID = type.GetField("PersistentID", BindingFlags.Instance | BindingFlags.Public);
if ((object)GetCorePuzzleDataID == null)
{
throw new Exception("Unable to find PersistentID field in CorePuzzleData!");
}
GetCorePuzzleData = (typeof(GameObject).GetMethod("GetComponent", BindingFlags.Instance | BindingFlags.Public, Array.Empty<Type>()) ?? throw new Exception("Unable to find GetComponent function!")).MakeGenericMethod(type);
}
catch (Exception value)
{
DinoLogger.Log($"Exception thrown while trying to find method to get CorePuzzleData:\n{value}");
}
}
}
}
namespace MTFO.Ext.Scans.CustomPuzzleData
{
public class ScanData
{
public float FullTeamScanMulti { get; set; }
public float[][] PerTeamSizeScanMultis { get; set; } = Array.Empty<float[]>();
public uint PersistentID { get; set; }
}
internal class ScanDataHolder
{
public List<ScanData> Scans { get; set; }
public List<EmptyClusterHolder> Clusters { get; set; }
}
internal class EmptyClusterHolder
{
}
public static class ScanDataManager
{
private static readonly Dictionary<uint, ScanData> _scanData = new Dictionary<uint, ScanData>();
internal static void Init()
{
string path = Path.Combine(MTFOPathAPI.CustomPath, "PuzzleTypes.json");
if (!File.Exists(path))
{
DinoLogger.Error("Datablocks exist, but PuzzleTypes.json does not exist!");
return;
}
JsonSerializerOptions options = new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip,
IncludeFields = true,
PropertyNameCaseInsensitive = true
};
List<ScanData> list = JsonSerializer.Deserialize<ScanDataHolder>(File.ReadAllText(path), options)?.Scans;
if (list == null)
{
DinoLogger.Error("Unable to read data from PuzzleTypes.json!");
return;
}
foreach (ScanData item in list)
{
_scanData.TryAdd(item.PersistentID, item);
}
}
public static bool TryGetScanData(GameObject go, [MaybeNullWhen(false)] out ScanData data)
{
data = null;
object obj = MTFOWrapper.GetCorePuzzleData.Invoke(go, null);
if (obj == null)
{
return false;
}
return TryGetScanData(Il2CppValueField<uint>.op_Implicit((Il2CppValueField<uint>)MTFOWrapper.GetCorePuzzleDataID.GetValue(obj)), out data);
}
public static bool TryGetScanData(uint id, [MaybeNullWhen(false)] out ScanData data)
{
return _scanData.TryGetValue(id, out data);
}
}
}