using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using OniroDev.Patches;
using Unity.Collections;
using Unity.Netcode;
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("WeedKillerAdjuster")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("WeedKiller Adjuster - Ported to v81")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: AssemblyProduct("WeedKillerAdjuster")]
[assembly: AssemblyTitle("WeedKillerAdjuster")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace OniroDev
{
[BepInPlugin("OniroDev.WeedKillerAdjuster", "WeedKillerAdjuster", "2.0.0")]
public class WeedKillerAdjusterBase : BaseUnityPlugin
{
private readonly Harmony _harmony = new Harmony("OniroDev.WeedKillerAdjuster");
public static WeedKillerAdjusterBase Instance { get; private set; }
private void Awake()
{
Instance = this;
WeedKillerAdjusterLogger.Initialize("OniroDev.WeedKillerAdjuster");
WeedKillerAdjusterLogger.Log("WeedKillerAdjuster starting up (OniroDev.WeedKillerAdjuster)");
new WeedKillerConfig(((BaseUnityPlugin)this).Config);
WeedKillerAdjusterLogger.Log("Applying patches...");
_harmony.PatchAll(typeof(WeedKillerPatch));
_harmony.PatchAll(typeof(WeedKillerConfig));
WeedKillerAdjusterLogger.Log("Patches applied successfully.");
}
}
internal static class PluginInfo
{
internal const string PLUGIN_GUID = "OniroDev.WeedKillerAdjuster";
internal const string PLUGIN_NAME = "WeedKillerAdjuster";
internal const string PLUGIN_VERSION = "2.0.0";
}
public static class WeedKillerAdjusterLogger
{
private static ManualLogSource _logSource;
public static void Initialize(string pluginGUID)
{
_logSource = Logger.CreateLogSource(pluginGUID);
}
public static void Log(object message)
{
ManualLogSource logSource = _logSource;
if (logSource != null)
{
logSource.LogInfo(message);
}
}
public static void LogWarning(object message)
{
ManualLogSource logSource = _logSource;
if (logSource != null)
{
logSource.LogWarning(message);
}
}
public static void LogError(object message)
{
ManualLogSource logSource = _logSource;
if (logSource != null)
{
logSource.LogError(message);
}
}
}
public class WeedKillerConfig
{
[CompilerGenerated]
private static class <>O
{
public static HandleNamedMessageDelegate <0>__OnRequestSync;
public static HandleNamedMessageDelegate <1>__OnReceiveSync;
}
public static ConfigEntry<float> weedKillRate;
public static ConfigEntry<float> weedKillTank;
public static ConfigEntry<bool> usesBattery;
private static WeedKillerConfig _default;
private static WeedKillerConfig _synced;
private float _killRate;
private float _killTank;
private bool _battery;
public static bool IsSynced { get; private set; }
private static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager;
private static bool IsHost => NetworkManager.Singleton.IsHost;
private static bool IsClient => NetworkManager.Singleton.IsClient;
public WeedKillerConfig(ConfigFile configFile)
{
configFile.SaveOnConfigSet = false;
weedKillRate = configFile.Bind<float>("Weed Killer Settings", "Vain Shroud Kill Rate", 1f, "Multiplier for kill rate of Vain Shrouds. Set to 7 to kill them 7x faster than normal.");
weedKillTank = configFile.Bind<float>("Weed Killer Settings", "Weed Killer Base Fuel Tank", 1f, "Multiplier for fuel tank capacity. Set to 7 for 7x more spray fuel.");
usesBattery = configFile.Bind<bool>("Weed Killer Settings", "Use Battery Charges", false, "When true, the weed killer uses battery charges and can be recharged on the ship. When enabled, the Fuel Tank multiplier is ignored.");
ClearOrphanedEntries(configFile);
configFile.Save();
configFile.SaveOnConfigSet = true;
_default = this;
_synced = this;
SnapshotFromConfig();
WeedKillerAdjusterLogger.Log($"Config loaded — killRate={weedKillRate.Value}, killTank={weedKillTank.Value}, battery={usesBattery.Value}");
}
private void SnapshotFromConfig()
{
_killRate = weedKillRate.Value;
_killTank = weedKillTank.Value;
_battery = usesBattery.Value;
}
private static byte[] Serialize(WeedKillerConfig cfg)
{
byte[] array = new byte[9];
Buffer.BlockCopy(BitConverter.GetBytes(cfg._killRate), 0, array, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(cfg._killTank), 0, array, 4, 4);
array[8] = (byte)(cfg._battery ? 1 : 0);
return array;
}
private static WeedKillerConfig Deserialize(byte[] data)
{
return new WeedKillerConfig
{
_killRate = BitConverter.ToSingle(data, 0),
_killTank = BitConverter.ToSingle(data, 4),
_battery = (data[8] != 0)
};
}
private WeedKillerConfig()
{
}
private static void ApplySynced(WeedKillerConfig cfg)
{
weedKillRate.Value = cfg._killRate;
weedKillTank.Value = cfg._killTank;
usesBattery.Value = cfg._battery;
_synced = cfg;
IsSynced = true;
WeedKillerAdjusterLogger.Log("Config synced from host.");
}
private static void RevertSync()
{
if (_default != null)
{
weedKillRate.Value = _default._killRate;
weedKillTank.Value = _default._killTank;
usesBattery.Value = _default._battery;
_synced = _default;
IsSynced = false;
WeedKillerAdjusterLogger.Log("Config reverted to local defaults.");
}
}
public static void RequestSync()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
if (!IsClient)
{
return;
}
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1);
try
{
MessageManager.SendNamedMessage("OniroDev.WeedKillerAdjuster_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3);
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
public static void OnRequestSync(ulong clientId, FastBufferReader _)
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
if (!IsHost)
{
return;
}
WeedKillerAdjusterLogger.Log($"Config sync request from client {clientId}");
byte[] array = Serialize(_default);
int num = array.Length;
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(num + 4, (Allocator)2, -1);
try
{
((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0);
MessageManager.SendNamedMessage("OniroDev.WeedKillerAdjuster_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3);
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
public static void OnReceiveSync(ulong _, FastBufferReader reader)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
if (!((FastBufferReader)(ref reader)).TryBeginRead(4))
{
WeedKillerAdjusterLogger.LogError("Config sync error: could not read length.");
return;
}
int num = default(int);
((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
if (!((FastBufferReader)(ref reader)).TryBeginRead(num))
{
WeedKillerAdjusterLogger.LogError("Config sync error: could not read payload.");
return;
}
byte[] data = new byte[num];
((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
try
{
ApplySynced(Deserialize(data));
}
catch (Exception arg)
{
WeedKillerAdjusterLogger.LogError($"Config sync deserialization failed: {arg}");
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
public static void InitializeLocalPlayer()
{
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
if (IsHost)
{
CustomMessagingManager messageManager = MessageManager;
object obj = <>O.<0>__OnRequestSync;
if (obj == null)
{
HandleNamedMessageDelegate val = OnRequestSync;
<>O.<0>__OnRequestSync = val;
obj = (object)val;
}
messageManager.RegisterNamedMessageHandler("OniroDev.WeedKillerAdjuster_OnRequestConfigSync", (HandleNamedMessageDelegate)obj);
IsSynced = true;
return;
}
IsSynced = false;
CustomMessagingManager messageManager2 = MessageManager;
object obj2 = <>O.<1>__OnReceiveSync;
if (obj2 == null)
{
HandleNamedMessageDelegate val2 = OnReceiveSync;
<>O.<1>__OnReceiveSync = val2;
obj2 = (object)val2;
}
messageManager2.RegisterNamedMessageHandler("OniroDev.WeedKillerAdjuster_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2);
RequestSync();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
public static void PlayerLeave()
{
RevertSync();
}
private static void ClearOrphanedEntries(ConfigFile configFile)
{
if (AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(configFile) is Dictionary<ConfigDefinition, string> dictionary)
{
dictionary.Clear();
}
}
}
}
namespace OniroDev.Patches
{
public class WeedKillerPatch
{
private static readonly FieldRef<SprayPaintItem, float> _sprayCanTankRef = AccessTools.FieldRefAccess<SprayPaintItem, float>("sprayCanTank");
private static readonly FieldRef<SprayPaintItem, float> _killWeedSpeedRef = TryGetKillWeedSpeedRef();
private static readonly FieldRef<SprayPaintItem, bool> _isSprayingRef = AccessTools.FieldRefAccess<SprayPaintItem, bool>("isSpraying");
private static readonly Dictionary<SprayPaintItem, float> _tempCanTank = new Dictionary<SprayPaintItem, float>();
private static FieldRef<SprayPaintItem, float> TryGetKillWeedSpeedRef()
{
FieldInfo fieldInfo = AccessTools.Field(typeof(SprayPaintItem), "killWeedSpeed");
if (fieldInfo == null)
{
WeedKillerAdjusterLogger.LogWarning("SprayPaintItem.killWeedSpeed not found in this game version. weedKillRate multiplier will be applied to drain rate instead.");
return null;
}
return AccessTools.FieldRefAccess<SprayPaintItem, float>(fieldInfo);
}
[HarmonyPatch(typeof(SprayPaintItem), "Start")]
[HarmonyPostfix]
public static void WeedKillerKillRatePatch(SprayPaintItem __instance)
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Expected O, but got Unknown
if (_killWeedSpeedRef != null)
{
float num = _killWeedSpeedRef.Invoke(__instance) * WeedKillerConfig.weedKillRate.Value;
_killWeedSpeedRef.Invoke(__instance) = num;
WeedKillerAdjusterLogger.Log($"killWeedSpeed scaled to {num} (x{WeedKillerConfig.weedKillRate.Value})");
}
if (__instance.isWeedKillerSprayBottle && WeedKillerConfig.usesBattery.Value)
{
((GrabbableObject)__instance).insertedBattery = new Battery(false, _sprayCanTankRef.Invoke(__instance));
((GrabbableObject)__instance).itemProperties.requiresBattery = true;
WeedKillerAdjusterLogger.Log("Weed killer battery mode enabled.");
}
}
[HarmonyPatch(typeof(GrabbableObject), "ChargeBatteries")]
[HarmonyPrefix]
private static void WeedKillerChargeBatteries(GrabbableObject __instance)
{
SprayPaintItem val = (SprayPaintItem)(object)((__instance is SprayPaintItem) ? __instance : null);
if (val != null && val.isWeedKillerSprayBottle && WeedKillerConfig.usesBattery.Value)
{
_sprayCanTankRef.Invoke(val) = ((GrabbableObject)val).insertedBattery.charge;
}
}
[HarmonyPatch(typeof(SprayPaintItem), "LateUpdate")]
[HarmonyPrefix]
private static void PreWeedKillerLateUpdate(SprayPaintItem __instance)
{
_tempCanTank[__instance] = _sprayCanTankRef.Invoke(__instance);
}
[HarmonyPatch(typeof(SprayPaintItem), "LateUpdate")]
[HarmonyPostfix]
private static void PostWeedKillerLateUpdate(SprayPaintItem __instance)
{
if (!__instance.isWeedKillerSprayBottle)
{
return;
}
bool flag = _isSprayingRef.Invoke(__instance);
if (((GrabbableObject)__instance).isHeld && flag)
{
if (_killWeedSpeedRef != null)
{
if (!_tempCanTank.TryGetValue(__instance, out var value))
{
return;
}
float num = Mathf.Max(value - Time.deltaTime / (15f * WeedKillerConfig.weedKillTank.Value), 0f);
_sprayCanTankRef.Invoke(__instance) = num;
}
else
{
float num2 = _sprayCanTankRef.Invoke(__instance);
float num3 = Time.deltaTime * (WeedKillerConfig.weedKillRate.Value - 1f) / (15f * WeedKillerConfig.weedKillTank.Value);
_sprayCanTankRef.Invoke(__instance) = Mathf.Max(num2 - num3, 0f);
}
}
if (WeedKillerConfig.usesBattery.Value)
{
((GrabbableObject)__instance).insertedBattery.charge = _sprayCanTankRef.Invoke(__instance);
}
}
[HarmonyPatch(typeof(SprayPaintItem), "OnDestroy")]
[HarmonyPostfix]
private static void WeedKillerOnDestroy(SprayPaintItem __instance)
{
_tempCanTank.Remove(__instance);
}
}
}