using System;
using System.Collections.Concurrent;
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;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using ShockController;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("UltraShock")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: AssemblyInformationalVersion("0.0.1+ab8bcb5dbf1baa9dd238cf14558753e175d5104b")]
[assembly: AssemblyProduct("UltraShock")]
[assembly: AssemblyTitle("UltraShock")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.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 ShockController
{
internal class ShockRequestQueue : IDisposable
{
private ConcurrentQueue<Func<Task>> _taskQueue;
private SemaphoreSlim _signal;
private CancellationTokenSource _cts;
private Task _worker;
private readonly object _lock = new object();
private bool _disposed;
private ManualLogSource _logger;
public ShockRequestQueue(ManualLogSource logger)
{
_logger = logger;
Start();
}
public void Enqueue(Func<Task> task)
{
if (_disposed)
{
throw new ObjectDisposedException("ShockRequestQueue");
}
_taskQueue.Enqueue(task);
_signal.Release();
}
public void Enqueue<T>(Func<T, Task> task, T args)
{
if (_disposed)
{
throw new ObjectDisposedException("ShockRequestQueue");
}
_taskQueue.Enqueue(() => task(args));
_signal.Release();
}
public void Start()
{
_taskQueue = new ConcurrentQueue<Func<Task>>();
_signal = new SemaphoreSlim(0);
_cts = new CancellationTokenSource();
_worker = Task.Run((Func<Task?>)ProcessQueueAsync);
}
private async Task ProcessQueueAsync()
{
while (!_cts.Token.IsCancellationRequested)
{
await _signal.WaitAsync(_cts.Token);
if (_taskQueue.TryDequeue(out var result))
{
try
{
await result();
}
catch (Exception ex)
{
_logger.LogError((object)ex.ToString());
}
}
}
}
public async Task StopAsync()
{
if (_disposed)
{
return;
}
_cts.Cancel();
_signal.Release();
try
{
await _worker;
}
catch (Exception ex)
{
_logger.LogError((object)ex.ToString());
}
}
public async Task ResetAsync()
{
lock (_lock)
{
if (!_worker.IsCompleted)
{
StopAsync().Wait();
}
Start();
}
}
public void Dispose()
{
if (!_disposed)
{
StopAsync().Wait();
_cts.Dispose();
_signal.Dispose();
_disposed = true;
}
}
}
public interface IShockController
{
void EnqueueShock(int intensity, int duration_ms, string? code = null);
}
public class OpenShockController : IShockController
{
private readonly ShockRequestQueue _queue;
private readonly string _apiUrl;
private readonly string _deviceId;
private readonly string _apiKey;
private readonly float _cooldownSeconds;
private readonly ManualLogSource _logger;
private readonly HttpClient _client = new HttpClient();
private DateTime _lastShockTime = DateTime.MinValue;
private TimeSpan ShockCooldown => TimeSpan.FromSeconds(0.1 + (double)Math.Max(0f, _cooldownSeconds));
public OpenShockController(string apiUrl, string deviceId, string apiKey, float cooldownSeconds, ManualLogSource logger)
{
_apiUrl = apiUrl;
_deviceId = deviceId;
_apiKey = apiKey;
_cooldownSeconds = cooldownSeconds;
_logger = logger;
_queue = new ShockRequestQueue(logger);
}
public void EnqueueShock(int intensity, int duration_ms, string? code = null)
{
string code2 = code;
DateTime utcNow = DateTime.UtcNow;
if (utcNow - _lastShockTime < ShockCooldown)
{
_logger.LogInfo((object)"OpenShock shock skipped due to cooldown.");
return;
}
_lastShockTime = utcNow;
_queue.Enqueue(() => TriggerShockInternal(intensity, duration_ms, code2));
}
private async Task TriggerShockInternal(int intensity, int duration_ms, string? code)
{
duration_ms = Math.Clamp(duration_ms, 300, 65535);
if (string.IsNullOrEmpty(_apiUrl) || string.IsNullOrEmpty(_apiKey))
{
_logger.LogWarning((object)$"Would send OpenShock (intensity={intensity}, duration_ms={duration_ms}), but OpenShock credentials are not set.");
return;
}
string text = ((!string.IsNullOrEmpty(code)) ? code : _deviceId);
if (string.IsNullOrEmpty(text))
{
_logger.LogWarning((object)"No deviceId or share code provided for OpenShock.");
return;
}
_logger.LogInfo((object)$"Sending OpenShock: id={text}, intensity={intensity}, duration_ms={duration_ms}");
StringContent content = new StringContent(JsonConvert.SerializeObject((object)new
{
Shocks = new[]
{
new
{
Id = text,
Type = 1,
Intensity = intensity,
Duration = duration_ms
}
},
CustomName = "Integrations.UltraShock"
}), Encoding.UTF8, "application/json");
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, _apiUrl + "/2/shockers/control")
{
Content = content
};
httpRequestMessage.Headers.Add("OpenShockToken", _apiKey);
httpRequestMessage.Headers.Add("User-Agent", "UnityShock");
try
{
HttpResponseMessage response = await _client.SendAsync(httpRequestMessage);
if (!response.IsSuccessStatusCode)
{
string arg = await response.Content.ReadAsStringAsync();
_logger.LogError((object)$"OpenShock API error: {response.StatusCode} {arg}");
}
}
catch (Exception arg2)
{
_logger.LogError((object)$"OpenShock API exception: {arg2}");
}
}
}
public class PiShockController : IShockController
{
private readonly HttpClient _client = new HttpClient();
private readonly ShockRequestQueue _queue;
private readonly ManualLogSource _logger;
private readonly string _userName;
private readonly string _shareCode;
private readonly string _apiKey;
private readonly float _cooldownSeconds;
private DateTime _lastShockTime = DateTime.MinValue;
private TimeSpan ShockCooldown => TimeSpan.FromSeconds(0.1 + (double)Math.Max(0f, _cooldownSeconds));
public PiShockController(string userName, string shareCode, string apiKey, float cooldownSeconds, ManualLogSource logger)
{
_userName = userName;
_shareCode = shareCode;
_apiKey = apiKey;
_cooldownSeconds = cooldownSeconds;
_logger = logger;
_queue = new ShockRequestQueue(logger);
}
public void TriggerShock(int intensity, int duration_ms = 1, string? shareCode = null)
{
DateTime utcNow = DateTime.UtcNow;
if (utcNow - _lastShockTime < ShockCooldown)
{
_logger.LogInfo((object)"Shock skipped due to cooldown.");
return;
}
_lastShockTime = utcNow;
string code = shareCode ?? _shareCode;
_logger.LogInfo((object)$"Enqueue shock: intensity={intensity}, duration={duration_ms}, code={code}");
_queue.Enqueue(() => TriggerShockInternal(intensity, duration_ms, code));
}
public void EnqueueShock(int intensity, int duration_ms, string? code = null)
{
TriggerShock(intensity, duration_ms, code);
}
private async Task TriggerShockInternal(int intensity, int duration, string code)
{
string userName = _userName;
string apiKey = _apiKey;
duration /= 1000;
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(apiKey) || string.IsNullOrEmpty(code))
{
_logger.LogWarning((object)$"Would send shock (intensity={intensity}, duration={duration}, code={code}), but PiShock credentials are not set.");
return;
}
_logger.LogInfo((object)$"Sending shock: intensity={intensity}, duration_sec={duration}, code={code}");
StringContent content = new StringContent(JsonConvert.SerializeObject((object)new
{
Username = userName,
APIKey = apiKey,
Code = code,
Intensity = intensity,
Duration = duration,
Op = 0
}), Encoding.UTF8, "application/json");
try
{
_logger.LogInfo((object)$"Sending request to PiShock API: {userName}, Intensity={intensity}, Duration={duration}");
HttpResponseMessage httpResponseMessage = await _client.PostAsync("https://do.pishock.com/api/apioperate/", content);
if (!httpResponseMessage.IsSuccessStatusCode)
{
_logger.LogError((object)$"PiShock API error: {httpResponseMessage.StatusCode}");
}
}
catch (Exception arg)
{
_logger.LogError((object)$"PiShock API exception: {arg}");
}
}
}
public class ShockConfig
{
public enum ShockProvider
{
OpenShock,
PiShock
}
public ConfigFile f { get; private set; }
public ConfigEntry<float> ShockCooldownSeconds { get; private set; }
public ConfigEntry<ShockProvider> ShockProviderType { get; private set; }
public ConfigEntry<string> OpenShockApiUrl { get; private set; }
public ConfigEntry<string> OpenShockDeviceId { get; private set; }
public ConfigEntry<string> OpenShockApiKey { get; private set; }
public ConfigEntry<string> PiShockUserName { get; private set; }
public ConfigEntry<string> PiShockAPIKey { get; private set; }
public ConfigEntry<string> PiShockShareCode { get; private set; }
public ShockConfig(ConfigFile f)
{
ShockCooldownSeconds = f.Bind<float>("Shock", "ShockCooldownSeconds", 2f, "Minimum seconds between shocks (prevents shock spam)");
ShockProviderType = f.Bind<ShockProvider>("Shock", "Provider", ShockProvider.OpenShock, "Choose PiShock or OpenShock");
OpenShockApiUrl = f.Bind<string>("OpenShock", "ApiUrl", "https://api.openshock.app", "OpenShock API URL");
OpenShockDeviceId = f.Bind<string>("OpenShock", "DeviceId", "", "OpenShock Device ID");
OpenShockApiKey = f.Bind<string>("OpenShock", "ApiKey", "", "OpenShock API Key");
PiShockUserName = f.Bind<string>("PiShock", "UserName", "", "Your PiShock username");
PiShockAPIKey = f.Bind<string>("PiShock", "APIKey", "", "Your PiShock API Key");
PiShockShareCode = f.Bind<string>("PiShock", "ShareCode", "", "Your PiShock ShareCode");
}
}
}
namespace UltraShock
{
[HarmonyPatch(typeof(NewMovement), "GetHurt")]
public class HurtPatch
{
private static void Postfix(int damage, bool invincible, float scoreLossMultiplier, bool explosion, bool instablack, float hardDamageMultiplier, bool ignoreInvincibility)
{
UltraShockPlugin.Logger.LogInfo((object)("Damage" + damage + "!"));
float num = (float)UltraShockPlugin.ShockScale.Value / 100f;
UltraShockPlugin.Shocker.EnqueueShock(Mathf.RoundToInt((float)damage * num), 500);
}
}
internal class PluginInfo
{
public const string PLUGIN_GUID = "jakobbbb.UltraShock";
public const string PLUGIN_NAME = "UltraShock";
public const string PLUGIN_VERSION = "0.0.1";
}
[BepInPlugin("jakobbbb.UltraShock", "UltraShock", "0.0.1")]
public class UltraShockPlugin : BaseUnityPlugin
{
public static ManualLogSource Logger;
public static UltraShockPlugin Instance;
internal ShockConfig _shockConf;
public static IShockController Shocker;
public static ConfigEntry<int> ShockScale { get; private set; }
private void Awake()
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Expected O, but got Unknown
Instance = this;
Object.DontDestroyOnLoad((Object)(object)this);
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"Plugin jakobbbb.UltraShock is loaded :3");
SceneManager.sceneLoaded += delegate
{
Logger.LogInfo((object)"Scene loaded!");
};
Harmony.CreateAndPatchAll(typeof(HurtPatch), (string)null);
ConfigFile val = new ConfigFile("BepInEx/config/jakobbbb.UltraShock.cfg", true);
ShockScale = val.Bind<int>("Shock", "ShockScale", 50, "How much to scale shock intensity (0-100)");
_shockConf = new ShockConfig(val);
ShockConfig.ShockProvider value = _shockConf.ShockProviderType.Value;
Logger.LogInfo((object)$"Shock provider is: {value}");
switch (value)
{
case ShockConfig.ShockProvider.OpenShock:
Shocker = new OpenShockController(_shockConf.OpenShockApiUrl.Value, _shockConf.OpenShockDeviceId.Value, _shockConf.OpenShockApiKey.Value, _shockConf.ShockCooldownSeconds.Value, Logger);
break;
case ShockConfig.ShockProvider.PiShock:
Shocker = new PiShockController(_shockConf.PiShockUserName.Value, _shockConf.PiShockShareCode.Value, _shockConf.PiShockAPIKey.Value, _shockConf.ShockCooldownSeconds.Value, Logger);
break;
}
}
private void OnEnable()
{
Logger.LogInfo((object)"Enabled");
}
private void OnDisable()
{
Logger.LogInfo((object)"Disabled");
}
private void Update()
{
Logger.LogError((object)"OWO");
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "UltraShock";
public const string PLUGIN_NAME = "UltraShock";
public const string PLUGIN_VERSION = "0.0.1";
}
}