using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Photon.Realtime;
using RunConfigAPI;
using RunConfigAPI.Common;
using ServerSeedSetter.Patches;
using Steamworks;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("dev.kirsho.ServerSeedSetter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("dev.kirsho.ServerSeedSetter")]
[assembly: AssemblyTitle("ServerSeedSetter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace ServerSeedSetter
{
internal struct DailyRunConfig
{
public struct BiomeInfo
{
[JsonProperty("section")]
public string Section;
[JsonProperty("name")]
public string Name;
[JsonProperty("variant")]
public string Variant;
public readonly BiomeInfo ToRunConfigBiomeInfo()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
return new BiomeInfo
{
Name = Name,
Variant = Variant
};
}
}
[JsonProperty("seed")]
public int Seed;
[JsonProperty("biomes")]
public List<BiomeInfo> Biomes;
public RunConfig ToRunConfig()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
RunConfig val = new RunConfig();
val.Seed = Seed;
val.BiomeInformation = ((IEnumerable<BiomeInfo>)Biomes).ToDictionary((Func<BiomeInfo, string>)((BiomeInfo i) => i.Section), (Func<BiomeInfo, BiomeInfo>)((BiomeInfo i) => new BiomeInfo
{
Name = i.Name,
Variant = i.Variant
}));
return val;
}
}
[BepInPlugin("dev.kirsho.ServerSeedSetter", "ServerSeedSetter", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
private Harmony _harmony;
internal static ConfigEntry<bool> IsEnabled;
internal static ConfigEntry<string> ServerBaseURL;
internal static ConfigEntry<string> DailyInfoPath;
public const string Id = "dev.kirsho.ServerSeedSetter";
internal static ManualLogSource Logger { get; private set; }
public static string Name => "ServerSeedSetter";
public static string Version => "1.0.0";
private void Awake()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
BindConfig();
_harmony = new Harmony("dev.kirsho.ServerSeedSetter");
_harmony.PatchAll(typeof(InitializationPatch));
_harmony.PatchAll(typeof(BoardingPassPatch));
Logger.LogInfo((object)("Plugin " + Name + " is loaded!"));
}
private void BindConfig()
{
IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Whether or not the setter is activated");
ServerBaseURL = ((BaseUnityPlugin)this).Config.Bind<string>("RemoteServer", "BaseURL", "https://api.kirsho.dev", "Base URL of the remote server to recieve seed information from.\r\nNote: dont specify any trailing forward slashes ('/') as they will be added implicitly when creating full request URL");
DailyInfoPath = ((BaseUnityPlugin)this).Config.Bind<string>("RemoteServer", "InfoRequestPath", "peak/nugget", "Path to the endpoint from which to recieve seed information.\r\nNote: dont specify any preceding forward slashes ('/') as they will be added implicitly when creating full request URL");
}
private static string CreateRequestURL(string path)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(NormalizeServerBaseURL(ServerBaseURL.Value));
stringBuilder.Append("/");
stringBuilder.Append(NormalizeServerPath(path));
return stringBuilder.ToString();
}
private static string NormalizeServerBaseURL(string initial)
{
return initial.TrimEnd('/', ' ');
}
private static string NormalizeServerPath(string initial)
{
return initial.TrimStart('/', ' ');
}
internal static DailyRunConfig? GetDailyConfigFromServer()
{
string url = CreateRequestURL(DailyInfoPath.Value);
SteamTicketPayload steamTicketPayload = new SteamTicketPayload();
steamTicketPayload.Ticket = SteamUtil.GetFreshSessionTicketAsync().Result;
if (string.IsNullOrEmpty(steamTicketPayload.Ticket))
{
Logger.LogError((object)"Error obtaining steam session ticket");
return null;
}
HttpResponseMessage httpResponseMessage = RemoteServerUtil.PostData(url, steamTicketPayload);
if (!httpResponseMessage.IsSuccessStatusCode)
{
Logger.LogError((object)("Recieving info from remote server: " + httpResponseMessage.StatusCode));
return null;
}
return JsonConvert.DeserializeObject<DailyRunConfig>(httpResponseMessage.Content.ReadAsStringAsync().Result);
}
internal static bool TryGetRandomizerInfo(out DailyRunConfig? info)
{
info = GetDailyConfigFromServer();
return info.HasValue;
}
}
internal abstract class ServerPayloadBase
{
[JsonProperty("ticket")]
public string Ticket { get; set; } = string.Empty;
public abstract ServerPayloadBase GetTruncatedCopy(int TruncatedTicketLength = 16);
}
internal class SteamTicketPayload : ServerPayloadBase
{
public override ServerPayloadBase GetTruncatedCopy(int TruncatedTicketLength = 16)
{
return new SteamTicketPayload
{
Ticket = base.Ticket.Substring(0, TruncatedTicketLength)
};
}
}
internal class RemoteServerUtil
{
private static readonly HttpClient client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(5.0)
};
public static HttpResponseMessage PostData(string url, ServerPayloadBase payload)
{
string content = JsonConvert.SerializeObject((object)payload);
Plugin.Logger.LogDebug((object)("Request body: " + JsonConvert.SerializeObject((object)payload.GetTruncatedCopy())));
HttpContent content2 = new StringContent(content, Encoding.UTF8, "application/json");
try
{
Plugin.Logger.LogDebug((object)("Requesting information from " + url));
return client.PostAsync(url, content2).ConfigureAwait(continueOnCapturedContext: false).GetAwaiter()
.GetResult();
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Getting information from the server: " + ex.Message));
return new HttpResponseMessage(HttpStatusCode.RequestTimeout);
}
}
public static Task<HttpResponseMessage> PostDataAsync(string url, ServerPayloadBase payload)
{
string content = JsonConvert.SerializeObject((object)payload);
Plugin.Logger.LogDebug((object)("Request body: " + JsonConvert.SerializeObject((object)payload.GetTruncatedCopy())));
HttpContent content2 = new StringContent(content, Encoding.UTF8, "application/json");
try
{
Plugin.Logger.LogDebug((object)("Requesting information from " + url));
return client.PostAsync(url, content2);
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Getting information from the server: " + ex.Message));
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.RequestTimeout));
}
}
}
internal class SteamUtil
{
public const int STEAM_API_REPEATS = 5;
public static readonly int STEAM_API_DELAY = 100;
private static string SessionTicket = string.Empty;
private static Callback<GetTicketForWebApiResponse_t>? GetTicketForWebApiResponseCallback;
private static TaskCompletionSource<string>? _tcs;
public static void Init()
{
if (GetTicketForWebApiResponseCallback == null)
{
RequestSessionTicket();
}
}
private static void OnAuthCallback(GetTicketForWebApiResponse_t callback)
{
//IL_000a: 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_001f: Unknown result type (might be due to invalid IL or missing references)
Plugin.Logger.LogDebug((object)$"Ticket Callback is called: {callback.m_eResult}");
SessionTicket = BitConverter.ToString(callback.m_rgubTicket).Replace("-", string.Empty);
GetTicketForWebApiResponseCallback.Dispose();
GetTicketForWebApiResponseCallback = null;
_tcs?.TrySetResult(SessionTicket);
}
public static void RequestSessionTicket()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
GetTicketForWebApiResponseCallback = Callback<GetTicketForWebApiResponse_t>.Create((DispatchDelegate<GetTicketForWebApiResponse_t>)OnAuthCallback);
HAuthTicket authTicketForWebApi = SteamUser.GetAuthTicketForWebApi("daily_config.v1");
Plugin.Logger.LogDebug((object)$"Requesting steam for auth ticket: {authTicketForWebApi.m_HAuthTicket}");
new Thread((ThreadStart)delegate
{
int num = 0;
Thread.Sleep(STEAM_API_DELAY);
while (string.IsNullOrEmpty(SessionTicket))
{
num++;
Plugin.Logger.LogWarning((object)"No callback was run yet. Running callbacks manually...");
Thread.Sleep(STEAM_API_DELAY * num);
SteamAPI.RunCallbacks();
if (num > 5)
{
Plugin.Logger.LogError((object)$"No callback was run after {num} tries, aborting SessionTicket request.");
break;
}
}
}).Start();
}
public static string GetSessionTicket()
{
return SessionTicket;
}
private static Task<string> WaitForTicketAsync()
{
_tcs = new TaskCompletionSource<string>();
return _tcs.Task;
}
public static Task<string> GetFreshSessionTicketAsync()
{
SessionTicket = string.Empty;
RequestSessionTicket();
return WaitForTicketAsync();
}
}
}
namespace ServerSeedSetter.Patches
{
internal class BoardingPassPatch
{
[HarmonyPatch(typeof(BoardingPass), "StartGame")]
[HarmonyPriority(800)]
[HarmonyPrefix]
private static void SetDailyConfig()
{
if (Plugin.IsEnabled.Value)
{
if (!Plugin.TryGetRandomizerInfo(out var info))
{
Plugin.Logger.LogWarning((object)"Unable to retreive daily config information, proceeding with usual settings.");
}
else
{
RunCapabilityApplier.Apply(info.Value.ToRunConfig());
}
}
}
}
internal class RunProgressTracker
{
internal struct RunContext
{
[JsonProperty("start")]
public DateTime startTimestamp;
[JsonProperty("end")]
public DateTime endTimestamp;
[JsonProperty("progress")]
public float progress;
}
internal static RunContext context;
[HarmonyPatch(typeof(RunManager), "StartRun")]
[HarmonyPostfix]
private static void RecordStartTimestamp()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name == "Airport")
{
Plugin.Logger.LogDebug((object)"Ignoring StartTimestamp, because we are in Airport");
return;
}
context = default(RunContext);
context.startTimestamp = DateTime.Now;
context.progress = 0f;
}
[HarmonyPatch(typeof(GlobalEvents), "TriggerPlayerDisconnected")]
[HarmonyPostfix]
private static void RecordEndTimestampOnDisconnect(Player player)
{
if (player.IsLocal)
{
RecordEndTimestamp();
}
}
[HarmonyPatch(typeof(Campfire), "Light_Rpc")]
[HarmonyPostfix]
private static void UpdateProgress(Campfire __instance)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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_0025: Expected I4, but got Unknown
Segment advanceToSegment = __instance.advanceToSegment;
switch ((int)advanceToSegment)
{
case 0:
context.progress = 0f;
break;
case 1:
context.progress = 0.2f;
break;
case 2:
context.progress = 0.4f;
break;
case 3:
context.progress = 0.6f;
break;
case 4:
context.progress = 0.8f;
break;
case 5:
context.progress = 1f;
break;
default:
context.progress = 0f;
break;
}
}
[HarmonyPatch(typeof(RunManager), "EndGame")]
[HarmonyPostfix]
private static void RecordEndTimestamp()
{
context.endTimestamp = DateTime.Now;
}
}
public class InitializationPatch
{
[HarmonyPatch(typeof(GameHandler), "Initialize")]
[HarmonyPostfix]
public static void InitializeSessionTicket()
{
SteamUtil.Init();
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}