using System;
using System.Collections;
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 Battle;
using Battle.Attacks;
using Battle.Attacks.AttackBehaviours;
using Battle.Pachinko.BallBehaviours;
using Battle.PegBehaviour;
using Battle.StatusEffects;
using BepInEx;
using HarmonyLib;
using IL.Battle;
using IL.Battle.Attacks;
using IL.Battle.Attacks.AttackBehaviours;
using IL.Battle.Pachinko.BallBehaviours;
using IL.Battle.StatusEffects;
using IL.Relics;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On;
using On.Battle;
using On.Battle.PegBehaviour;
using PeglinUtils;
using UnityEngine;
[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("PeglinRNGSeeding")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Seeds some of the game RNG")]
[assembly: AssemblyFileVersion("0.0.9.0")]
[assembly: AssemblyInformationalVersion("0.0.9+58409b0627c01dd3feb2e34019099c0fd4c17937")]
[assembly: AssemblyProduct("PeglinRNGSeeding")]
[assembly: AssemblyTitle("PeglinRNGSeeding")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.9.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 PeglinRNGSeeding
{
public enum LogLevel
{
Off,
On,
Debug,
Trace
}
[BepInPlugin("PeglinRNGSeeding", "PeglinRNGSeeding", "0.0.9")]
public class Plugin : BaseUnityPlugin
{
private void Awake()
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin PeglinRNGSeeding is loaded!");
try
{
((Component)this).gameObject.AddComponent<RngSeeding>();
RngSeeding.LogLevel = ((BaseUnityPlugin)this).Config.Bind<LogLevel>("General", "Log Level", LogLevel.On, "Controls the amount of info that should be printed to the console").Value;
RngSeeding.SeedAllShuffles = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Seed Random Shuffles", true, "Seed all randomized shuffling. Slightly experimental").Value;
}
catch (Exception arg)
{
Debug.LogWarning((object)$"Couldn't read config file: {arg}");
}
}
}
public class RngSeeding : MonoBehaviour
{
[HarmonyPatch]
private class PatchShuffle
{
[HarmonyTargetMethod]
[UsedImplicitly]
private static MethodBase TargetMethod()
{
return typeof(ListExtensions).GetMethod("Shuffle")?.MakeGenericMethod(typeof(object));
}
[UsedImplicitly]
private static bool Prefix(IList list)
{
if (!SeedAllShuffles)
{
Log(LogLevel.Debug, "Shuffle seeding disabled");
return true;
}
Log(LogLevel.Trace, "Shuffling List Before: " + string.Join(", ", list));
Log($"Shuffling list of type: {list.GetType()}");
int num = list.Count;
while (num > 1)
{
num--;
int index = _shuffleRng?.Next(0, num + 1) ?? Random.Range(0, num + 1);
int index2 = num;
object value = list[num];
object value2 = list[index];
list[index] = value;
list[index2] = value2;
}
Log(LogLevel.Trace, "Shuffling List After: " + string.Join(", ", list));
return false;
}
}
private Random _specialPegRng;
private Dictionary<PegType, Random> _specialPegRngs = new Dictionary<PegType, Random>();
private Random _deckOrderRng;
private Random _roundrelStatusRng;
private Random _roundrelStatusDebug;
private Random _critStatusRng;
private Random _primeSlimeRng;
private Random _potionBalltRng;
private Random _refresherCourseRng;
private Random _specialSlotRng;
private Random _dungeonDieRng;
private Random _randomPegFieldRng;
private static Random _shuffleRng;
private Harmony _harmony;
public static LogLevel LogLevel { get; set; }
public static bool SeedAllShuffles { get; set; }
public void Awake()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Expected O, but got Unknown
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Expected O, but got Unknown
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Expected O, but got Unknown
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Expected O, but got Unknown
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Expected O, but got Unknown
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Expected O, but got Unknown
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Expected O, but got Unknown
_harmony = new Harmony("PeglinRNGSeeding");
_harmony.PatchAll();
BattleController.Start += new hook_Start(BattleControllerOnStart);
DeckManager.ShuffleCompleteDeck += new hook_ShuffleCompleteDeck(DeckManagerOnShuffleCompleteDeck);
PegManager.CreateSpecialPeg += new Manipulator(PegManagerOnCreateSpecialPeg);
AddRandomStatusEffectOnHit.AffectEnemy += new Manipulator(AddRandomStatusEffectOnHitOnAffectEnemy);
TargetingManager.OnCritActivated += new Manipulator(TargetingManagerOnOnCritActivated);
RelicManager.GetRandomPrimeSlimeType += new Manipulator(RelicManagerOnGetRandomPrimeSlimeType);
MultiballPrefabOverridePool.GetMultiballGameobject += new Manipulator(MultiballPrefabOverridePoolOnGetMultiballGameobject);
PlayerStatusEffectController.CheckRefreshEffects += new Manipulator(PlayerStatusEffectControllerOnCheckRefreshEffects);
SpecialSlotController.BattleTurnComplete += new hook_BattleTurnComplete(SpecialSlotControllerOnBattleTurnComplete);
Attack.SetRandomRolledDamage += new Manipulator(AttackOnSetRandomRolledDamage);
RandomPegField.CreatePegs += new hook_CreatePegs(RandomPegFieldOnCreatePegs);
}
private void PegManagerOnCreateSpecialPeg(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[5]
{
(Instruction i) => ILPatternMatchingExt.MatchLdarg(i, 2),
(Instruction i) => ILPatternMatchingExt.MatchLdcI4(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchLdarg(i, 2),
(Instruction i) => ILPatternMatchingExt.MatchCallvirt(i, (MethodBase)(typeof(List<Peg>).GetProperty("Count")?.GetMethod)),
(Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)typeof(Random).GetMethod("Range", new Type[2]
{
typeof(int),
typeof(int)
}))
}))
{
Debug.LogWarning((object)"Failed to match special peg IL");
return;
}
val.Index += 4;
val.Remove();
val.Emit(OpCodes.Ldarg_1);
val.EmitDelegate<Func<int, int, PegType, int>>((Func<int, int, PegType, int>)delegate(int a, int b, PegType pegType)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
Log($"Creating special peg of type: {pegType}");
if (!_specialPegRngs.TryGetValue(pegType, out var value))
{
Log(LogLevel.Debug, $"Instantiating RNG for type: {pegType} in this battle");
value = new Random(_specialPegRng.Next());
_specialPegRngs[pegType] = value;
}
else
{
Log(LogLevel.Debug, $"Found existing RNG for type: {pegType}");
}
int num = value.Next(a, b);
Log(LogLevel.Debug, $"Next {pegType} peg index: {num}");
return num;
});
}
public void OnDestroy()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Expected O, but got Unknown
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected O, but got Unknown
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Expected O, but got Unknown
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Expected O, but got Unknown
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Expected O, but got Unknown
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Expected O, but got Unknown
BattleController.Start -= new hook_Start(BattleControllerOnStart);
DeckManager.ShuffleCompleteDeck -= new hook_ShuffleCompleteDeck(DeckManagerOnShuffleCompleteDeck);
PegManager.CreateSpecialPeg -= new Manipulator(PegManagerOnCreateSpecialPeg);
AddRandomStatusEffectOnHit.AffectEnemy -= new Manipulator(AddRandomStatusEffectOnHitOnAffectEnemy);
TargetingManager.OnCritActivated -= new Manipulator(TargetingManagerOnOnCritActivated);
RelicManager.GetRandomPrimeSlimeType -= new Manipulator(RelicManagerOnGetRandomPrimeSlimeType);
MultiballPrefabOverridePool.GetMultiballGameobject -= new Manipulator(MultiballPrefabOverridePoolOnGetMultiballGameobject);
PlayerStatusEffectController.CheckRefreshEffects -= new Manipulator(PlayerStatusEffectControllerOnCheckRefreshEffects);
SpecialSlotController.BattleTurnComplete -= new hook_BattleTurnComplete(SpecialSlotControllerOnBattleTurnComplete);
Attack.SetRandomRolledDamage -= new Manipulator(AttackOnSetRandomRolledDamage);
RandomPegField.CreatePegs -= new hook_CreatePegs(RandomPegFieldOnCreatePegs);
}
private void RandomPegFieldOnCreatePegs(orig_CreatePegs orig, RandomPegField self)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (_randomPegFieldRng == null)
{
orig.Invoke(self);
return;
}
State state = Random.state;
Random.InitState(_randomPegFieldRng.Next());
orig.Invoke(self);
Random.state = state;
}
private void AddRandomStatusEffectOnHitOnAffectEnemy(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[5]
{
(Instruction i) => ILPatternMatchingExt.MatchLdcI4(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchLdsfld<AddRandomStatusEffectOnHit>(i, "RoundreloquencePotentialEffects"),
(Instruction i) => ILPatternMatchingExt.MatchLdlen(i),
(Instruction i) => ILPatternMatchingExt.MatchConvI4(i),
(Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)typeof(Random).GetMethod("Range", new Type[2]
{
typeof(int),
typeof(int)
}))
}))
{
Debug.LogWarning((object)"Failed to match call for status on hit");
return;
}
val.Index += 4;
val.Remove();
val.EmitDelegate<Func<int, int, int>>((Func<int, int, int>)delegate(int a, int b)
{
_roundrelStatusDebug.Next(a, b);
int num = _roundrelStatusDebug.Next(a, b);
int num2 = _roundrelStatusRng.Next(a, b);
StatusEffectType[] roundreloquencePotentialEffects = AddRandomStatusEffectOnHit.RoundreloquencePotentialEffects;
Log($"Applying status effect: {roundreloquencePotentialEffects[num2]}");
Log(LogLevel.Trace, $"Upcoming status effect is: {roundreloquencePotentialEffects[num]}");
return num2;
});
}
private IEnumerator BattleControllerOnStart(orig_Start orig, BattleController self)
{
int num = SeedUtils.ConvertSeedFromSymbolsToInt(StaticGameData.currentSeed) - StaticGameData.totalFloorCount;
Random random = new Random(num);
Log($"Setting up battle RNG with seed: {num}");
_deckOrderRng = new Random(random.Next());
_specialPegRng = new Random(random.Next());
int seed = random.Next();
_roundrelStatusRng = new Random(seed);
_roundrelStatusDebug = new Random(seed);
_critStatusRng = new Random(random.Next());
_primeSlimeRng = new Random(random.Next());
_potionBalltRng = new Random(random.Next());
_refresherCourseRng = new Random(random.Next());
_specialSlotRng = new Random(random.Next());
_dungeonDieRng = new Random(random.Next());
_randomPegFieldRng = new Random(random.Next());
_shuffleRng = new Random(random.Next());
_specialPegRngs = new Dictionary<PegType, Random>();
return orig.Invoke(self);
}
private void DeckManagerOnShuffleCompleteDeck(orig_ShuffleCompleteDeck orig, DeckManager self, bool fromcomplete)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
State state = Random.state;
int num = _deckOrderRng.Next();
Log($"Shuffling deck with random state seed: {num}");
Random.InitState(num);
orig.Invoke(self, fromcomplete);
Random.state = state;
}
private void TargetingManagerOnOnCritActivated(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[5]
{
(Instruction i) => ILPatternMatchingExt.MatchLdcI4(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchLdsfld<AddRandomStatusEffectOnHit>(i, "RoundreloquencePotentialEffects"),
(Instruction i) => ILPatternMatchingExt.MatchLdlen(i),
(Instruction i) => ILPatternMatchingExt.MatchConvI4(i),
(Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)typeof(Random).GetMethod("Range", new Type[2]
{
typeof(int),
typeof(int)
}))
}))
{
Debug.LogWarning((object)"Failed to match call for status on crit");
return;
}
val.Index += 4;
val.Remove();
val.EmitDelegate<Func<int, int, int>>((Func<int, int, int>)delegate(int a, int b)
{
int num = _critStatusRng.Next(a, b);
Log($"Applying crit status effect: {AddRandomStatusEffectOnHit.RoundreloquencePotentialEffects[num]}");
return num;
});
}
private void RelicManagerOnGetRandomPrimeSlimeType(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[5]
{
(Instruction i) => ILPatternMatchingExt.MatchLdloc(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchLdcI4(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchLdloc(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchCallvirt(i, (MethodBase)(typeof(List<SlimeType>).GetProperty("Count")?.GetMethod)),
(Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)typeof(Random).GetMethod("Range", new Type[2]
{
typeof(int),
typeof(int)
}))
}))
{
Debug.LogWarning((object)"Failed to match call for prime slime");
return;
}
val.Index += 4;
val.Remove();
val.Emit(OpCodes.Ldloc_0);
val.EmitDelegate<Func<int, int, List<SlimeType>, int>>((Func<int, int, List<SlimeType>, int>)delegate(int a, int b, List<SlimeType> slimeTypes)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
int num = _primeSlimeRng.Next(a, b);
Log($"Applying prime slime: {slimeTypes[num]}");
return num;
});
}
private void MultiballPrefabOverridePoolOnGetMultiballGameobject(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[8]
{
(Instruction i) => ILPatternMatchingExt.MatchLdarg(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchLdfld<MultiballPrefabOverridePool>(i, "multiballOverridePool"),
(Instruction i) => ILPatternMatchingExt.MatchLdcI4(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchLdarg(i, 0),
(Instruction i) => ILPatternMatchingExt.MatchLdfld<MultiballPrefabOverridePool>(i, "multiballOverridePool"),
(Instruction i) => ILPatternMatchingExt.MatchLdlen(i),
(Instruction i) => ILPatternMatchingExt.MatchConvI4(i),
(Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)typeof(Random).GetMethod("Range", new Type[2]
{
typeof(int),
typeof(int)
}))
}))
{
Debug.LogWarning((object)"Failed to match call for potion ballt");
return;
}
val.Index += 7;
val.Remove();
FieldInfo field = typeof(MultiballPrefabOverridePool).GetField("multiballOverridePool", BindingFlags.Instance | BindingFlags.NonPublic);
val.Emit(OpCodes.Ldarg_0);
val.Emit(OpCodes.Ldfld, field);
val.EmitDelegate<Func<int, int, GameObject[], int>>((Func<int, int, GameObject[], int>)delegate(int a, int b, GameObject[] slimeTypes)
{
if (_potionBalltRng == null)
{
return Random.Range(a, b);
}
int num = _potionBalltRng.Next(a, b);
Log($"Next slime ball is: {slimeTypes[num]}");
return num;
});
}
private void PlayerStatusEffectControllerOnCheckRefreshEffects(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
{
(Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)(typeof(Random).GetProperty("value")?.GetMethod)),
(Instruction i) => ILPatternMatchingExt.MatchLdcR4(i, 0.5f)
}))
{
Debug.LogWarning((object)"Failed to match call for player status effect");
return;
}
val.Remove();
val.EmitDelegate<Func<float>>((Func<float>)delegate
{
float num = (float)_refresherCourseRng.NextDouble();
Log(((double)num < 0.5) ? "refresher course adding muscircle" : "refresher course adding spinesse");
return num;
});
}
private void SpecialSlotControllerOnBattleTurnComplete(orig_BattleTurnComplete orig, SpecialSlotController self)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
State state = Random.state;
Random.InitState(_specialSlotRng.Next());
orig.Invoke(self);
Random.state = state;
}
private void AttackOnSetRandomRolledDamage(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
{
(Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)typeof(Random).GetMethod("Range", new Type[2]
{
typeof(int),
typeof(int)
})),
(Instruction i) => ILPatternMatchingExt.MatchStfld<Attack>(i, "_randomDmgMod")
}))
{
Debug.LogWarning((object)"Failed to match call for dungeon die base damage");
return;
}
val.Remove();
val.EmitDelegate<Func<int, int, int>>((Func<int, int, int>)delegate(int a, int b)
{
int result2 = _dungeonDieRng.Next(a, b);
Log(LogLevel.Debug, $"Rolling dungeon die base damage between [{a}, {b}]");
return result2;
});
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
{
(Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)typeof(Random).GetMethod("Range", new Type[2]
{
typeof(int),
typeof(int)
})),
(Instruction i) => ILPatternMatchingExt.MatchStfld<Attack>(i, "_randomCritMod")
}))
{
Debug.LogWarning((object)"Failed to match call for dungeon die crit damage");
return;
}
val.Remove();
val.EmitDelegate<Func<int, int, int>>((Func<int, int, int>)delegate(int a, int b)
{
int result = _dungeonDieRng.Next(a, b);
Log(LogLevel.Debug, $"Rolling dungeon die crit damage between [{a}, {b}]");
return result;
});
}
private static void Log(object message)
{
Log(LogLevel.On, message);
}
private static void Log(LogLevel level, object message)
{
if (LogLevel != 0 && LogLevel >= level)
{
Debug.Log(message);
}
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "PeglinRNGSeeding";
public const string PLUGIN_NAME = "PeglinRNGSeeding";
public const string PLUGIN_VERSION = "0.0.9";
}
}