using System;
using System.Collections.Generic;
using System.Diagnostics;
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.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using ReOpenShock.Patches;
using Sirenix.Serialization.Utilities;
using Sirenix.Utilities;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ReOpenShock")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5+b1f49121efd3625308aaa2fa11c6630d1abfc48c")]
[assembly: AssemblyProduct("Shocks you in R.E.P.O")]
[assembly: AssemblyTitle("ReOpenShock")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.5.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 ReOpenShock
{
public static class ModConfig
{
private static class ConfigGroups
{
public static readonly string Connection = "Connection";
public static readonly string General = "General";
public static readonly string ShockEvents = "Shock Events";
public static readonly string Misc = "Misc";
}
public static ConfigEntry<string> OpenShockAPIDomain;
public static ConfigEntry<string> OpenShockAPIKey;
public static ConfigEntry<bool> DeveloperMode;
public static ConfigEntry<int> ShockStrength;
public static ConfigEntry<float> ShockDuration;
public static ConfigEntry<bool> ShockOnDeath;
public static ConfigEntry<bool> ShockOnDamage;
public static ConfigEntry<bool> ShockOnItemBreak;
private static readonly ImmutableList<ConfigEntry<string>> RegenOsClientOnChange = new ImmutableList<ConfigEntry<string>>((IList<ConfigEntry<string>>)new List<ConfigEntry<string>>(2) { OpenShockAPIDomain, OpenShockAPIKey });
public static void Init(ConfigFile config)
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Expected O, but got Unknown
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Expected O, but got Unknown
OpenShockAPIDomain = config.Bind<string>(ConfigGroups.Connection, "OpenShock API", "https://api.openshock.app", "The OpenShock instance's API");
OpenShockAPIKey = config.Bind<string>(ConfigGroups.Connection, "OpenShock API Key", "GO TO YOUR CONFIG FILE TO EDIT", "Go to your config file to edit!");
DeveloperMode = config.Bind<bool>(ConfigGroups.Misc, "Developer Mode", false, new ConfigDescription("Beeps Only", (AcceptableValueBase)null, new object[1] { "HideFromREPOConfig" }));
ShockStrength = config.Bind<int>(ConfigGroups.General, "Shock Strength", 20, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
ShockDuration = config.Bind<float>(ConfigGroups.General, "Shock Duration", 0.3f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 30f), Array.Empty<object>()));
ShockOnDeath = config.Bind<bool>(ConfigGroups.ShockEvents, "Shock On Death", true, "Do you want to be shocked on death?");
ShockOnDamage = config.Bind<bool>(ConfigGroups.ShockEvents, "Shock On Damage", true, "Shock on damage proportionate to how low you are");
ShockOnItemBreak = config.Bind<bool>(ConfigGroups.ShockEvents, "Shock On Item Break", true, "Shocks you when an item breaks, proportionate to how much health the item had");
}
}
internal static class ModGlobals
{
private static float _lastLevelMessage = Time.time;
internal static GameObject? LastOffensiveObject = null;
internal static float LastOffensiveGracePeriodTime = 0f;
internal static readonly Dictionary<GameObject, float> RecentlyHeldObjects = new Dictionary<GameObject, float>();
internal static bool IsAlive { get; set; } = true;
internal static string CurrentLevel { get; set; } = "";
internal static bool IsSafeLevel { get; set; } = true;
internal static float LastHeldItemPickupTime { get; set; } = Time.time;
internal static void UpdateLevel(string level)
{
CurrentLevel = level;
EvaluateIsSafeLevel();
if (!(_lastLevelMessage < 3f))
{
ReOpenShock.Instance.Logger.LogInfo((object)("Updating Level to " + level + " - Resetting Mod Global Variables"));
_lastLevelMessage = Time.time;
}
}
private static void EvaluateIsSafeLevel()
{
bool flag = false;
if (!SemiFunc.IsMultiplayer())
{
flag = CurrentLevel == "Arena";
}
IsSafeLevel = CurrentLevel == "Shop" || CurrentLevel == "Lobby" || CurrentLevel == "Lobby Menu" || CurrentLevel == "" || flag;
}
internal static void Revive()
{
IsAlive = true;
ReOpenShock.Instance.Logger.LogInfo((object)"Player has been revived.");
}
}
public enum ControlType
{
Stop,
Shock,
Vibrate,
Sound
}
public class ControlRequest
{
public IEnumerable<Control> Shocks { get; set; } = null;
public string CustomName { get; set; }
}
public class Control
{
public string Id { get; set; }
public ControlType Type { get; set; }
public int Intensity { get; set; }
public int Duration { get; set; }
}
public class DevicesRes
{
public string message { get; set; }
public List<Hub> data { get; set; }
}
public class Hub
{
public string id { get; set; }
public string name { get; set; }
public DateTime createdOn { get; set; }
public List<Shocker> shockers { get; set; }
}
public class Shocker
{
public string name { get; set; }
public bool isPaused { get; set; }
public DateTime createdOn { get; set; }
public string id { get; set; }
public int rfId { get; set; }
public string model { get; set; }
}
public class OpenShockApi
{
private static readonly ManualLogSource Logger = Logger.CreateLogSource("OpenShockApi");
private readonly HttpClient _httpClient;
public ImmutableList<string> devices = new ImmutableList<string>((IList<string>)new List<string>());
public OpenShockApi(string apiToken, Uri server)
{
HttpClientHandler handler = new HttpClientHandler();
_httpClient = new HttpClient(handler)
{
BaseAddress = server
};
_httpClient.DefaultRequestHeaders.Add("User-Agent", "ReOpenShock/1.0.5");
_httpClient.DefaultRequestHeaders.Add("OpenShockToken", apiToken);
}
public async Task Control(List<Control> shocks)
{
if (shocks.Count != 0)
{
Logger.LogInfo((object)"Sending control request to OpenShock API");
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, "/2/shockers/control")
{
Content = new StringContent(JsonConvert.SerializeObject((object)new ControlRequest
{
Shocks = shocks,
CustomName = "Integrations.ReOpenShock"
}), Encoding.UTF8, "application/json")
};
HttpResponseMessage response = await _httpClient.SendAsync(requestMessage);
if (!response.IsSuccessStatusCode)
{
Logger.LogError((object)$"Failed to send control request to OpenShock API [{response.StatusCode}]");
}
else
{
Logger.LogInfo((object)"Successfully sent control request");
}
}
}
public async Task GetDevices()
{
if (ModConfig.OpenShockAPIKey.Value == (string)((ConfigEntryBase)ModConfig.OpenShockAPIKey).DefaultValue)
{
devices = new ImmutableList<string>((IList<string>)new List<string>());
return;
}
Logger.LogInfo((object)"Sending get devices request to OpenShock API");
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, "/1/shockers/own");
HttpResponseMessage response = await _httpClient.SendAsync(requestMessage);
if (!response.IsSuccessStatusCode)
{
Logger.LogError((object)$"Failed to send get devices request to OpenShock API [{response.StatusCode}]");
return;
}
DevicesRes resCl = JsonConvert.DeserializeObject<DevicesRes>(await response.Content.ReadAsStringAsync());
List<string> shockerIds = new List<string>();
foreach (Hub hub in resCl.data)
{
foreach (Shocker shocker in hub.shockers)
{
shockerIds.Add(shocker.id);
}
}
devices = LinqExtensions.ToImmutableList<string>((IEnumerable<string>)shockerIds);
Logger.LogInfo((object)$"Got {devices.Count} shockers");
}
}
[BepInPlugin("gay.lilyy.ReOpenShock", "ReOpenShock", "1.0.5")]
public class ReOpenShock : BaseUnityPlugin
{
public const string PluginGuid = "gay.lilyy.ReOpenShock";
public const string PluginName = "ReOpenShock";
public const string PluginVersion = "1.0.5";
public static ReOpenShock Instance;
private Harmony _harmony;
internal OpenShockApi client;
public ManualLogSource Logger;
public async void Awake()
{
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
ModConfig.Init(((BaseUnityPlugin)this).Config);
Patch();
Logger.LogInfo((object)"ReOpenShock patched!");
await MakeClient();
}
public async Task MakeClient()
{
client = new OpenShockApi(ModConfig.OpenShockAPIKey.Value, new Uri(ModConfig.OpenShockAPIDomain.Value));
await client.GetDevices();
}
private void Patch()
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
if (_harmony == null)
{
_harmony = new Harmony("gay.lilyy.ReOpenShock");
}
_harmony.PatchAll(typeof(PlayerPatches));
_harmony.PatchAll(typeof(ValuablePatches));
_harmony.PatchAll(typeof(ValuablePatches.PhysGrabObjectImpactDetectorPatch));
}
public async void ActionShockers(ControlType action, int strength)
{
List<Control> actions = new List<Control>();
foreach (string device in Instance.client.devices)
{
actions.Add(new Control
{
Id = device,
Duration = (int)(ModConfig.ShockDuration.Value * 1000f),
Intensity = strength,
Type = (ModConfig.DeveloperMode.Value ? ControlType.Sound : action)
});
}
Logger.LogInfo((object)$"Actioning shockers at mode {action} at {strength}% for {ModConfig.ShockDuration}s");
await Instance.client.Control(actions);
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "ReOpenShock";
public const string PLUGIN_NAME = "Shocks you in R.E.P.O";
public const string PLUGIN_VERSION = "1.0.5";
}
}
namespace ReOpenShock.Patches
{
public static class PlayerPatches
{
private static int _lastHealth;
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathDone")]
public static void PlayerDeathDone_PostFix(PlayerAvatar __instance)
{
ReOpenShock.Instance.Logger.LogInfo((object)(__instance.playerName + " died"));
if (__instance.isLocal)
{
ReOpenShock.Instance.Logger.LogInfo((object)"Shocking!");
Task.Run(delegate
{
ReOpenShock.Instance.ActionShockers(ModConfig.ShockOnDeath.Value ? ControlType.Shock : ControlType.Vibrate, ModConfig.ShockStrength.Value);
});
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
public static void PlayerHurt_Prefix(PlayerHealth __instance)
{
if (!((Component)__instance).GetComponent<PlayerAvatar>().isLocal || !ModConfig.ShockOnDamage.Value)
{
return;
}
if (_lastHealth < 0)
{
_lastHealth = __instance.health;
}
if (__instance.health < _lastHealth)
{
float num = (1f - (float)__instance.health / (float)__instance.maxHealth) * 100f;
ReOpenShock.Instance.Logger.LogInfo((object)num);
int shockValue = Mathf.RoundToInt(num);
ReOpenShock.Instance.Logger.LogInfo((object)$"Health decreased: {_lastHealth} -> {__instance.health}, sending shock {shockValue}");
Task.Run(delegate
{
ReOpenShock.Instance.ActionShockers(ControlType.Shock, shockValue);
});
}
_lastHealth = __instance.health;
}
}
public static class ValuablePatches
{
[HarmonyPatch(typeof(PhysGrabObjectImpactDetector))]
public static class PhysGrabObjectImpactDetectorPatch
{
private static bool _lastHitEnemy;
[HarmonyPrefix]
[HarmonyPatch("OnCollisionStay")]
private static void OnCollisionStay(ref Collision collision)
{
if (((Component)collision.transform).CompareTag("Enemy"))
{
_lastHitEnemy = true;
}
else
{
_lastHitEnemy = false;
}
}
[HarmonyPostfix]
[HarmonyPatch("BreakRPC")]
private static void ItemImpactBreakRPC(float valueLost, ref bool _loseValue, int breakLevel, PhysGrabObjectImpactDetector __instance)
{
if (ModConfig.ShockOnItemBreak.Value && _loseValue)
{
ItemBreakPostfix(valueLost, __instance);
}
}
private static void ItemBreakPostfix(float valueLost, PhysGrabObjectImpactDetector __instance)
{
if (!ModGlobals.IsAlive || ModGlobals.CurrentLevel == "Arena" || !__instance.isValuable)
{
return;
}
bool heldByLocalPlayer = __instance.physGrabObject.heldByLocalPlayer;
if (heldByLocalPlayer)
{
if (!ModGlobals.RecentlyHeldObjects.ContainsKey(((Component)__instance).gameObject))
{
ModGlobals.RecentlyHeldObjects.Add(((Component)__instance).gameObject, Time.time);
ReOpenShock.Instance.Logger.LogInfo((object)("Object " + ((Object)((Component)__instance).gameObject).name + " added to held objects."));
}
else
{
ModGlobals.RecentlyHeldObjects[((Component)__instance).gameObject] = Time.time;
}
}
float dollarValueOriginal = __instance.valuableObject.dollarValueOriginal;
ShockPlayerIfNecessary(((Component)__instance).gameObject, valueLost, dollarValueOriginal, heldByLocalPlayer);
}
private static void ShockPlayerIfNecessary(GameObject damagedObject, float valueLost, float originalValue, bool isHeldByLocalPlayer)
{
if (ModGlobals.RecentlyHeldObjects.ContainsKey(damagedObject))
{
float num = ModGlobals.RecentlyHeldObjects[damagedObject];
if (isHeldByLocalPlayer && _lastHitEnemy)
{
ModGlobals.LastOffensiveGracePeriodTime = Time.time;
ModGlobals.LastOffensiveObject = damagedObject;
ReOpenShock.Instance.Logger.LogInfo((object)"[Damage Item Event] Enemy hit, aborting shock");
}
else if (_lastHitEnemy && Time.time - num <= 2f)
{
ModGlobals.LastOffensiveGracePeriodTime = Time.time;
ModGlobals.LastOffensiveObject = damagedObject;
ReOpenShock.Instance.Logger.LogInfo((object)"[Damage Item Event] Enemy hit in thrown grace period, aborting shock");
}
else if ((Object)(object)ModGlobals.LastOffensiveObject == (Object)(object)damagedObject && Time.time - ModGlobals.LastOffensiveGracePeriodTime <= 3f)
{
ReOpenShock.Instance.Logger.LogInfo((object)"[Damage Item Event] Recently used 'weapon' took damage, aborting shock");
}
else if (Time.time - num <= 4f)
{
ShockPlayer(valueLost, originalValue, ((Object)damagedObject).name);
}
}
}
private static void ShockPlayer(float valueLost, float originalValue, string objName)
{
int num = MapValue(valueLost, 0f, originalValue, 0f, ModConfig.ShockStrength.Value);
ReOpenShock.Instance.Logger.LogInfo((object)$"[Damage Item Event] Played damaged {objName} for {valueLost} - Shocking for {num}%");
ReOpenShock.Instance.ActionShockers(ControlType.Shock, num);
}
private static int MapValue(float value, float start1, float stop1, float start2, float stop2)
{
return (int)(start1 + (value - start1) * (stop2 - start2) / (stop1 - start1));
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PhysGrabObject), "GrabEnded")]
private static void GrabEndedPostFix(PhysGrabObject __instance)
{
if (__instance.isValuable && __instance.heldByLocalPlayer)
{
ModGlobals.LastHeldItemPickupTime = Time.time;
ModGlobals.LastOffensiveGracePeriodTime = 0f;
if (!ModGlobals.RecentlyHeldObjects.ContainsKey(((Component)__instance).gameObject))
{
ModGlobals.RecentlyHeldObjects.Add(((Component)__instance).gameObject, Time.time);
ReOpenShock.Instance.Logger.LogInfo((object)("Added " + ((Object)((Component)__instance).gameObject).name + " to recently held"));
}
else
{
ModGlobals.RecentlyHeldObjects[((Component)__instance).gameObject] = Time.time;
ReOpenShock.Instance.Logger.LogInfo((object)("Updated " + ((Object)((Component)__instance).gameObject).name + " in recently held"));
}
}
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}