Decompiled source of MonsterDB v0.0.1
MonsterDB.dll
Decompiled 3 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using MonsterDB.Solution; using MonsterDB.Solution.Behaviors; using MonsterDB.Solution.Methods; using ServerSync; using TMPro; using UnityEngine; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: AssemblyFileVersion("0.0.1")] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("MonsterDB")] [assembly: AssemblyCompany("RustyMods")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("MonsterDB")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<6e0dc3a0-64de-4aaf-b3b3-b90948b54a8e>Embedded] internal sealed class <6e0dc3a0-64de-4aaf-b3b3-b90948b54a8e>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<6e0dc3a0-64de-4aaf-b3b3-b90948b54a8e>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<6e0dc3a0-64de-4aaf-b3b3-b90948b54a8e>Embedded] [CompilerGenerated] internal sealed class <62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContextAttribute : Attribute { public readonly byte Flag; public <62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace MonsterDB { [BepInPlugin("RustyMods.MonsterDB", "MonsterDB", "0.0.1")] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] public class MonsterDBPlugin : BaseUnityPlugin { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] public enum Toggle { On = 1, Off = 0 } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)] public string Category; [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(new byte[] { 2, 1 })] [UsedImplicitly] public Action<ConfigEntryBase> CustomDrawer; } internal const string ModName = "MonsterDB"; internal const string ModVersion = "0.0.1"; internal const string Author = "RustyMods"; private const string ModGUID = "RustyMods.MonsterDB"; private static readonly string ConfigFileName = "RustyMods.MonsterDB.cfg"; private static readonly string ConfigFileFullPath; internal static string ConnectionError; private readonly Harmony _harmony = new Harmony("RustyMods.MonsterDB"); public static readonly ManualLogSource MonsterDBLogger; public static readonly ConfigSync ConfigSync; public static GameObject m_root; public static MonsterDBPlugin m_plugin; public void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown m_plugin = this; m_root = new GameObject("root"); Object.DontDestroyOnLoad((Object)(object)m_root); m_root.SetActive(false); Tutorial.Write(); SpawnMan.Setup(); TextureManager.ReadLocalTextures(); CreatureManager.Setup(); Initialization.ReadLocalFiles(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { MonsterDBLogger.LogDebug((object)"ReadConfigValues called"); ((BaseUnityPlugin)this).Config.Reload(); } catch { MonsterDBLogger.LogError((object)("There was an issue loading your " + ConfigFileName)); MonsterDBLogger.LogError((object)"Please check your config entries for spelling and format!"); } } private ConfigEntry<T> config<[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2); syncedConfigEntry.SynchronizedConfig = synchronizedSetting; return val2; } private ConfigEntry<T> config<[<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } static MonsterDBPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ConnectionError = ""; MonsterDBLogger = Logger.CreateLogSource("MonsterDB"); ConfigSync = new ConfigSync("RustyMods.MonsterDB") { DisplayName = "MonsterDB", CurrentVersion = "0.0.1", MinimumRequiredVersion = "0.0.1" }; m_root = null; m_plugin = null; } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] public static class RegisterAndCheckVersion { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void Prefix(ZNetPeer peer, ref ZNet __instance) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Registering version RPC handler"); peer.m_rpc.Register<ZPackage>("MonsterDB_VersionCheck", (Action<ZRpc, ZPackage>)RpcHandlers.RPC_MonsterDB_Version); MonsterDBPlugin.MonsterDBLogger.LogInfo((object)"Invoking version check"); ZPackage val = new ZPackage(); val.Write("0.0.1"); peer.m_rpc.Invoke("MonsterDB_VersionCheck", new object[1] { val }); } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public static class VerifyClient { private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance) { if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc)) { return true; } MonsterDBPlugin.MonsterDBLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting")); rpc.Invoke("Error", new object[1] { 3 }); return false; } private static void Postfix(ZNet __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "MonsterDBRequestAdminSync", new object[1] { (object)new ZPackage() }); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] public class ShowConnectionError { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void Postfix(FejdStartup __instance) { if (__instance.m_connectionFailedPanel.activeSelf) { __instance.m_connectionFailedError.fontSizeMax = 25f; __instance.m_connectionFailedError.fontSizeMin = 15f; TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + MonsterDBPlugin.ConnectionError; } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] public static class RemoveDisconnectedPeerFromVerified { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void Prefix(ZNetPeer peer, ref ZNet __instance) { if (__instance.IsServer()) { MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list")); RpcHandlers.ValidatedPeers.Remove(peer.m_rpc); } } } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public static class RpcHandlers { public static readonly List<ZRpc> ValidatedPeers = new List<ZRpc>(); public static void RPC_MonsterDB_Version(ZRpc rpc, ZPackage pkg) { string text = pkg.ReadString(); MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Version check, local: 0.0.1, remote: " + text)); if (text != "0.0.1") { MonsterDBPlugin.ConnectionError = "MonsterDB Installed: 0.0.1\n Needed: " + text; if (ZNet.instance.IsServer()) { MonsterDBPlugin.MonsterDBLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting...")); rpc.Invoke("Error", new object[1] { 3 }); } } else if (!ZNet.instance.IsServer()) { MonsterDBPlugin.MonsterDBLogger.LogInfo((object)"Received same version from server!"); } else { MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list")); ValidatedPeers.Add(rpc); } } public static string ComputeHashForMod() { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(File.ReadAllBytes(Assembly.GetExecutingAssembly().Location)); StringBuilder stringBuilder = new StringBuilder(); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("X2")); } return stringBuilder.ToString(); } } } namespace MonsterDB.Solution { public static class Commands { [HarmonyPatch(typeof(Terminal), "Awake")] private static class Terminal_Awake_Patch { private static void Postfix() { LoadCommands(); } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEventFailable <>9__1_0; public static ConsoleOptionsFetcher <>9__1_1; internal object <LoadCommands>b__1_0(ConsoleEventArgs args) { if (args.Length < 2) { return false; } switch (args[1]) { case "help": Help(); break; case "clone": case "reset": case "write": case "update": case "export": case "clone_item": case "write_item": case "write_spawn": { if (args.Length < 3 || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return false; } string text = args[2]; GameObject val = DataBase.TryGetGameObject(text); if ((Object)(object)val == (Object)null) { MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Failed to find prefab: " + text)); return false; } switch (args[1]) { case "write": Write(val); break; case "update": Update(val); break; case "clone": { if (args.Length < 4) { return false; } string name2 = args[3]; CreatureManager.Clone(val, name2); break; } case "reset": CreatureManager.Reset(val); break; case "write_item": if (!Object.op_Implicit((Object)(object)val.GetComponent<ItemDrop>())) { return false; } ItemDataMethods.Write(val); break; case "clone_item": { if (args.Length < 4) { return false; } string name = args[3]; ItemDataMethods.Clone(val, name); break; } case "write_spawn": MonsterDBPlugin.MonsterDBLogger.LogInfo((object)(SpawnMan.Write(val) ? "Wrote spawn data to disk" : "Failed to find spawn data")); break; case "export": CreatureManager.Export(text); break; } break; } case "reload": Initialization.RemoveAll(); Initialization.CloneAll(); Initialization.UpdateAll(); break; case "import": CreatureManager.Import(); Initialization.RemoveAll(); Initialization.CloneAll(); Initialization.UpdateAll(); break; } return true; } internal List<string> <LoadCommands>b__1_1() { return new List<string> { "help", "write", "update", "clone", "reset", "reload", "write_item", "clone_item", "import", "export" }; } } private static void LoadCommands() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEventFailable val = delegate(ConsoleEventArgs args) { if (args.Length < 2) { return false; } switch (args[1]) { case "help": Help(); break; case "clone": case "reset": case "write": case "update": case "export": case "clone_item": case "write_item": case "write_spawn": { if (args.Length < 3 || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return false; } string text = args[2]; GameObject val4 = DataBase.TryGetGameObject(text); if ((Object)(object)val4 == (Object)null) { MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Failed to find prefab: " + text)); return false; } switch (args[1]) { case "write": Write(val4); break; case "update": Update(val4); break; case "clone": { if (args.Length < 4) { return false; } string name2 = args[3]; CreatureManager.Clone(val4, name2); break; } case "reset": CreatureManager.Reset(val4); break; case "write_item": if (!Object.op_Implicit((Object)(object)val4.GetComponent<ItemDrop>())) { return false; } ItemDataMethods.Write(val4); break; case "clone_item": { if (args.Length < 4) { return false; } string name = args[3]; ItemDataMethods.Clone(val4, name); break; } case "write_spawn": MonsterDBPlugin.MonsterDBLogger.LogInfo((object)(SpawnMan.Write(val4) ? "Wrote spawn data to disk" : "Failed to find spawn data")); break; case "export": CreatureManager.Export(text); break; } break; } case "reload": Initialization.RemoveAll(); Initialization.CloneAll(); Initialization.UpdateAll(); break; case "import": CreatureManager.Import(); Initialization.RemoveAll(); Initialization.CloneAll(); Initialization.UpdateAll(); break; } return true; }; <>c.<>9__1_0 = val; obj = (object)val; } object obj2 = <>c.<>9__1_1; if (obj2 == null) { ConsoleOptionsFetcher val2 = () => new List<string> { "help", "write", "update", "clone", "reset", "reload", "write_item", "clone_item", "import", "export" }; <>c.<>9__1_1 = val2; obj2 = (object)val2; } ConsoleCommand val3 = new ConsoleCommand("monsterdb", "use help to list out commands", (ConsoleEventFailable)obj, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, true); } private static void Help() { foreach (string item in new List<string> { "write [prefabName] - write creature data to disk", "update [prefabName] - reads files and updates creature", "clone [prefabName] [cloneName] - clones creature, and saves to disk", "reset [prefabName] - resets creature data to original state", "reload - reloads all MonsterDB files", "write_item [prefabName] - Saves ItemData to file for reference", "clone_item [prefabName] [cloneName] - clones item to use as a new attack for creatures", "write_spawn [prefabName] - Writes to disk spawn data, of current spawn system", "import - Imports all creature files from Import folder, and reload data", "export [prefabName] - Writes creature data to a single YML document to share" }) { MonsterDBPlugin.MonsterDBLogger.LogInfo((object)item); } } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void Write(GameObject prefab) { if (CreatureManager.IsClone(prefab)) { MonsterDBPlugin.MonsterDBLogger.LogInfo((object)"Creature is a MonsterDB clone, will not write to disk"); return; } CreatureManager.Write(prefab, out var folderPath); MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Saved " + ((Object)prefab).name + " at:")); MonsterDBPlugin.MonsterDBLogger.LogInfo((object)folderPath); } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void Update(GameObject prefab) { CreatureManager.Read(((Object)prefab).name, CreatureManager.IsClone(prefab)); CreatureManager.Update(prefab); MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Updated " + ((Object)prefab).name)); } } [Serializable] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] public class CharacterData { public string ClonedFrom = ""; public string PrefabName = ""; public string Name = ""; public string Group = ""; public string Faction = ""; public bool Boss; public bool DoNotHideBossHUD; public string BossEvent = ""; public string DefeatSetGlobalKey = ""; public bool AISkipTarget; public float CrouchSpeed; public float WalkSpeed; public float Speed; public float TurnSpeed; public float RunSpeed; public float RunTurnSpeed; public float FlySlowSpeed; public float FlyFastSpeed; public float FlyTurnSpeed; public float Acceleration; public float JumpForce; public float JumpForceForward; public float JumpForceTiredFactor; public float AirControl; public bool CanSwim; public float SwimDepth; public float SwimSpeed; public float SwimTurnSpeed; public float SwimAcceleration; public string GroundTilt = ""; public float GroundTiltSpeed; public bool Flying; public float JumpStaminaUsage; public bool DisableWhileSleeping; public bool TolerateWater; public bool TolerateFire; public bool TolerateSmoke; public bool TolerateTar; public float Health; public string BluntResistance = "Normal"; public string SlashResistance = "Normal"; public string PierceResistance = "Normal"; public string ChopResistance = "Normal"; public string PickaxeResistance = "Normal"; public string FireResistance = "Normal"; public string FrostResistance = "Normal"; public string LightningResistance = "Normal"; public string PoisonResistance = "Normal"; public string SpiritResistance = "Normal"; public bool StaggerWhenBlocked; public float StaggerDamageFactor; } [Serializable] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] public class EffectInfo { public string PrefabName = ""; public bool Enabled; public int Variant = -1; public bool Attach; public bool Follow; public bool InheritParentRotation; public bool InheritParentScale; public bool MultiplyParentVisualScale; public bool RandomRotation; public bool Scale; public string ChildTransform = ""; } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class AttackData { public string OriginalPrefab = ""; public string Name = ""; public string AnimationState = ""; public int ToolTier; public float Damage; public float Blunt; public float Slash; public float Pierce; public float Chop; public float Pickaxe; public float Fire; public float Frost; public float Lightning; public float Poison; public float Spirit; public float AttackForce; public bool Dodgeable; public bool Blockable; public string SpawnOnHit = ""; public string SpawnOnHitTerrain = ""; public string AttackStatusEffect = ""; public float AttackStatusEffectChance; public string AttackType = ""; public string AttackAnimation = ""; public bool HitTerrain; public bool HitFriendly; public float DamageMultiplier; public float DamageMultiplierPerMissingHP; public float DamageMultiplierByTotalHealthMissing; public float ForceMultiplier; public float StaggerMultiplier; public float RecoilPushback; public int SelfDamage; public string AttackOriginJoint = ""; public float AttackRange; public float AttackHeight; public float AttackOffset; public string SpawnOnTrigger = ""; public bool ToggleFlying; public bool Attach; public float AttackAngle; public float AttackRayWidth; public float MaxYAngle; public bool LowerDamagePerHit; public bool HitThroughWalls; public float AttackRangeMinimum; public float AttackInterval; public float AttackMaxAngle; public string Projectile = ""; } [Serializable] public class RandomItemData { [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(1)] public string PrefabName = ""; public float Chance; } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class ProjectileData { public string Name = ""; public float Damage; public float Blunt; public float Slash; public float Pierce; public float Chop; public float Pickaxe; public float Fire; public float Frost; public float Lightning; public float Poison; public float Spirit; public float AOE; public bool Dodgeable; public bool Blockable; public float AttackForce; public float BackstabBonus; public string StatusEffect = ""; public float HealthReturn; public bool CanHitWater; public float Duration; public float Gravity; public float Drag; public float RayRadius; public bool StayAfterHitStatic; public bool StayAfterHitDynamic; public float StayDuration; public bool Bounce; public bool BounceOnWater; public float BouncePower; public float BounceRoughness; public int MaxBounces; public float MinBounceVelocity; public bool RespawnItemOnHit; public bool SpawnOnDuration; public string SpawnOnHit = ""; public float SpawnOnHitChance; public int SpawnCount; public List<string> RandomSpawnOnHit = new List<string>(); public int RandomSpawnOnHitCount; public bool RandomSpawnSkipLava; public bool StaticHitOnly; public bool GroundHitOnly; public bool SpawnRandomRotation; } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class MonsterAIData { public float ViewRange; public float ViewAngle; public float HearRange; public bool MistVision; public float IdleSoundInterval; public float IdleSoundChance; public string PathAgentType = ""; public float MoveMinAngle; public bool SmoothMovement; public bool SerpentMovement; public float SerpentTurnRadius; public float JumpInterval; public float RandomCircleInterval; public float RandomMoveInterval; public float RandomMoveRange; public bool RandomFly; public float ChanceToTakeOff; public float ChanceToLand; public float GroundDuration; public float AirDuration; public float MaxLandAltitude; public float TakeoffTime; public float FlyAltitudeMin; public float FlyAltitudeMax; public float FlyAbsMinAltitude; public bool AvoidFire; public bool AfraidOfFire; public bool AvoidWater; public bool AvoidLava; public bool SkipLavaTargets; public bool Aggravatable; public bool PassiveAggressive; public string SpawnMessage = ""; public string DeathMessage = ""; public string AlertedMessage = ""; public float FleeRange; public float FleeAngle; public float FleeInterval; public float AlertRange; public bool FleeIfHurtWhenTargetCannotBeReached; public float FleeUnreachableSinceAttack; public float FleeUnreachableSinceHurt; public bool FleeIfNotAlerted; public float FleeIfLowHealth; public float FleeTimeSinceHurt; public bool FleeInLava; public bool CirculateWhileCharging; public bool CirculateWhileChargingFlying; public bool EnableHuntPlayer; public bool AttackPlayerObjects; public int PrivateAreaTriggerThreshold; public float InterceptTimeMax; public float InterceptTimeMin; public float MaxChaseDistance; public float MinAttackInterval; public float CircleTargetInterval; public float CircleTargetDuration; public float CircleTargetDistance; public bool Sleeping; public float WakeupRange; public bool NoiseWakeup; public float MaxNoiseWakeupRange; public float WakeupDelayMin; public float WakeupDelayMax; public bool AvoidLand; public List<string> ConsumeItems = new List<string>(); public float ConsumeRange; public float ConsumeSearchRange; public float ConsumeSearchInterval; } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class AnimalAIData { public float ViewRange; public float ViewAngle; public float HearRange; public bool MistVision; public float IdleSoundInterval; public float IdleSoundChance; public string PathAgentType = ""; public float MoveMinAngle; public bool SmoothMovement; public bool SerpentMovement; public float SerpentTurnRadius; public float JumpInterval; public float RandomCircleInterval; public float RandomMoveInterval; public float RandomMoveRange; public bool RandomFly; public float ChanceToTakeOff; public float ChanceToLand; public float GroundDuration; public float AirDuration; public float MaxLandAltitude; public float TakeoffTime; public float FlyAltitudeMin; public float FlyAltitudeMax; public float FlyAbsMinAltitude; public bool AvoidFire; public bool AfraidOfFire; public bool AvoidWater; public bool AvoidLava; public bool SkipLavaTargets; public bool Aggravatable; public bool PassiveAggressive; public string SpawnMessage = ""; public string DeathMessage = ""; public string AlertedMessage = ""; public float FleeRange; public float FleeAngle; public float FleeInterval; } [Serializable] public class CharacterDropData { [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(1)] public string PrefabName = ""; public int AmountMin; public int AmountMax; public float Chance; public bool OnePerPlayer; public bool LevelMultiplier; public bool DoNotScale; } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class TameableData { public float FedDuration; public float TamingTime; public bool StartTamed; public bool Commandable; public float UnsummonDistance; public float UnsummonOnOwnerLogoutSeconds; public string LevelUpOwnerSkill = ""; public float LevelUpFactor; public bool DropSaddleOnDeath; public List<string> RandomStartingName = new List<string>(); } [Serializable] public class ProcreationData { public float UpdateInterval; public float TotalCheckRange; public int MaxCreatures; public float PartnerCheckRange; public float PregnancyChance; public float PregnancyDuration; public int RequiredLovePoints; [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(1)] public string Offspring = ""; public int MinOffspringLevel; public float SpawnOffset; } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class NPCTalkData { public string Name = ""; public float MaxRange; public float GreetRange; public float ByeRange; public float Offset; public float MinTalkInterval; public float HideDialogueDelay; public float RandomTalkInterval; public float RandomTalkChance; public List<string> RandomTalk = new List<string>(); public List<string> RandomTalkInFactionBase = new List<string>(); public List<string> RandomGreets = new List<string>(); public List<string> RandomGoodbye = new List<string>(); public List<string> PrivateAreaAlarm = new List<string>(); public List<string> Aggravated = new List<string>(); } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class CreatureData { public VisualMethods.ScaleData m_scale = new VisualMethods.ScaleData(); public VisualMethods.ScaleData m_ragdollScale = new VisualMethods.ScaleData(); public Dictionary<string, VisualMethods.MaterialData> m_materials = new Dictionary<string, VisualMethods.MaterialData>(); public CharacterData m_characterData = new CharacterData(); public CharacterEffects m_effects = new CharacterEffects(); public List<ItemAttackData> m_defaultItems = new List<ItemAttackData>(); public List<ItemAttackData> m_randomWeapons = new List<ItemAttackData>(); public List<ItemAttackData> m_randomArmors = new List<ItemAttackData>(); public List<ItemAttackData> m_randomShields = new List<ItemAttackData>(); public List<RandomItemData> m_randomItems = new List<RandomItemData>(); public List<RandomItemSetsData> m_randomSets = new List<RandomItemSetsData>(); public MonsterAIData m_monsterAIData = new MonsterAIData(); public AnimalAIData m_animalAIData = new AnimalAIData(); public List<CharacterDropData> m_characterDrops = new List<CharacterDropData>(); public TameableData m_tameable = new TameableData(); public ProcreationData m_procreation = new ProcreationData(); public NPCTalkData m_npcTalk = new NPCTalkData(); } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class ItemAttackData { public AttackData m_attackData = new AttackData(); public ItemEffects m_effects = new ItemEffects(); } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class RandomItemSetsData { public string m_name = ""; public List<ItemAttackData> m_items = new List<ItemAttackData>(); } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class CharacterEffects { public List<EffectInfo> m_hitEffects = new List<EffectInfo>(); public List<EffectInfo> m_critHitEffects = new List<EffectInfo>(); public List<EffectInfo> m_backstabHitEffects = new List<EffectInfo>(); public List<EffectInfo> m_deathEffects = new List<EffectInfo>(); public List<EffectInfo> m_waterEffects = new List<EffectInfo>(); public List<EffectInfo> m_tarEffects = new List<EffectInfo>(); public List<EffectInfo> m_slideEffects = new List<EffectInfo>(); public List<EffectInfo> m_jumpEffects = new List<EffectInfo>(); public List<EffectInfo> m_flyingContinuousEffects = new List<EffectInfo>(); public List<EffectInfo> m_pickupEffects = new List<EffectInfo>(); public List<EffectInfo> m_dropEffects = new List<EffectInfo>(); public List<EffectInfo> m_consumeItemEffects = new List<EffectInfo>(); public List<EffectInfo> m_equipEffects = new List<EffectInfo>(); public List<EffectInfo> m_perfectBlockEffects = new List<EffectInfo>(); public List<EffectInfo> m_alertedEffects = new List<EffectInfo>(); public List<EffectInfo> m_idleSounds = new List<EffectInfo>(); public List<EffectInfo> m_wakeupEffects = new List<EffectInfo>(); public List<EffectInfo> m_birthEffects = new List<EffectInfo>(); public List<EffectInfo> m_loveEffects = new List<EffectInfo>(); public List<EffectInfo> m_tamedEffects = new List<EffectInfo>(); public List<EffectInfo> m_soothEffects = new List<EffectInfo>(); public List<EffectInfo> m_petEffects = new List<EffectInfo>(); public List<EffectInfo> m_unSummonEffects = new List<EffectInfo>(); public List<EffectInfo> m_randomTalkFX = new List<EffectInfo>(); public List<EffectInfo> m_randomGreetFX = new List<EffectInfo>(); public List<EffectInfo> m_randomGoodbyeFX = new List<EffectInfo>(); } [Serializable] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public class ItemEffects { public List<EffectInfo> m_hitEffects = new List<EffectInfo>(); public List<EffectInfo> m_hitTerrainEffects = new List<EffectInfo>(); public List<EffectInfo> m_blockEffects = new List<EffectInfo>(); public List<EffectInfo> m_startEffects = new List<EffectInfo>(); public List<EffectInfo> m_holdStartEffects = new List<EffectInfo>(); public List<EffectInfo> m_equipEffects = new List<EffectInfo>(); public List<EffectInfo> m_unEquipEffects = new List<EffectInfo>(); public List<EffectInfo> m_triggerEffects = new List<EffectInfo>(); public List<EffectInfo> m_trailStartEffects = new List<EffectInfo>(); } [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] public static class CreatureManager { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "Awake")] private static class ZNet_Awake_Patch { private static void Postfix() { UpdateServer(); } } public static readonly string m_folderPath; public static readonly string m_creatureFolderPath; public static readonly string m_cloneFolderPath; private static readonly string m_exportFolderPath; private static readonly string m_importFolderPath; private static readonly CustomSyncedValue<string> m_serverDataFiles; private static readonly Dictionary<string, CreatureData> m_originalData; public static Dictionary<string, CreatureData> m_data; public static readonly Dictionary<string, GameObject> m_clones; private static FileSystemWatcher m_creatureWatcher; private static FileSystemWatcher m_cloneWatcher; private static void UpdateServer() { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Server: Updating server sync creature & clones"); ISerializer serializer = new SerializerBuilder().Build(); m_serverDataFiles.Value = serializer.Serialize(m_data); } } public static bool IsClone(GameObject creature) { return m_clones.ContainsKey(((Object)creature).name); } public static void Setup() { m_serverDataFiles.ValueChanged += ReadServerFiles; SetupFileWatch(); } private static void SetupFileWatch() { if (!Directory.Exists(m_folderPath)) { Directory.CreateDirectory(m_folderPath); } if (!Directory.Exists(m_creatureFolderPath)) { Directory.CreateDirectory(m_creatureFolderPath); } if (!Directory.Exists(m_cloneFolderPath)) { Directory.CreateDirectory(m_cloneFolderPath); } if (!Directory.Exists(m_importFolderPath)) { Directory.CreateDirectory(m_importFolderPath); } m_creatureWatcher = new FileSystemWatcher(m_creatureFolderPath, "*.yml") { EnableRaisingEvents = true, IncludeSubdirectories = true, SynchronizingObject = ThreadingHelper.SynchronizingObject, NotifyFilter = NotifyFilters.LastWrite }; m_creatureWatcher.Changed += OnCreatureFileChange; m_cloneWatcher = new FileSystemWatcher(m_cloneFolderPath, "*.yml") { EnableRaisingEvents = true, IncludeSubdirectories = true, SynchronizingObject = ThreadingHelper.SynchronizingObject, NotifyFilter = NotifyFilters.LastWrite }; m_cloneWatcher.Changed += OnCloneFileChange; FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(m_importFolderPath, "*.yml") { EnableRaisingEvents = true, IncludeSubdirectories = true, SynchronizingObject = ThreadingHelper.SynchronizingObject, NotifyFilter = NotifyFilters.LastWrite }; fileSystemWatcher.Changed += OnImportFileChange; } private static void OnImportFileChange(object sender, FileSystemEventArgs e) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return; } try { string fileName = Path.GetFileName(e.Name); IDeserializer deserializer = new DeserializerBuilder().Build(); string input = File.ReadAllText(e.FullPath); CreatureData creatureData = deserializer.Deserialize<CreatureData>(input); GameObject val = DataBase.TryGetGameObject(creatureData.m_characterData.PrefabName); if (!((Object)(object)val == (Object)null)) { m_data[creatureData.m_characterData.PrefabName] = creatureData; UpdateServer(); Update(val); MonsterDBPlugin.MonsterDBLogger.LogDebug((object)(((Object)val).name + " data changed: " + fileName)); } } catch { Helpers.LogParseFailure(e.FullPath); } } private static void OnCloneFileChange(object sender, FileSystemEventArgs e) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { string fileName = Path.GetFileName(e.Name); string cloneFolderName = GetCloneFolderName(e.FullPath); GameObject val = DataBase.TryGetGameObject(cloneFolderName); if (!((Object)(object)val == (Object)null)) { Read(cloneFolderName, isClone: true); Update(val); MonsterDBPlugin.MonsterDBLogger.LogDebug((object)(cloneFolderName + " data changed: " + fileName)); } } } private static void OnCreatureFileChange(object sender, FileSystemEventArgs e) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { string fileName = Path.GetFileName(e.Name); string creatureFolderName = GetCreatureFolderName(e.FullPath); GameObject val = DataBase.TryGetGameObject(creatureFolderName); if (!((Object)(object)val == (Object)null)) { Read(creatureFolderName); Update(val); MonsterDBPlugin.MonsterDBLogger.LogDebug((object)(creatureFolderName + " data changed: " + fileName)); } } } private static string GetCloneFolderName(string fullPath) { return fullPath.Replace(m_cloneFolderPath, string.Empty).Split(new char[1] { Path.DirectorySeparatorChar })[1]; } private static string GetCreatureFolderName(string fullPath) { return fullPath.Replace(m_creatureFolderPath, string.Empty).Split(new char[1] { Path.DirectorySeparatorChar })[1]; } private static void ReadServerFiles() { if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.IsServer()) { return; } IDeserializer deserializer = new DeserializerBuilder().Build(); try { Initialization.ResetAll(); m_data = deserializer.Deserialize<Dictionary<string, CreatureData>>(m_serverDataFiles.Value); Initialization.RemoveAll(); Initialization.CloneAll(); Initialization.UpdateAll(); MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Server updated MonsterDB Files"); } catch { MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Failed to parse server synced data"); } } public static void Delete(GameObject critter, bool loop = true) { string prefabName = ((Object)critter).name + "_ragdoll"; GameObject val = DataBase.TryGetGameObject(prefabName); if ((Object)(object)val != (Object)null) { Delete(val, loop); } Helpers.RemoveFromZNetScene(critter); Helpers.RemoveFromObjectDB(critter); if (!loop) { m_clones.Remove(((Object)critter).name); } Transform val2 = MonsterDBPlugin.m_root.transform.Find(((Object)critter).name); if (Object.op_Implicit((Object)(object)val2)) { Object.Destroy((Object)(object)((Component)val2).gameObject); } } private static void Save(GameObject critter, string cloneFrom) { if (!m_originalData.ContainsKey(((Object)critter).name)) { CreatureData creatureData = new CreatureData(); VisualMethods.Save(critter, ref creatureData); HumanoidMethods.Save(critter, cloneFrom, ref creatureData); CharacterMethods.Save(critter, cloneFrom, ref creatureData); MonsterAIMethods.Save(critter, ref creatureData); AnimalAIMethods.Save(critter, ref creatureData); CharacterDropMethods.Save(critter, ref creatureData); TameableMethods.Save(critter, ref creatureData); ProcreationMethods.Save(critter, ref creatureData); NPCTalkMethods.Save(critter, ref creatureData); m_originalData[((Object)critter).name] = creatureData; } } public static void Write(GameObject critter, out string folderPath, bool clone = false, string clonedFrom = "") { m_creatureWatcher.EnableRaisingEvents = false; m_cloneWatcher.EnableRaisingEvents = false; if (!Directory.Exists(m_folderPath)) { Directory.CreateDirectory(m_folderPath); } if (!Directory.Exists(m_creatureFolderPath)) { Directory.CreateDirectory(m_creatureFolderPath); } string obj = (clone ? m_cloneFolderPath : m_creatureFolderPath); char directorySeparatorChar = Path.DirectorySeparatorChar; folderPath = obj + directorySeparatorChar + ((Object)critter).name; if (Directory.Exists(folderPath)) { Directory.Delete(folderPath, recursive: true); } Directory.CreateDirectory(folderPath); VisualMethods.Write(critter, folderPath); HumanoidMethods.Write(critter, folderPath, clonedFrom); CharacterMethods.Write(critter, folderPath, clonedFrom); MonsterAIMethods.Write(critter, folderPath); AnimalAIMethods.Write(critter, folderPath); CharacterDropMethods.Write(critter, folderPath); TameableMethods.Write(critter, folderPath); ProcreationMethods.Write(critter, folderPath); NPCTalkMethods.Write(critter, folderPath); m_creatureWatcher.EnableRaisingEvents = true; m_cloneWatcher.EnableRaisingEvents = true; } public static void Read(string creatureName, bool isClone = false) { string obj = (isClone ? m_cloneFolderPath : m_creatureFolderPath); char directorySeparatorChar = Path.DirectorySeparatorChar; string text = obj + directorySeparatorChar + creatureName; if (Directory.Exists(text)) { CreatureData creatureData = new CreatureData(); VisualMethods.Read(text, ref creatureData); HumanoidMethods.Read(text, ref creatureData); CharacterMethods.Read(text, ref creatureData); MonsterAIMethods.Read(text, ref creatureData); AnimalAIMethods.Read(text, ref creatureData); CharacterDropMethods.Read(text, ref creatureData); TameableMethods.Read(text, ref creatureData); ProcreationMethods.Read(text, ref creatureData); NPCTalkMethods.Read(text, ref creatureData); m_data[creatureName] = creatureData; UpdateServer(); } } public static void Update(GameObject critter) { if (m_data.TryGetValue(((Object)critter).name, out var value)) { Save(critter, value.m_characterData.ClonedFrom); VisualMethods.Update(critter, value); TameableMethods.Update(critter, value); HumanoidMethods.Update(critter, value); CharacterMethods.Update(critter, value); MonsterAIMethods.Update(critter, value); AnimalAIMethods.Update(critter, value); CharacterDropMethods.Update(critter, value); ProcreationMethods.Update(critter, value); NPCTalkMethods.Update(critter, value); } } public static void Reset(GameObject critter) { if (m_originalData.TryGetValue(((Object)critter).name, out var value)) { VisualMethods.Update(critter, value); HumanoidMethods.Update(critter, value); CharacterMethods.Update(critter, value); MonsterAIMethods.Update(critter, value); AnimalAIMethods.Update(critter, value); CharacterDropMethods.Update(critter, value); TameableMethods.Update(critter, value); ProcreationMethods.Update(critter, value); NPCTalkMethods.Update(critter, value); MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Reset: " + ((Object)critter).name)); } } public static void Clone(GameObject critter, string name, bool saveToDisk = true) { if (!Directory.Exists(m_folderPath)) { Directory.CreateDirectory(m_folderPath); } if (!Directory.Exists(m_cloneFolderPath)) { Directory.CreateDirectory(m_cloneFolderPath); } GameObject val = Object.Instantiate<GameObject>(critter, MonsterDBPlugin.m_root.transform, false); ((Object)val).name = name; Dictionary<string, Material> ragDollMats = VisualMethods.CloneMaterials(val); CharacterMethods.CloneRagDoll(val, ragDollMats); HumanoidMethods.CloneRagDoll(val, ragDollMats); HumanoidMethods.CloneItems(val); Helpers.RegisterToZNetScene(val); m_clones[((Object)val).name] = val; if (saveToDisk) { Write(val, out var folderPath, clone: true, ((Object)critter).name); Read(((Object)val).name, isClone: true); MonsterDBPlugin.MonsterDBLogger.LogInfo((object)("Cloned " + ((Object)critter).name + " as " + ((Object)val).name)); MonsterDBPlugin.MonsterDBLogger.LogInfo((object)folderPath); } } public static void Export(string creatureName) { if (!Directory.Exists(m_folderPath)) { Directory.CreateDirectory(m_folderPath); } if (!Directory.Exists(m_exportFolderPath)) { Directory.CreateDirectory(m_exportFolderPath); } if (!Directory.Exists(m_importFolderPath)) { Directory.CreateDirectory(m_importFolderPath); } if (m_data.TryGetValue(creatureName, out var value)) { ISerializer serializer = new SerializerBuilder().Build(); string contents = serializer.Serialize(value); string exportFolderPath = m_exportFolderPath; char directorySeparatorChar = Path.DirectorySeparatorChar; string text = exportFolderPath + directorySeparatorChar + creatureName + ".yml"; File.WriteAllText(text, contents); MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Exported creature data: "); MonsterDBPlugin.MonsterDBLogger.LogDebug((object)text); } } public static void Import() { if (!Directory.Exists(m_folderPath)) { Directory.CreateDirectory(m_folderPath); } if (!Directory.Exists(m_importFolderPath)) { Directory.CreateDirectory(m_importFolderPath); } string[] files = Directory.GetFiles(m_importFolderPath); if (files.Length == 0) { return; } IDeserializer deserializer = new DeserializerBuilder().Build(); int num = 0; string[] array = files; foreach (string text in array) { try { string input = File.ReadAllText(text); CreatureData creatureData = deserializer.Deserialize<CreatureData>(input); string prefabName = creatureData.m_characterData.PrefabName; m_data[prefabName] = creatureData; num++; } catch { Helpers.LogParseFailure(text); } } MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Imported {num} creature data files"); } static CreatureManager() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; m_folderPath = configPath + directorySeparatorChar + "MonsterDB"; string folderPath = m_folderPath; directorySeparatorChar = Path.DirectorySeparatorChar; m_creatureFolderPath = folderPath + directorySeparatorChar + "Creatures"; string folderPath2 = m_folderPath; directorySeparatorChar = Path.DirectorySeparatorChar; m_cloneFolderPath = folderPath2 + directorySeparatorChar + "Clones"; string folderPath3 = m_folderPath; directorySeparatorChar = Path.DirectorySeparatorChar; m_exportFolderPath = folderPath3 + directorySeparatorChar + "Export"; string folderPath4 = m_folderPath; directorySeparatorChar = Path.DirectorySeparatorChar; m_importFolderPath = folderPath4 + directorySeparatorChar + "Import"; m_serverDataFiles = new CustomSyncedValue<string>(MonsterDBPlugin.ConfigSync, "MonsterDB_ServerFiles", ""); m_originalData = new Dictionary<string, CreatureData>(); m_data = new Dictionary<string, CreatureData>(); m_clones = new Dictionary<string, GameObject>(); m_creatureWatcher = null; m_cloneWatcher = null; } } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public static class DataBase { [HarmonyPriority(800)] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class CacheResources_Patch { private static void Postfix() { CacheResources(); } } private static readonly Dictionary<string, GameObject> m_items = new Dictionary<string, GameObject>(); public static readonly Dictionary<string, Texture2D> m_textures = new Dictionary<string, Texture2D>(); private static void CacheResources() { List<GameObject> list = Resources.FindObjectsOfTypeAll<GameObject>().ToList(); foreach (GameObject item in list) { m_items[((Object)item).name] = item; } List<Texture2D> source = Resources.FindObjectsOfTypeAll<Texture2D>().ToList(); foreach (Texture2D item2 in source.Where([<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] (Texture2D texture) => !Utility.IsNullOrWhiteSpace(((Object)texture).name))) { m_textures[((Object)item2).name] = item2; } string texturePath = TextureManager.m_texturePath; char directorySeparatorChar = Path.DirectorySeparatorChar; string path = texturePath + directorySeparatorChar + "Resources.txt"; if (!File.Exists(path)) { List<string> contents = m_textures.Keys.ToList(); File.WriteAllLines(path, contents); } } [return: <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)] public static GameObject TryGetGameObject(string prefabName) { if (!Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return null; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName); if ((Object)(object)itemPrefab != (Object)null) { return itemPrefab; } itemPrefab = ZNetScene.instance.GetPrefab(prefabName); if ((Object)(object)itemPrefab != (Object)null) { return itemPrefab; } if (ItemDataMethods.m_clonedItems.TryGetValue(prefabName, out var value)) { return value; } GameObject value2; return (!m_items.TryGetValue(prefabName, out value2)) ? null : value2; } public static bool TryGetTexture(string textureName, out Texture2D texture) { if (TextureManager.m_customTextures.TryGetValue(textureName, out texture)) { return true; } return m_textures.TryGetValue(textureName, out texture); } } public static class HumanMan { public static void Create() { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Expected O, but got Unknown //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Expected O, but got Unknown //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Expected O, but got Unknown //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Expected O, but got Unknown //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Expected O, but got Unknown //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_0606: Unknown result type (might be due to invalid IL or missing references) //IL_061b: Unknown result type (might be due to invalid IL or missing references) //IL_0622: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Unknown result type (might be due to invalid IL or missing references) //IL_0635: Unknown result type (might be due to invalid IL or missing references) //IL_0641: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Expected O, but got Unknown GameObject prefab = ZNetScene.instance.GetPrefab("Player"); Player val = default(Player); if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<Player>(ref val)) { GameObject val2 = Object.Instantiate<GameObject>(prefab, MonsterDBPlugin.m_root.transform, false); ((Object)val2).name = "Human"; Object.Destroy((Object)(object)val2.GetComponent<PlayerController>()); Object.Destroy((Object)(object)val2.GetComponent<Player>()); Object.Destroy((Object)(object)val2.GetComponent<Talker>()); Object.Destroy((Object)(object)val2.GetComponent<Skills>()); ZNetView val3 = default(ZNetView); if (val2.TryGetComponent<ZNetView>(ref val3)) { val3.m_persistent = true; } Human human = val2.AddComponent<Human>(); ((Object)human).name = ((Object)val2).name; ((Character)human).m_name = "Human"; ((Character)human).m_group = "Humans"; ((Character)human).m_faction = (Faction)2; ((Character)human).m_crouchSpeed = ((Character)val).m_crouchSpeed; ((Character)human).m_walkSpeed = ((Character)val).m_walkSpeed; ((Character)human).m_speed = ((Character)val).m_speed; ((Character)human).m_runSpeed = ((Character)val).m_runSpeed; ((Character)human).m_runTurnSpeed = ((Character)val).m_runTurnSpeed; ((Character)human).m_acceleration = ((Character)val).m_acceleration; ((Character)human).m_jumpForce = ((Character)val).m_jumpForce; ((Character)human).m_jumpForceForward = ((Character)val).m_jumpForceForward; ((Character)human).m_jumpForceTiredFactor = ((Character)val).m_jumpForceForward; ((Character)human).m_airControl = ((Character)val).m_airControl; ((Character)human).m_canSwim = true; ((Character)human).m_swimDepth = ((Character)val).m_swimDepth; ((Character)human).m_swimSpeed = ((Character)val).m_swimSpeed; ((Character)human).m_swimTurnSpeed = ((Character)val).m_swimTurnSpeed; ((Character)human).m_swimAcceleration = ((Character)val).m_swimAcceleration; ((Character)human).m_groundTilt = ((Character)val).m_groundTilt; ((Character)human).m_groundTiltSpeed = ((Character)val).m_groundTiltSpeed; ((Character)human).m_jumpStaminaUsage = ((Character)val).m_jumpStaminaUsage; ((Character)human).m_eye = Utils.FindChild(val2.transform, "EyePos", (IterativeSearchType)0); ((Character)human).m_hitEffects = ((Character)val).m_hitEffects; ((Character)human).m_critHitEffects = ((Character)val).m_critHitEffects; ((Character)human).m_backstabHitEffects = ((Character)val).m_backstabHitEffects; GameObject val4 = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("Player_ragdoll"), MonsterDBPlugin.m_root.transform, false); Ragdoll val5 = default(Ragdoll); EffectList val6; if (val4.TryGetComponent<Ragdoll>(ref val5)) { val5.m_ttl = 8f; Ragdoll obj = val5; val6 = new EffectList(); val6.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { new EffectData { m_prefab = ZNetScene.instance.GetPrefab("vfx_corpse_destruction_small"), m_enabled = true } }; obj.m_removeEffect = val6; val5.m_float = true; val5.m_dropItems = true; } ((Object)val4).name = "human_ragdoll"; val4.AddComponent<Visuals>(); Helpers.RegisterToZNetScene(val4); val6 = new EffectList(); val6.m_effectPrefabs = (EffectData[])(object)new EffectData[2] { new EffectData { m_prefab = ZNetScene.instance.GetPrefab("vfx_player_death"), m_enabled = true }, new EffectData { m_prefab = val4, m_enabled = true } }; ((Character)human).m_deathEffects = val6; ((Character)human).m_waterEffects = ((Character)val).m_waterEffects; ((Character)human).m_tarEffects = ((Character)val).m_tarEffects; ((Character)human).m_slideEffects = ((Character)val).m_slideEffects; ((Character)human).m_jumpEffects = ((Character)val).m_jumpEffects; ((Character)human).m_flyingContinuousEffect = ((Character)val).m_flyingContinuousEffect; ((Character)human).m_tolerateWater = true; ((Character)human).m_health = 100f; ((Character)human).m_damageModifiers = ((Character)val).m_damageModifiers; ((Character)human).m_staggerWhenBlocked = true; ((Character)human).m_staggerDamageFactor = ((Character)val).m_staggerDamageFactor; ((Humanoid)human).m_defaultItems = ((Humanoid)val).m_defaultItems; ((Humanoid)human).m_randomWeapon = ((Humanoid)val).m_randomWeapon; ((Humanoid)human).m_randomArmor = ((Humanoid)val).m_randomArmor; ((Humanoid)human).m_randomShield = ((Humanoid)val).m_randomShield; ItemSet[] array = new ItemSet[2]; ItemSet val7 = new ItemSet(); val7.m_name = "Leather"; val7.m_items = (GameObject[])(object)new GameObject[3] { ZNetScene.instance.GetPrefab("ArmorLeatherChest"), ZNetScene.instance.GetPrefab("ArmorLeatherLegs"), ZNetScene.instance.GetPrefab("Torch") }; array[0] = val7; val7 = new ItemSet(); val7.m_name = "Bronze"; val7.m_items = (GameObject[])(object)new GameObject[4] { ZNetScene.instance.GetPrefab("ArmorBronzeChest"), ZNetScene.instance.GetPrefab("ArmorBronzeLegs"), ZNetScene.instance.GetPrefab("ShieldBronzeBuckler"), ZNetScene.instance.GetPrefab("KnifeCopper") }; array[1] = val7; ((Humanoid)human).m_randomSets = (ItemSet[])(object)array; ((Humanoid)human).m_randomItems = ((Humanoid)val).m_randomItems; ((Humanoid)human).m_unarmedWeapon = ((Humanoid)val).m_unarmedWeapon; ((Humanoid)human).m_pickupEffects = val.m_autopickupEffects; ((Humanoid)human).m_dropEffects = ((Humanoid)val).m_dropEffects; ((Humanoid)human).m_consumeItemEffects = ((Humanoid)val).m_consumeItemEffects; ((Humanoid)human).m_equipEffects = val.m_equipStartEffects; ((Humanoid)human).m_perfectBlockEffect = ((Humanoid)val).m_perfectBlockEffect; MonsterAI val8 = val2.AddComponent<MonsterAI>(); ((BaseAI)val8).m_viewRange = 30f; ((BaseAI)val8).m_viewAngle = 90f; ((BaseAI)val8).m_hearRange = 9999f; ((BaseAI)val8).m_idleSoundInterval = 10f; ((BaseAI)val8).m_idleSoundChance = 0f; ((BaseAI)val8).m_pathAgentType = (AgentType)1; ((BaseAI)val8).m_moveMinAngle = 90f; ((BaseAI)val8).m_smoothMovement = true; ((BaseAI)val8).m_jumpInterval = 10f; ((BaseAI)val8).m_randomCircleInterval = 2f; ((BaseAI)val8).m_randomMoveInterval = 30f; ((BaseAI)val8).m_randomMoveRange = 3f; val8.m_alertRange = 20f; val8.m_circulateWhileCharging = true; val8.m_privateAreaTriggerTreshold = 4; val8.m_interceptTimeMax = 2f; val8.m_maxChaseDistance = 300f; val8.m_circleTargetInterval = 8f; val8.m_circleTargetDuration = 6f; val8.m_circleTargetDistance = 8f; val8.m_consumeRange = 2f; val8.m_consumeSearchRange = 5f; val8.m_consumeSearchInterval = 10f; val8.m_consumeItems = new List<ItemDrop>(); CharacterDrop val9 = val2.AddComponent<CharacterDrop>(); val9.m_drops = new List<Drop> { new Drop { m_prefab = ZNetScene.instance.GetPrefab("Coins"), m_amountMin = 1, m_amountMax = 10, m_chance = 0.25f, m_levelMultiplier = true } }; GameObject prefab2 = ZNetScene.instance.GetPrefab("Boar"); Tameable val10 = default(Tameable); if (prefab2.TryGetComponent<Tameable>(ref val10)) { Tameable val11 = val2.AddComponent<Tameable>(); val11.m_fedDuration = 600f; val11.m_tamingTime = 1800f; val11.m_commandable = true; val11.m_tamedEffect = val10.m_tamedEffect; val11.m_sootheEffect = val10.m_sootheEffect; val11.m_petEffect = val10.m_petEffect; val11.m_commandable = true; val11.m_unsummonDistance = 0f; val11.m_randomStartingName = new List<string>(); } val2.AddComponent<Visuals>(); Helpers.RegisterToZNetScene(val2); } } } public static class Initialization { [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPriority(0)] private static class ObjectDB_Awake_Patch { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void Postfix(ObjectDB __instance) { if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)ZNetScene.instance)) { HumanMan.Create(); CloneAll(); UpdateAll(); SpawnMan.UpdateSpawnData(); } } } public static void ReadLocalFiles() { if (!Directory.Exists(CreatureManager.m_folderPath)) { Directory.CreateDirectory(CreatureManager.m_folderPath); } CreatureManager.Import(); if (!Directory.Exists(CreatureManager.m_creatureFolderPath)) { Directory.CreateDirectory(CreatureManager.m_creatureFolderPath); } string[] directories = Directory.GetDirectories(CreatureManager.m_creatureFolderPath); int num = 0; string[] array = directories; foreach (string text in array) { string text2 = text.Replace(CreatureManager.m_creatureFolderPath, string.Empty); char directorySeparatorChar = Path.DirectorySeparatorChar; string creatureName = text2.Replace(directorySeparatorChar.ToString(), string.Empty); CreatureManager.Read(creatureName); num++; } MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Registered {num} creature directories"); num = 0; if (!Directory.Exists(CreatureManager.m_cloneFolderPath)) { Directory.CreateDirectory(CreatureManager.m_cloneFolderPath); } string[] directories2 = Directory.GetDirectories(CreatureManager.m_cloneFolderPath); string[] array2 = directories2; foreach (string text3 in array2) { string text4 = text3.Replace(CreatureManager.m_cloneFolderPath, string.Empty); char directorySeparatorChar = Path.DirectorySeparatorChar; string creatureName2 = text4.Replace(directorySeparatorChar.ToString(), string.Empty); CreatureManager.Read(creatureName2, isClone: true); num++; } MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Registered {num} cloned creature directories"); } public static void ResetAll() { int num = 0; foreach (KeyValuePair<string, CreatureData> datum in CreatureManager.m_data) { GameObject val = DataBase.TryGetGameObject(datum.Value.m_characterData.PrefabName); if (!((Object)(object)val == (Object)null)) { CreatureManager.Reset(val); num++; } } MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Reset {num} creature data"); } public static void RemoveAll() { int num = 0; foreach (KeyValuePair<string, GameObject> clone in CreatureManager.m_clones) { CreatureManager.Delete(clone.Value); num++; } CreatureManager.m_clones.Clear(); MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Removed {num} clones"); } public static void CloneAll() { int num = 0; foreach (KeyValuePair<string, CreatureData> datum in CreatureManager.m_data) { CloneAllItems(datum.Value); string clonedFrom = datum.Value.m_characterData.ClonedFrom; if (!Utility.IsNullOrWhiteSpace(clonedFrom)) { GameObject val = DataBase.TryGetGameObject(clonedFrom); if (!((Object)(object)val == (Object)null)) { string prefabName = datum.Value.m_characterData.PrefabName; CreatureManager.Clone(val, prefabName, saveToDisk: false); num++; } } } MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Cloned {num} creatures"); } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void CloneAllItems(CreatureData data) { CloneItems(data.m_defaultItems); CloneItems(data.m_randomWeapons); CloneItems(data.m_randomShields); CloneItems(data.m_randomArmors); foreach (RandomItemSetsData randomSet in data.m_randomSets) { CloneItems(randomSet.m_items); } } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void CloneItems(List<ItemAttackData> data) { foreach (ItemAttackData datum in data) { if (!Utility.IsNullOrWhiteSpace(datum.m_attackData.OriginalPrefab)) { GameObject val = DataBase.TryGetGameObject(datum.m_attackData.OriginalPrefab); if (!((Object)(object)val == (Object)null)) { ItemDataMethods.Clone(val, datum.m_attackData.Name, write: false); } } } } public static void UpdateAll() { if (!Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return; } int num = 0; foreach (KeyValuePair<string, CreatureData> datum in CreatureManager.m_data) { GameObject val = DataBase.TryGetGameObject(datum.Value.m_characterData.PrefabName); if (!((Object)(object)val == (Object)null)) { CreatureManager.Update(val); num++; } } MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Updated {num} creatures"); } } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public static class SpawnMan { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] [HarmonyPatch(typeof(SpawnSystem), "Awake")] private static class SpawnSystem_Awake_Patch { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static void Postfix(SpawnSystem __instance) { if (Object.op_Implicit((Object)(object)__instance) && !__instance.m_spawnLists.Contains(m_spawnSystemList)) { __instance.m_spawnLists.Add(m_spawnSystemList); } } } [HarmonyPatch(typeof(ZNet), "Awake")] [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] private static class ZNet_Awake_Patch { private static void Postfix() { UpdateServerFiles(); } } [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] private class CreatureSpawnData { public string m_name = ""; public bool m_enabled = false; public bool m_devDisabled; public string m_prefab = null; public string m_biome = null; public string m_biomeArea = "Everything"; public int m_maxSpawned = 1; public float m_spawnInterval = 4f; public float m_spawnChance = 100f; public float m_spawnDistance = 10f; public float m_spawnRadiusMin; public float m_spawnRadiusMax; public string m_requiredGlobalKey = ""; public List<string> m_requiredEnvironments = new List<string>(); public int m_groupSizeMin = 1; public int m_groupSizeMax = 1; public float m_groupRadius = 3f; public bool m_spawnAtNight = true; public bool m_spawnAtDay = true; public float m_minAltitude = -1000f; public float m_maxAltitude = 1000f; public float m_minTilt; public float m_maxTilt = 35f; public bool m_inForest = true; public bool m_outsideForest = true; public bool m_inLava; public bool m_outsideLava = true; public bool m_canSpawnCloseToPlayer; public bool m_insidePlayerBase; public float m_minOceanDepth; public float m_maxOceanDepth; public bool m_huntPlayer; public float m_groundOffset = 0.5f; public float m_groundOffsetRandom; public int m_maxLevel = 1; public int m_minLevel = 1; public float m_levelUpMinCenterDistance; public float m_overrideLevelupChance = -1f; public bool m_foldout; } private static readonly CustomSyncedValue<string> ServerSpawnSystem = new CustomSyncedValue<string>(MonsterDBPlugin.ConfigSync, "MonsterDB_SpawnSystemData", ""); private static readonly string m_spawnFolderPath; private static readonly string m_referenceFolderPath; private static SpawnSystemList m_spawnSystemList; private static Dictionary<string, CreatureSpawnData> m_spawnData; public static void Setup() { m_spawnSystemList = MonsterDBPlugin.m_root.AddComponent<SpawnSystemList>(); ReadSpawnFiles(); string spawnFolderPath = m_spawnFolderPath; char directorySeparatorChar = Path.DirectorySeparatorChar; string path = spawnFolderPath + directorySeparatorChar + "Example.yml"; if (!File.Exists(path)) { CreatureSpawnData graph = new CreatureSpawnData(); ISerializer serializer = new SerializerBuilder().Build(); string contents = serializer.Serialize(graph); File.WriteAllText(path, contents); } ServerSpawnSystem.ValueChanged += delegate { if (Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer()) { UpdateSpawnData(); } }; SetupFileWatch(); } private static void SetupFileWatch() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(m_spawnFolderPath, "*.yml") { EnableRaisingEvents = true, IncludeSubdirectories = false, SynchronizingObject = ThreadingHelper.SynchronizingObject, NotifyFilter = NotifyFilters.LastWrite }; fileSystemWatcher.Created += OnSpawnChange; fileSystemWatcher.Deleted += OnSpawnChange; fileSystemWatcher.Changed += OnSpawnChange; } private static void OnSpawnChange(object sender, FileSystemEventArgs e) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { string fileName = Path.GetFileName(e.Name); if (!(fileName == "Example.yml")) { MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Spawn files changed"); ClearSpawnData(); ReadSpawnFiles(); } } } private static void ReadFile(string filePath) { try { IDeserializer deserializer = new DeserializerBuilder().Build(); string input = File.ReadAllText(filePath); CreatureSpawnData creatureSpawnData = deserializer.Deserialize<CreatureSpawnData>(input); m_spawnData[creatureSpawnData.m_name] = creatureSpawnData; UpdateSpawnList(); UpdateServerFiles(); } catch { Helpers.LogParseFailure(filePath); } } private static void ReadSpawnFiles() { if (!Directory.Exists(m_spawnFolderPath)) { Directory.CreateDirectory(m_spawnFolderPath); } string[] files = Directory.GetFiles(m_spawnFolderPath, "*.yml"); IDeserializer deserializer = new DeserializerBuilder().Build(); int num = 0; string[] array = files; foreach (string text in array) { if (!text.EndsWith("Example.yml")) { string input = File.ReadAllText(text); try { CreatureSpawnData creatureSpawnData = deserializer.Deserialize<CreatureSpawnData>(input); m_spawnData[creatureSpawnData.m_name] = creatureSpawnData; num++; } catch { Helpers.LogParseFailure(text); } } } MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Registered {num} spawn files"); } public static void UpdateSpawnData() { if (Utility.IsNullOrWhiteSpace(ServerSpawnSystem.Value)) { return; } try { IDeserializer deserializer = new DeserializerBuilder().Build(); Dictionary<string, CreatureSpawnData> dictionary = deserializer.Deserialize<Dictionary<string, CreatureSpawnData>>(ServerSpawnSystem.Value); ClearSpawnData(); AddSpawnData(dictionary); UpdateSpawnList(); MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Loaded {dictionary.Count} spawn files"); } catch { MonsterDBPlugin.MonsterDBLogger.LogDebug((object)"Failed to parse server spawn files"); } } private static void ClearSpawnData() { m_spawnData.Clear(); } private static void AddSpawnData(Dictionary<string, CreatureSpawnData> data) { m_spawnData = data; } private static void UpdateSpawnList() { m_spawnSystemList.m_spawners = (from info in m_spawnData.Values.Select(FormatSpawnData) where info != null select info).ToList(); } public static bool Write(GameObject critter) { if (!Directory.Exists(m_spawnFolderPath)) { Directory.CreateDirectory(m_spawnFolderPath); } if (!Directory.Exists(m_referenceFolderPath)) { Directory.CreateDirectory(m_referenceFolderPath); } CreatureSpawnData creatureSpawnData = new CreatureSpawnData(); foreach (SpawnSystemList item in SpawnSystem.m_instances.SelectMany([<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] (SpawnSystem instance) => instance.m_spawnLists)) { using IEnumerator<SpawnData> enumerator2 = item.m_spawners.Where([<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(0)] (SpawnData stream) => (Object)(object)stream.m_prefab == (Object)(object)critter).GetEnumerator(); if (enumerator2.MoveNext()) { SpawnData current2 = enumerator2.Current; creatureSpawnData.m_name = current2.m_name; creatureSpawnData.m_enabled = current2.m_enabled; creatureSpawnData.m_prefab = ((Object)current2.m_prefab).name; creatureSpawnData.m_biome = ((object)(Biome)(ref current2.m_biome)).ToString(); creatureSpawnData.m_biomeArea = ((object)(BiomeArea)(ref current2.m_biomeArea)).ToString(); creatureSpawnData.m_maxSpawned = current2.m_maxSpawned; creatureSpawnData.m_spawnInterval = current2.m_spawnInterval; creatureSpawnData.m_spawnChance = current2.m_spawnChance; creatureSpawnData.m_spawnDistance = current2.m_spawnDistance; creatureSpawnData.m_spawnRadiusMin = current2.m_spawnRadiusMin; creatureSpawnData.m_spawnRadiusMax = current2.m_spawnRadiusMax; creatureSpawnData.m_requiredGlobalKey = current2.m_requiredGlobalKey; creatureSpawnData.m_requiredEnvironments = current2.m_requiredEnvironments; creatureSpawnData.m_groupSizeMin = current2.m_groupSizeMin; creatureSpawnData.m_groupSizeMax = current2.m_groupSizeMax; creatureSpawnData.m_groupRadius = current2.m_groupRadius; creatureSpawnData.m_spawnAtNight = current2.m_spawnAtNight; creatureSpawnData.m_spawnAtDay = current2.m_spawnAtDay; creatureSpawnData.m_minAltitude = current2.m_minAltitude; creatureSpawnData.m_maxAltitude = current2.m_maxAltitude; creatureSpawnData.m_minTilt = current2.m_minTilt; creatureSpawnData.m_maxTilt = current2.m_maxTilt; creatureSpawnData.m_inForest = current2.m_inForest; creatureSpawnData.m_outsideForest = current2.m_outsideForest; creatureSpawnData.m_inLava = current2.m_inLava; creatureSpawnData.m_outsideLava = current2.m_outsideLava; creatureSpawnData.m_canSpawnCloseToPlayer = current2.m_canSpawnCloseToPlayer; creatureSpawnData.m_insidePlayerBase = current2.m_insidePlayerBase; creatureSpawnData.m_minOceanDepth = current2.m_minOceanDepth; creatureSpawnData.m_maxOceanDepth = current2.m_maxOceanDepth; creatureSpawnData.m_huntPlayer = current2.m_huntPlayer; creatureSpawnData.m_groundOffset = current2.m_groundOffset; creatureSpawnData.m_groundOffsetRandom = current2.m_groundOffsetRandom; creatureSpawnData.m_maxLevel = current2.m_maxLevel; creatureSpawnData.m_minLevel = current2.m_minLevel; creatureSpawnData.m_levelUpMinCenterDistance = current2.m_levelUpMinCenterDistance; creatureSpawnData.m_overrideLevelupChance = current2.m_overrideLevelupChance; creatureSpawnData.m_foldout = current2.m_foldout; } } if (Utility.IsNullOrWhiteSpace(creatureSpawnData.m_prefab)) { return false; } string text = creatureSpawnData.m_prefab + ".yml"; string referenceFolderPath = m_referenceFolderPath; char directorySeparatorChar = Path.DirectorySeparatorChar; string path = referenceFolderPath + directorySeparatorChar + text; ISerializer serializer = new SerializerBuilder().Build(); string contents = serializer.Serialize(creatureSpawnData); File.WriteAllText(path, contents); return true; } [return: <2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(2)] private static SpawnData FormatSpawnData(CreatureSpawnData input) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown if (Utility.IsNullOrWhiteSpace(input.m_name)) { return null; } GameObject val = DataBase.TryGetGameObject(input.m_prefab); if ((Object)(object)val == (Object)null) { return null; } if (!Enum.TryParse<Biome>(input.m_biome, out Biome result)) { return null; } if (!Enum.TryParse<BiomeArea>(input.m_biomeArea, out BiomeArea result2)) { return null; } return new SpawnData { m_name = input.m_name, m_enabled = input.m_enabled, m_devDisabled = input.m_devDisabled, m_prefab = val, m_biome = result, m_biomeArea = result2, m_maxSpawned = input.m_maxSpawned, m_spawnInterval = input.m_spawnInterval, m_spawnChance = input.m_spawnChance, m_spawnDistance = input.m_spawnDistance, m_spawnRadiusMin = input.m_spawnRadiusMin, m_spawnRadiusMax = input.m_spawnRadiusMax, m_requiredGlobalKey = input.m_requiredGlobalKey, m_requiredEnvironments = input.m_requiredEnvironments, m_groupSizeMin = input.m_groupSizeMin, m_groupSizeMax = input.m_groupSizeMax, m_groupRadius = input.m_groupRadius, m_spawnAtNight = input.m_spawnAtNight, m_spawnAtDay = input.m_spawnAtDay, m_minAltitude = input.m_minAltitude, m_maxAltitude = input.m_maxAltitude, m_minTilt = input.m_minTilt, m_maxTilt = input.m_maxTilt, m_inForest = input.m_inForest, m_outsideForest = input.m_outsideForest, m_inLava = input.m_inLava, m_outsideLava = input.m_outsideLava, m_canSpawnCloseToPlayer = input.m_canSpawnCloseToPlayer, m_insidePlayerBase = input.m_insidePlayerBase, m_minOceanDepth = input.m_minOceanDepth, m_maxOceanDepth = input.m_maxOceanDepth, m_huntPlayer = input.m_huntPlayer, m_groundOffset = input.m_groundOffset, m_groundOffsetRandom = input.m_groundOffsetRandom, m_maxLevel = input.m_maxLevel, m_minLevel = input.m_minLevel, m_levelUpMinCenterDistance = input.m_levelUpMinCenterDistance, m_overrideLevelupChance = input.m_overrideLevelupChance, m_foldout = input.m_foldout }; } private static void UpdateServerFiles() { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { ISerializer serializer = new SerializerBuilder().Build(); string value = serializer.Serialize(m_spawnData); ServerSpawnSystem.Value = value; } } static SpawnMan() { string folderPath = CreatureManager.m_folderPath; char directorySeparatorChar = Path.DirectorySeparatorChar; m_spawnFolderPath = folderPath + directorySeparatorChar + "SpawnData"; string spawnFolderPath = m_spawnFolderPath; directorySeparatorChar = Path.DirectorySeparatorChar; m_referenceFolderPath = spawnFolderPath + directorySeparatorChar + "References"; m_spawnSystemList = null; m_spawnData = new Dictionary<string, CreatureSpawnData>(); } } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public static class TextureManager { public static readonly string m_texturePath; public static readonly Dictionary<string, Texture2D> m_customTextures; private static readonly Dictionary<string, byte[]> m_textureBytes; public static void ReadLocalTextures() { if (!Directory.Exists(CreatureManager.m_folderPath)) { Directory.CreateDirectory(CreatureManager.m_folderPath); } if (!Directory.Exists(m_texturePath)) { Directory.CreateDirectory(m_texturePath); } string[] files = Directory.GetFiles(m_texturePath, "*.png"); int num = 0; string[] array = files; foreach (string filePath in array) { RegisterTexture(filePath); num++; } MonsterDBPlugin.MonsterDBLogger.LogDebug((object)$"Registered {num} textures"); } private static Texture2D LoadTexture(string name, byte[] data) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, data); ((Object)val).name = name; return val; } private static void RegisterTexture(string filePath) { byte[] data = File.ReadAllBytes(filePath); string name = Path.GetFileName(filePath).Replace(".png", string.Empty).Trim(); Texture2D val = LoadTexture(name, data); m_customTextures[((Object)val).name] = val; MonsterDBPlugin.MonsterDBLogger.LogDebug((object)("Registered texture: " + ((Object)val).name)); } private static Texture2D ReadBytes(string name, byte[] data) { Texture2D val = LoadTexture(name, data); m_customTextures[((Object)val).name] = val; m_textureBytes[((Object)val).name] = data; return val; } static TextureManager() { string folderPath = CreatureManager.m_folderPath; char directorySeparatorChar = Path.DirectorySeparatorChar; m_texturePath = folderPath + directorySeparatorChar + "CustomTextures"; m_customTextures = new Dictionary<string, Texture2D>(); m_textureBytes = new Dictionary<string, byte[]>(); } } public static class Tutorial { public static void Write() { string folderPath = CreatureManager.m_folderPath; char directorySeparatorChar = Path.DirectorySeparatorChar; string path = folderPath + directorySeparatorChar + "README.md"; if (!File.Exists(path)) { TextAsset text = GetText("Tutorial.md"); File.WriteAllText(path, text.text); } } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] private static TextAsset GetText(string fileName) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(fileName)); using Stream stream = executingAssembly.GetManifestResourceStream(name); if (stream == null) { return new TextAsset(); } using StreamReader streamReader = new StreamReader(stream); string text = streamReader.ReadToEnd(); return new TextAsset(text); } } } namespace MonsterDB.Solution.Methods { [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public static class AnimalAIMethods { public static void Save(GameObject critter, ref CreatureData creatureData) { AnimalAI val = default(AnimalAI); if (critter.TryGetComponent<AnimalAI>(ref val)) { creatureData.m_animalAIData = RecordAIData(val); Helpers.SaveEffectList(((BaseAI)val).m_alertedEffects, ref creatureData.m_effects.m_alertedEffects); Helpers.SaveEffectList(((BaseAI)val).m_idleSound, ref creatureData.m_effects.m_idleSounds); } } public static void Write(GameObject critter, string folderPath) { AnimalAI val = default(AnimalAI); if (critter.TryGetComponent<AnimalAI>(ref val)) { AnimalAIData graph = RecordAIData(val); char directorySeparatorChar = Path.DirectorySeparatorChar; string path = folderPath + directorySeparatorChar + "AnimalAI.yml"; ISerializer serializer = new SerializerBuilder().Build(); string contents = serializer.Serialize(graph); File.WriteAllText(path, contents); directorySeparatorChar = Path.DirectorySeparatorChar; string text = folderPath + directorySeparatorChar + "Effects"; if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } directorySeparatorChar = Path.DirectorySeparatorChar; string filePath = text + directorySeparatorChar + "AlertedEffects.yml"; directorySeparatorChar = Path.DirectorySeparatorChar; string filePath2 = text + directorySeparatorChar + "IdleSounds.yml"; Helpers.WriteEffectList(((BaseAI)val).m_alertedEffects, filePath); Helpers.WriteEffectList(((BaseAI)val).m_idleSound, filePath2); } } private static AnimalAIData RecordAIData(AnimalAI component) { return new AnimalAIData { ViewRange = ((BaseAI)component).m_viewRange, ViewAngle = ((BaseAI)component).m_viewAngle, HearRange = ((BaseAI)component).m_hearRange, MistVision = ((BaseAI)component).m_mistVision, IdleSoundInterval = ((BaseAI)component).m_idleSoundInterval, IdleSoundChance = ((BaseAI)component).m_idleSoundChance, PathAgentType = ((object)(AgentType)(ref ((BaseAI)component).m_pathAgentType)).ToString(), MoveMinAngle = ((BaseAI)component).m_moveMinAngle, SmoothMovement = ((BaseAI)component).m_smoothMovement, SerpentMovement = ((BaseAI)component).m_serpentMovement, SerpentTurnRadius = ((BaseAI)component).m_serpentTurnRadius, JumpInterval = ((BaseAI)component).m_jumpInterval, RandomCircleInterval = ((BaseAI)component).m_randomCircleInterval, RandomMoveInterval = ((BaseAI)component).m_randomMoveInterval, RandomMoveRange = ((BaseAI)component).m_randomMoveRange, RandomFly = ((BaseAI)component).m_randomFly, ChanceToTakeOff = ((BaseAI)component).m_chanceToTakeoff, ChanceToLand = ((BaseAI)component).m_chanceToLand, GroundDuration = ((BaseAI)component).m_groundDuration, AirDuration = ((BaseAI)component).m_airDuration, MaxLandAltitude = ((BaseAI)component).m_maxLandAltitude, TakeoffTime = ((BaseAI)component).m_takeoffTime, FlyAltitudeMin = ((BaseAI)component).m_flyAltitudeMin, FlyAltitudeMax = ((BaseAI)component).m_flyAltitudeMax, FlyAbsMinAltitude = ((BaseAI)component).m_flyAbsMinAltitude, AvoidFire = ((BaseAI)component).m_avoidFire, AfraidOfFire = ((BaseAI)component).m_afraidOfFire, AvoidWater = ((BaseAI)component).m_avoidWater, AvoidLava = ((BaseAI)component).m_avoidLava, SkipLavaTargets = ((BaseAI)component).m_skipLavaTargets, Aggravatable = ((BaseAI)component).m_aggravatable, PassiveAggressive = ((BaseAI)component).m_passiveAggresive, SpawnMessage = ((BaseAI)component).m_spawnMessage, DeathMessage = ((BaseAI)component).m_deathMessage, AlertedMessage = ((BaseAI)component).m_alertedMessage, FleeRange = ((BaseAI)component).m_fleeRange, FleeAngle = ((BaseAI)component).m_fleeAngle, FleeInterval = ((BaseAI)component).m_fleeInterval }; } public static void Read(string folderPath, ref CreatureData creatureData) { char directorySeparatorChar = Path.DirectorySeparatorChar; string text = folderPath + directorySeparatorChar + "AnimalAI.yml"; if (!File.Exists(text)) { return; } string text2 = File.ReadAllText(text); if (Utility.IsNullOrWhiteSpace(text2)) { return; } IDeserializer deserializer = new DeserializerBuilder().Build(); try { AnimalAIData animalAIData = deserializer.Deserialize<AnimalAIData>(text2); creatureData.m_animalAIData = animalAIData; directorySeparatorChar = Path.DirectorySeparatorChar; string text3 = folderPath + directorySeparatorChar + "Effects"; if (Directory.Exists(text3)) { directorySeparatorChar = Path.DirectorySeparatorChar; string filePath = text3 + directorySeparatorChar + "AlertedEffects.yml"; directorySeparatorChar = Path.DirectorySeparatorChar; string filePath2 = text3 + directorySeparatorChar + "IdleSounds.yml"; Helpers.ReadEffectInfo(filePath, ref creatureData.m_effects.m_alertedEffects); Helpers.ReadEffectInfo(filePath2, ref creatureData.m_effects.m_idleSounds); } } catch { Helpers.LogParseFailure(text); } } public static void Update(GameObject critter, CreatureData creatureData) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) AnimalAIData animalAIData = creatureData.m_animalAIData; Vector3 scale = Helpers.GetScale(creatureData.m_scale); CharacterEffects effects = creatureData.m_effects; AnimalAI val = default(AnimalAI); if (critter.TryGetComponent<AnimalAI>(ref val)) { ((BaseAI)val).m_viewRange = animalAIData.ViewRange; ((BaseAI)val).m_viewAngle = animalAIData.ViewAngle; ((BaseAI)val).m_hearRange = animalAIData.HearRange; ((BaseAI)val).m_mistVision = animalAIData.MistVision; ((BaseAI)val).m_idleSoundInterval = animalAIData.IdleSoundInterval; ((BaseAI)val).m_idleSoundChance = animalAIData.IdleSoundChance; if (!Enum.TryParse<AgentType>(animalAIData.PathAgentType, ignoreCase: true, out AgentType result)) { ((BaseAI)val).m_pathAgentType = result; } ((BaseAI)val).m_moveMinAngle = animalAIData.MoveMinAngle; ((BaseAI)val).m_smoothMovement = animalAIData.SmoothMovement; ((BaseAI)val).m_serpentMovement = animalAIData.SerpentMovement; ((BaseAI)val).m_serpentTurnRadius = animalAIData.SerpentTurnRadius; ((BaseAI)val).m_jumpInterval = animalAIData.JumpInterval; ((BaseAI)val).m_randomCircleInterval = animalAIData.RandomCircleInterval; ((BaseAI)val).m_randomMoveInterval = animalAIData.RandomMoveInterval; ((BaseAI)val).m_randomMoveRange = animalAIData.RandomMoveRange; ((BaseAI)val).m_randomFly = animalAIData.RandomFly; ((BaseAI)val).m_chanceToTakeoff = animalAIData.ChanceToTakeOff; ((BaseAI)val).m_chanceToLand = animalAIData.ChanceToLand; ((BaseAI)val).m_groundDuration = animalAIData.GroundDuration; ((BaseAI)val).m_airDuration = animalAIData.AirDuration; ((BaseAI)val).m_maxLandAltitude = animalAIData.MaxLandAltitude; ((BaseAI)val).m_takeoffTime = animalAIData.TakeoffTime; ((BaseAI)val).m_flyAltitudeMin = animalAIData.FlyAltitudeMin; ((BaseAI)val).m_flyAltitudeMax = animalAIData.FlyAltitudeMax; ((BaseAI)val).m_flyAbsMinAltitude = animalAIData.FlyAbsMinAltitude; ((BaseAI)val).m_avoidFire = animalAIData.AvoidFire; ((BaseAI)val).m_afraidOfFire = animalAIData.AfraidOfFire; ((BaseAI)val).m_avoidWater = animalAIData.AvoidWater; ((BaseAI)val).m_avoidLava = animalAIData.AvoidLava; ((BaseAI)val).m_skipLavaTargets = animalAIData.SkipLavaTargets; ((BaseAI)val).m_aggravatable = animalAIData.Aggravatable; ((BaseAI)val).m_passiveAggresive = animalAIData.PassiveAggressive; ((BaseAI)val).m_spawnMessage = animalAIData.SpawnMessage; ((BaseAI)val).m_deathMessage = animalAIData.DeathMessage; ((BaseAI)val).m_alertedMessage = animalAIData.AlertedMessage; ((BaseAI)val).m_fleeRange = animalAIData.FleeRange; ((BaseAI)val).m_fleeAngle = animalAIData.FleeAngle; ((BaseAI)val).m_fleeInterval = animalAIData.FleeInterval; Helpers.UpdateEffectList(effects.m_alertedEffects, ref ((BaseAI)val).m_alertedEffects, scale); Helpers.UpdateEffectList(effects.m_idleSounds, ref ((BaseAI)val).m_alertedEffects, scale); } } } [<62d83a6a-fefa-47f1-b57d-a3d24ac11b92>NullableContext(1)] [<2f40b76b-2716-41a7-ab0b-f9a69626cdb6>Nullable(0)] public static class CharacterMethods { public static void Save(GameObject critter, string clonedFrom, ref CreatureData creatureData) { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) Character val = default(Character); if (!critter.TryGetComponent<Character>(ref val)) { return; } creatureData.m_characterData = RecordCharacterData(val, clonedFrom, critter); Helpers.SaveEffectList(val.m_hitEffects, ref creatureData.m_effects.m_hitEffects); Helpers.SaveEffectList(val.m_critHitEffects, ref creatureData.m_effects.m_critHitEffects); Helpers.SaveEffectList(val.m_backstabHitEffects, ref creatureData.m_effects.m_backstabHitEffects); Helpers.SaveEffectList(val.m_deathEffects, ref creatureData.m_effects.m_deathEffects); Helpers.SaveEffectList(val.m_waterEffects, ref creatureData.m_effects.m_waterEffects); Helpers.SaveEffectList(val.m_tarEffects, ref creatureData.m_effects.m_tarEffects); Helpers.SaveEffectList(val.m_slideEffects, ref creatureData.m_effects.m_slideEffects); Helpers.SaveEffectList(val.m_jumpEffects, ref creatureData.m_effects.m_jumpEffects); Helpers.SaveEffectList(val.m_flyingContinuousEffect, ref creatureData.m_effects.m_flyingContinuousEffects); if (val.m_deathEffects == null) { return; } EffectData[] effectPrefabs = val.m_deathEffects.m_effectPrefabs; foreach (EffectData val2 in effectPrefabs) { if (Object.op_Implicit((Object)(object)val2.m_prefab.GetComponent<Ragdoll>())) { Vector3 localScale = val2.m_prefab.transform.localScale; VisualMethods.ScaleData ragdollScale = new VisualMethods.ScaleData { x = localScale.x, y = localScale.y, z = localScale.z }; creatureData.m_ragdollScale = ragdollScale; } } } public static void Write(GameObject critter, string folderPath, string clonedFrom = "") { //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid I