The current BepInExPack is broken due to the Oakveil update, and mods installed through a mod manager may not work. Join the modding Discord for more information.
Decompiled source of Notify v3.0.10
BloodyNotify.dll
Decompiled 11 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using Bloodstone.API; using Bloody.Core; using Bloody.Core.API.v1; using Bloody.Core.GameData.v1; using Bloody.Core.Helper.v1; using Bloody.Core.Models.v1; using Bloody.Core.Models.v1.Base; using BloodyNotify.AutoAnnouncer; using BloodyNotify.AutoAnnouncer.Models; using BloodyNotify.AutoAnnouncer.Parser; using BloodyNotify.DB; using BloodyNotify.Systems; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using ProjectM; using ProjectM.Network; using Stunlock.Network; using Unity.Collections; using Unity.Entities; using VampireCommandFramework; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("BloodyNotify")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Add functionality to the server to have MOTD, Auto Announcer, when a user is online, when a user goes offline or when someone kills a VBlood in v rising.")] [assembly: AssemblyFileVersion("3.0.10.0")] [assembly: AssemblyInformationalVersion("3.0.10+1.Branch.master.Sha.ce2ad103a4f69831f7bc950d8ac7a303ae4bc750")] [assembly: AssemblyProduct("BloodyNotify")] [assembly: AssemblyTitle("BloodyNotify")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.10.0")] [module: UnverifiableCode] namespace BloodyNotify { [BepInPlugin("BloodyNotify", "BloodyNotify", "3.0.10")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [Reloadable] public class Plugin : BasePlugin, IRunOnInitialized { private Harmony _harmony; public static Logger Logger; public static SystemsCore SystemsCore; public static ConfigEntry<bool> AnnounceOnline; public static ConfigEntry<bool> AnnounceeOffline; public static ConfigEntry<bool> AnnounceNewUser; public static ConfigEntry<bool> AnnounceVBlood; public static ConfigEntry<string> VBloodFinalConcatCharacters; public static ConfigEntry<bool> AutoAnnouncerConfig; public static ConfigEntry<int> IntervalAutoAnnouncer; public static ConfigEntry<bool> MessageOfTheDay; public static readonly string ConfigPath = Path.Combine(Paths.ConfigPath, "BloodyNotify"); public override void Load() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown Logger = new Logger(((BasePlugin)this).Log); if (!Core.IsServer) { ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("BloodyNotify"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is only for server!"); } log.LogInfo(val); } else { _harmony = new Harmony("BloodyNotify"); CommandRegistry.RegisterAll(); EventsHandlerSystem.OnInitialize += new OnGameDataInitializedEventHandler(GameDataOnInitialize); InitConfig(); LoadDatabase.LoadAllConfig(); Logger.LogInfo("Plugin BloodyNotify version 3.0.10 is loaded!"); } } private void GameDataOnInitialize(World world) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown SystemsCore = Core.SystemsCore; Database.EnabledFeatures[NotifyFeature.online] = AnnounceOnline.Value; Database.EnabledFeatures[NotifyFeature.offline] = AnnounceeOffline.Value; Database.EnabledFeatures[NotifyFeature.newuser] = AnnounceNewUser.Value; Database.EnabledFeatures[NotifyFeature.vblood] = AnnounceVBlood.Value; Database.EnabledFeatures[NotifyFeature.auto] = AutoAnnouncerConfig.Value; Database.EnabledFeatures[NotifyFeature.motd] = MessageOfTheDay.Value; Database.setVBloodFinalConcatCharacters(VBloodFinalConcatCharacters.Value); Database.setIntervalAutoAnnouncer(IntervalAutoAnnouncer.Value); EventsHandlerSystem.OnUserConnected += new OnUserConnectedEventHandler(OnlineOfflineSystem.OnUserOnline); EventsHandlerSystem.OnUserDisconnected += new OnUserDisconnectedEventHandler(OnlineOfflineSystem.OnUserOffline); EventsHandlerSystem.OnDeathVBlood += new DeathVbloodEventHandler(KillVBloodSystem.OnDetahVblood); AutoAnnouncerFunction.StartAutoAnnouncer(); } private void InitConfig() { AnnounceOnline = ((BasePlugin)this).Config.Bind<bool>("UserOnline", "enabled", true, "Enable Announce when user online"); AnnounceeOffline = ((BasePlugin)this).Config.Bind<bool>("UserOffline", "enabled", true, "Enable Announce when user offline"); AnnounceNewUser = ((BasePlugin)this).Config.Bind<bool>("NewUserOnline", "enabled", true, "Enable Announce when new user create in server"); AnnounceVBlood = ((BasePlugin)this).Config.Bind<bool>("AnnounceVBlood", "enabled", true, "Enable Announce when user/users kill a VBlood Boss."); VBloodFinalConcatCharacters = ((BasePlugin)this).Config.Bind<string>("AnnounceVBlood", "VBloodFinalConcatCharacters", "and", "Final string for concat two or more players kill a VBlood Boss."); AutoAnnouncerConfig = ((BasePlugin)this).Config.Bind<bool>("AutoAnnouncer", "enabled", false, "Enable AutoAnnouncer."); IntervalAutoAnnouncer = ((BasePlugin)this).Config.Bind<int>("AutoAnnouncer", "interval", 300, "Interval seconds for spam AutoAnnouncer."); MessageOfTheDay = ((BasePlugin)this).Config.Bind<bool>("MessageOfTheDay", "enabled", false, "Enable Message Of The Day."); if (!Directory.Exists(ConfigPath)) { Directory.CreateDirectory(ConfigPath); } Config.CheckAndCreateConfigs(); } public void OnGameInitialized() { } public override bool Unload() { CommandRegistry.UnregisterAssembly(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } return true; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "BloodyNotify"; public const string PLUGIN_NAME = "BloodyNotify"; public const string PLUGIN_VERSION = "3.0.10"; } } namespace BloodyNotify.Systems { internal class KillVBloodSystem { private const double SendMessageDelay = 2.0; public static Dictionary<string, HashSet<string>> vbloodKills = new Dictionary<string, HashSet<string>>(); private static EntityManager _entityManager = Plugin.SystemsCore.EntityManager; private static PrefabCollectionSystem _prefabCollectionSystem = Plugin.SystemsCore.PrefabCollectionSystem; private static bool checkKiller = false; private static Dictionary<string, DateTime> lastKillerUpdate = new Dictionary<string, DateTime>(); public static void OnDetahVblood(VBloodSystem sender, NativeList<VBloodConsumed> deathEvents) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!Database.EnabledFeatures[NotifyFeature.vblood]) { return; } if (deathEvents.Length > 0) { Enumerator<VBloodConsumed> enumerator = deathEvents.GetEnumerator(); while (enumerator.MoveNext()) { VBloodConsumed current = enumerator.Current; if (((EntityManager)(ref _entityManager)).HasComponent<PlayerCharacter>(current.Target)) { PlayerCharacter componentData = ((EntityManager)(ref _entityManager)).GetComponentData<PlayerCharacter>(current.Target); User componentData2 = ((EntityManager)(ref _entityManager)).GetComponentData<User>(componentData.UserEntity); string text = _prefabCollectionSystem.PrefabGuidToNameDictionary[current.Source]; AddKiller(text.ToString(), ((object)(FixedString64Bytes)(ref componentData2.CharacterName)).ToString()); lastKillerUpdate[text.ToString()] = DateTime.Now; checkKiller = true; } } } else { if (!checkKiller) { return; } bool flag = false; foreach (KeyValuePair<string, DateTime> item in lastKillerUpdate) { DateTime value = item.Value; if (DateTime.Now - value < TimeSpan.FromSeconds(2.0)) { flag = true; } else { SendAnnouncementMessage(item.Key); } } checkKiller = flag; } } public static void AddKiller(string vblood, string killerCharacterName) { if (!vbloodKills.ContainsKey(vblood)) { vbloodKills[vblood] = new HashSet<string>(); } vbloodKills[vblood].Add(killerCharacterName); } public static void RemoveKillers(string vblood) { vbloodKills[vblood] = new HashSet<string>(); } public static List<string> GetKillers(string vblood) { return vbloodKills[vblood].ToList(); } public static void SendAnnouncementMessage(string vblood) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (checkifBloodyBoss(vblood)) { RemoveKillers(vblood); return; } string announcementMessage = GetAnnouncementMessage(vblood); if (announcementMessage == "ignore") { RemoveKillers(vblood); } else { if (announcementMessage == null) { return; } foreach (UserModel item in GameData.Users.Online) { if (!Database.getVBloodNotifyIgnore(item.CharacterName)) { ServerChatUtils.SendSystemMessageToClient(VWorld.Server.EntityManager, ((EntityModel)item).Internals.User.Value, announcementMessage); } } RemoveKillers(vblood); } } private static bool checkifBloodyBoss(string vblood) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) NativeArray<Entity> entitiesByComponentTypes = QueryComponents.GetEntitiesByComponentTypes<VBloodUnit, NameableInteractable, LifeTime>((EntityQueryOptions)0, false); Enumerator<Entity> enumerator = entitiesByComponentTypes.GetEnumerator(); while (enumerator.MoveNext()) { Entity current = enumerator.Current; try { NpcModel val = GameData.Npcs.FromEntity(current); if (!(_prefabCollectionSystem.PrefabGuidToNameDictionary[val.PrefabGUID] == vblood)) { continue; } NameableInteractable val2 = ECSExtensions.Read<NameableInteractable>(current); if (((FixedString64Bytes)(ref val2.Name)).Value.Contains("bb")) { if (ECSExtensions.Read<Health>(current).IsDead) { entitiesByComponentTypes.Dispose(); return true; } entitiesByComponentTypes.Dispose(); return false; } } catch { } } entitiesByComponentTypes.Dispose(); return false; } public static string GetAnnouncementMessage(string vblood) { List<string> killers = GetKillers(vblood); string prefabNameValue = Database.getPrefabNameValue(vblood); bool prefabIgnoreValue = Database.getPrefabIgnoreValue(vblood); StringBuilder stringBuilder = new StringBuilder(); if (prefabIgnoreValue) { return "ignore"; } if (killers.Count == 0) { return null; } if (killers.Count == 1) { stringBuilder.Append(FontColorChatSystem.Yellow(killers[0])); } if (killers.Count == 2) { StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 3, stringBuilder2); handler.AppendFormatted(FontColorChatSystem.Yellow(killers[0])); handler.AppendLiteral(" "); handler.AppendFormatted(Database.getVBloodFinalConcatCharacters()); handler.AppendLiteral(" "); handler.AppendFormatted(FontColorChatSystem.Yellow(killers[1])); stringBuilder3.Append(ref handler); } if (killers.Count > 2) { for (int i = 0; i < killers.Count; i++) { if (i == killers.Count - 1) { StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(1, 2, stringBuilder2); handler.AppendFormatted(Database.getVBloodFinalConcatCharacters()); handler.AppendLiteral(" "); handler.AppendFormatted(FontColorChatSystem.Yellow(killers[i])); stringBuilder4.Append(ref handler); } else { StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 1, stringBuilder2); handler.AppendFormatted(FontColorChatSystem.Yellow(killers[i])); handler.AppendLiteral(", "); stringBuilder5.Append(ref handler); } } } return FontColorChatSystem.Green(Database.getDefaultAnnounceValue("VBlood").Replace("#user#", $"{stringBuilder}").Replace("#vblood#", FontColorChatSystem.Red(prefabNameValue) ?? "") ?? ""); } } internal class OnlineOfflineSystem { private static EntityManager entityManager = Plugin.SystemsCore.EntityManager; internal static void OnUserOnline(ServerBootstrapSystem sender, NetConnectionId netConnectionId) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) int num = sender._NetEndPointToApprovedUserIndex[netConnectionId]; Entity userEntity = ((Il2CppArrayBase<ServerClient>)(object)sender._ApprovedUsersLookup)[num].UserEntity; UserModel val = GameData.Users.FromEntity(userEntity); bool num2 = IsNewUser(userEntity); string characterName = val.CharacterName; Plugin.Logger.LogInfo("ha conectado " + val.CharacterName + " "); if (!num2) { if (Database.EnabledFeatures[NotifyFeature.online]) { string userOnlineValue = Database.getUserOnlineValue(characterName); userOnlineValue = userOnlineValue.Replace("#user#", FontColorChatSystem.Yellow(characterName) ?? ""); ServerChatUtils.SendSystemMessageToAllClients(entityManager, FontColorChatSystem.Green(userOnlineValue ?? "")); } } else if (Database.EnabledFeatures[NotifyFeature.newuser]) { string userOnlineValue2 = Database.getUserOnlineValue(""); ServerChatUtils.SendSystemMessageToAllClients(entityManager, FontColorChatSystem.Green(userOnlineValue2 ?? "")); } if (!Database.EnabledFeatures[NotifyFeature.motd]) { return; } foreach (string item in Database.getMessageOfTheDay()) { string text = item.Replace("#user#", characterName ?? ""); ServerChatUtils.SendSystemMessageToClient(entityManager, ECSExtensions.Read<User>(userEntity), text); } } internal static void OnUserOffline(ServerBootstrapSystem sender, NetConnectionId netConnectionId, ConnectionStatusChangeReason connectionStatusReason, string extraData) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (Database.EnabledFeatures[NotifyFeature.offline] && (int)connectionStatusReason != 17) { int num = sender._NetEndPointToApprovedUserIndex[netConnectionId]; Entity userEntity = ((Il2CppArrayBase<ServerClient>)(object)sender._ApprovedUsersLookup)[num].UserEntity; string characterName = GameData.Users.FromEntity(userEntity).CharacterName; string userOfflineValue = Database.getUserOfflineValue(characterName); userOfflineValue = userOfflineValue.Replace("#user#", FontColorChatSystem.Yellow(characterName) ?? ""); ServerChatUtils.SendSystemMessageToAllClients(entityManager, userOfflineValue ?? ""); } } public static bool IsNewUser(Entity userEntity) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) User val = ECSExtensions.Read<User>(userEntity); return ((FixedString64Bytes)(ref val.CharacterName)).IsEmpty; } } } namespace BloodyNotify.DB { internal class Config { public static readonly string ConfigPath = Plugin.ConfigPath; public static string DefaultAutoAnnounceMessagesConfig = "[[\"Message 1 Line 1\",\"Message 1 Line 2\"],[\"Message 2 Line 1\",\"Message 2 Line 2\",\"Message 2 Line 3\",\"Message 2 Line 4\"]]"; public static Dictionary<string, string> DefaultAnnounceDictionary => new Dictionary<string, string> { { "online", "#user# is online!" }, { "offline", "#user# has gone offline!" }, { "newUser", "Welcome to server" }, { "VBlood", "Congratulations to #user# for beating #vblood#!" } }; public static Dictionary<string, string> PrefabToNamesDefault => new Dictionary<string, string> { { "CHAR_Bandit_Frostarrow_VBlood", "Keely the Frost Archer" }, { "CHAR_Bandit_Foreman_VBlood", "Rufus the Foreman" }, { "CHAR_Bandit_StoneBreaker_VBlood", "Errol the Stonebreaker" }, { "CHAR_Bandit_Chaosarrow_VBlood", "Lidia the Chaos Archer" }, { "CHAR_Undead_BishopOfDeath_VBlood", "Goreswine the Ravager" }, { "CHAR_Bandit_Stalker_VBlood", "Grayson the Armourer" }, { "CHAR_Vermin_DireRat_VBlood", "Putrid Rat" }, { "CHAR_Bandit_Bomber_VBlood", "Clive the Firestarter" }, { "CHAR_Undead_Priest_VBlood", "Nicholaus the Fallen" }, { "CHAR_Bandit_Tourok_VBlood", "Quincey the Bandit King" }, { "CHAR_Villager_Tailor_VBlood", "Beatrice the Tailor" }, { "CHAR_Militia_Guard_VBlood", "Vincent the Frostbringer" }, { "CHAR_VHunter_Leader_VBlood", "Tristan the Vampire Hunter" }, { "CHAR_Undead_BishopOfShadows_VBlood", "Leandra the Shadow Priestess" }, { "CHAR_Geomancer_Human_VBlood", "Terah the Geomancer" }, { "CHAR_Militia_Longbowman_LightArrow_Vblood", "Meredith the Bright Archer" }, { "CHAR_Wendigo_VBlood", "Frostmaw the Mountain Terror" }, { "CHAR_Militia_Leader_VBlood", "Octavian the Militia Captain" }, { "CHAR_Militia_BishopOfDunley_VBlood", "Raziel the Shepherd" }, { "CHAR_Spider_Queen_VBlood", "Ungora the Spider Queen" }, { "CHAR_Cursed_ToadKing_VBlood", "Albert the Duke of Balaton" }, { "CHAR_VHunter_Jade_VBlood", "Jade the Vampire Hunter" }, { "CHAR_Undead_ZealousCultist_VBlood", "Foulrot the Soultaker" }, { "CHAR_WerewolfChieftain_VBlood", "Willfred the Werewolf Chief" }, { "CHAR_ArchMage_VBlood", "Mairwyn the Elementalist" }, { "CHAR_Winter_Yeti_VBlood", "Terrorclaw the Ogre" }, { "CHAR_Harpy_Matriarch_VBlood", "Morian the Stormwing Matriarch" }, { "CHAR_Cursed_Witch_VBlood", "Matka the Curse Weaver" }, { "CHAR_BatVampire_VBlood", "Lord Styx the Night Champion" }, { "CHAR_Cursed_MountainBeast_VBlood", "Gorecrusher the Behemoth" }, { "CHAR_Manticore_VBlood", "Talzur the Winged Horror" }, { "CHAR_Bandit_GraveDigger_VBlood_UNUSED", "Boris the Gravedigger" }, { "CHAR_Bandit_Leader_VBlood_UNUSED", "Quincey the Marauder" }, { "CHAR_Bandit_Miner_VBlood_UNUSED", "Errol the Stonebreaker" }, { "CHAR_ChurchOfLight_Cardinal_VBlood", "Azariel the Sunbringer" }, { "CHAR_ChurchOfLight_Overseer_VBlood", "Sir Magnus the Overseer" }, { "CHAR_ChurchOfLight_Paladin_VBlood", "Solarus the Immaculate" }, { "CHAR_ChurchOfLight_Sommelier_VBlood", "Baron du Bouchon the Sommelier" }, { "CHAR_Forest_Bear_Dire_Vblood", "Kodia the Ferocious Bear" }, { "CHAR_Forest_Wolf_VBlood", "Alpha the White Wolf" }, { "CHAR_Gloomrot_Iva_VBlood", "Ziva the Engineer" }, { "CHAR_Gloomrot_Monster_VBlood", "Adam the Firstborn" }, { "CHAR_Gloomrot_Purifier_VBlood", "Angram the Purifier" }, { "CHAR_Gloomrot_RailgunSergeant_VBlood", "Voltatia the Power Master" }, { "CHAR_Gloomrot_TheProfessor_VBlood", "Henry Blackbrew the Doctor" }, { "CHAR_Gloomrot_Voltage_VBlood", "Domina the Blade Dancer" }, { "CHAR_Militia_Glassblower_VBlood", "Grethel the Glassblower" }, { "CHAR_Militia_Hound_VBlood", "Brutus the Watcher" }, { "CHAR_Militia_HoundMaster_VBlood", "Boyo" }, { "CHAR_Militia_Nun_VBlood", "Christina the Sun Priestess" }, { "CHAR_Militia_Scribe_VBlood", "Maja the Dark Savant" }, { "CHAR_Poloma_VBlood", "Polora the Feywalker" }, { "CHAR_Undead_CursedSmith_VBlood", "Cyril the Cursed Smith" }, { "CHAR_Undead_Infiltrator_VBlood", "Bane the Shadowblade" }, { "CHAR_Undead_Leader_Vblood", "Kriig the Undead General" }, { "CHAR_Villager_CursedWanderer_VBlood", "Ben the Old Wanderer" }, { "CHAR_Bandit_Fisherman_VBlood", "Finn the Fisherman" }, { "CHAR_VHunter_CastleMan", "Simon Belmont the Vampire Hunter" }, { "CHAR_Vampire_BloodKnight_VBlood", "General Valencia the Depraved" }, { "CHAR_Vampire_Dracula_VBlood", "Dracula the Immortal King" }, { "CHAR_Vampire_HighLord_VBlood", "General Cassius the Betrayer" }, { "CHAR_Vampire_IceRanger_VBlood", "General Elena the Hollow" }, { "NoPrefabName", "VBlood Boss" } }; public static Dictionary<string, bool> PrefabsIgnoreDefaul => new Dictionary<string, bool> { { "CHAR_Bandit_Frostarrow_VBlood", false }, { "CHAR_Bandit_Foreman_VBlood", false }, { "CHAR_Bandit_StoneBreaker_VBlood", false }, { "CHAR_Bandit_Chaosarrow_VBlood", false }, { "CHAR_Undead_BishopOfDeath_VBlood", false }, { "CHAR_Bandit_Stalker_VBlood", false }, { "CHAR_Vermin_DireRat_VBlood", false }, { "CHAR_Bandit_Bomber_VBlood", false }, { "CHAR_Undead_Priest_VBlood", false }, { "CHAR_Bandit_Tourok_VBlood", false }, { "CHAR_Villager_Tailor_VBlood", false }, { "CHAR_Militia_Guard_VBlood", false }, { "CHAR_VHunter_Leader_VBlood", false }, { "CHAR_Undead_BishopOfShadows_VBlood", false }, { "CHAR_Geomancer_Human_VBlood", false }, { "CHAR_Militia_Longbowman_LightArrow_Vblood", false }, { "CHAR_Wendigo_VBlood", false }, { "CHAR_Militia_Leader_VBlood", false }, { "CHAR_Militia_BishopOfDunley_VBlood", false }, { "CHAR_Spider_Queen_VBlood", false }, { "CHAR_Cursed_ToadKing_VBlood", false }, { "CHAR_VHunter_Jade_VBlood", false }, { "CHAR_Undead_ZealousCultist_VBlood", false }, { "CHAR_WerewolfChieftain_VBlood", false }, { "CHAR_ArchMage_VBlood", false }, { "CHAR_Winter_Yeti_VBlood", false }, { "CHAR_Harpy_Matriarch_VBlood", false }, { "CHAR_Cursed_Witch_VBlood", false }, { "CHAR_BatVampire_VBlood", false }, { "CHAR_Cursed_MountainBeast_VBlood", false }, { "CHAR_Manticore_VBlood", false }, { "CHAR_Paladin_VBlood", false }, { "CHAR_Bandit_GraveDigger_VBlood_UNUSED", false }, { "CHAR_Bandit_Leader_VBlood_UNUSED", false }, { "CHAR_Bandit_Miner_VBlood_UNUSED", false }, { "CHAR_ChurchOfLight_Cardinal_VBlood", false }, { "CHAR_ChurchOfLight_Overseer_VBlood", false }, { "CHAR_ChurchOfLight_Sommelier_VBlood", false }, { "CHAR_Forest_Bear_Dire_Vblood", false }, { "CHAR_Forest_Wolf_VBlood", false }, { "CHAR_Gloomrot_Iva_VBlood", false }, { "CHAR_Gloomrot_Monster_VBlood", false }, { "CHAR_Gloomrot_Purifier_VBlood", false }, { "CHAR_Gloomrot_RailgunSergeant_VBlood", false }, { "CHAR_Gloomrot_TheProfessor_VBlood", false }, { "CHAR_Gloomrot_Voltage_VBlood", false }, { "CHAR_Militia_Glassblower_VBlood", false }, { "CHAR_Militia_Hound_VBlood", false }, { "CHAR_Militia_HoundMaster_VBlood", false }, { "CHAR_Militia_Nun_VBlood", false }, { "CHAR_Militia_Scribe_VBlood", false }, { "CHAR_Poloma_VBlood", false }, { "CHAR_Undead_CursedSmith_VBlood", false }, { "CHAR_Undead_Infiltrator_VBlood", false }, { "CHAR_Undead_Leader_Vblood", false }, { "CHAR_Villager_CursedWanderer_VBlood", false }, { "CHAR_Bandit_Fisherman_VBlood", false }, { "CHAR_VHunter_CastleMan", false }, { "CHAR_Vampire_BloodKnight_VBlood", false }, { "CHAR_Vampire_Dracula_VBlood", false }, { "CHAR_Vampire_HighLord_VBlood", false }, { "CHAR_Vampire_IceRanger_VBlood", false }, { "NoPrefabName", false } }; public static Dictionary<string, string> DefaultOnline => new Dictionary<string, string> { { "nick", "#user# is online!" } }; public static Dictionary<string, string> DefaultOffline => new Dictionary<string, string> { { "nick", "#user# is ofline!" } }; public static Dictionary<string, bool> DefaultVBloodAnnounceIgnoreUsers => new Dictionary<string, bool> { { "nick", true } }; public static List<string> DefaultMessageOfTheDay => new List<string> { "#user# this is Message of the day Line 1", "Message of the day Line 2", "Message of the day Line 3" }; public static void CreateDefaultNotificationTextConfig() { string contents = JsonSerializer.Serialize(DefaultAnnounceDictionary, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(Path.Combine(ConfigPath, "default_announce.json"), contents); } public static void CreateOnlineDefaultConfig() { string contents = JsonSerializer.Serialize(DefaultOnline, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(Path.Combine(ConfigPath, "users_online.json"), contents); } public static void CreateOfflineDefaultConfig() { string contents = JsonSerializer.Serialize(DefaultOffline, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(Path.Combine(ConfigPath, "users_offline.json"), contents); } public static void CreateLocationVBloodDefaultConfig() { string contents = JsonSerializer.Serialize(PrefabToNamesDefault, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(Path.Combine(ConfigPath, "prefabs_names.json"), contents); } public static void CreateIgnoreVBloodDefaultConfig() { string contents = JsonSerializer.Serialize(PrefabsIgnoreDefaul, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(Path.Combine(ConfigPath, "prefabs_names_ignore.json"), contents); } public static void CreateVBloodNotifyIgnoreConfig() { string contents = JsonSerializer.Serialize(DefaultVBloodAnnounceIgnoreUsers, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(Path.Combine(ConfigPath, "vbloodannounce_ignore_users.json"), contents); } public static void CreateAutoAnnouncerMessagesConfig() { File.WriteAllText(Path.Combine(ConfigPath, "auto_announcer_messages.json"), DefaultAutoAnnounceMessagesConfig); } public static void CreateMessagesOfTheDayConfig() { string contents = JsonSerializer.Serialize(DefaultMessageOfTheDay, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(Path.Combine(ConfigPath, "message_of_the_day.json"), contents); } public static void CheckAndCreateConfigs() { if (!File.Exists(Path.Combine(ConfigPath, "users_online.json"))) { CreateOnlineDefaultConfig(); } if (!File.Exists(Path.Combine(ConfigPath, "users_offline.json"))) { CreateOfflineDefaultConfig(); } if (!File.Exists(Path.Combine(ConfigPath, "default_announce.json"))) { CreateDefaultNotificationTextConfig(); } if (!File.Exists(Path.Combine(ConfigPath, "prefabs_names.json"))) { CreateLocationVBloodDefaultConfig(); } if (!File.Exists(Path.Combine(ConfigPath, "prefabs_names_ignore.json"))) { CreateIgnoreVBloodDefaultConfig(); } if (!File.Exists(Path.Combine(ConfigPath, "vbloodannounce_ignore_users.json"))) { CreateVBloodNotifyIgnoreConfig(); } if (!File.Exists(Path.Combine(ConfigPath, "auto_announcer_messages.json"))) { CreateAutoAnnouncerMessagesConfig(); } if (!File.Exists(Path.Combine(ConfigPath, "message_of_the_day.json"))) { CreateMessagesOfTheDayConfig(); } } } internal class Database { private static string VBloodFinalConcatCharacters; private static int IntervalAutoAnnouncer; private static List<AutoAnnouncerMessage> AutoAnnouncerMessages; private static List<string> MessageOfTheDay; internal static Dictionary<NotifyFeature, bool> EnabledFeatures; private static Dictionary<string, string> DefaultAnnounce { get; set; } private static Dictionary<string, string> UsersConfigOnline { get; set; } private static Dictionary<string, string> UsersConfigOffline { get; set; } private static Dictionary<string, string> PrefabToNames { get; set; } private static Dictionary<string, bool> PrefabsIgnore { get; set; } private static Dictionary<string, bool> VBloodNotifyIgnore { get; set; } static Database() { VBloodFinalConcatCharacters = "and"; IntervalAutoAnnouncer = 0; AutoAnnouncerMessages = new List<AutoAnnouncerMessage>(); MessageOfTheDay = new List<string>(); DefaultAnnounce = new Dictionary<string, string>(); UsersConfigOnline = new Dictionary<string, string>(); UsersConfigOffline = new Dictionary<string, string>(); PrefabToNames = new Dictionary<string, string>(); PrefabsIgnore = new Dictionary<string, bool>(); VBloodNotifyIgnore = new Dictionary<string, bool>(); EnabledFeatures = new Dictionary<NotifyFeature, bool>(); setAllFeatures(isEnabled: false); } internal static void setAllFeatures(bool isEnabled) { foreach (NotifyFeature value in Enum.GetValues(typeof(NotifyFeature))) { EnabledFeatures[value] = isEnabled; } } public static void setVBloodFinalConcatCharacters(string value) { VBloodFinalConcatCharacters = value; } public static string getVBloodFinalConcatCharacters() { return VBloodFinalConcatCharacters; } public static bool setDefaultAnnounce(Dictionary<string, string> value) { if (value == null) { return false; } DefaultAnnounce = value; return true; } public static bool setUsersOnline(Dictionary<string, string> value) { if (value == null) { return false; } UsersConfigOnline = value; return true; } public static bool setUsersOffline(Dictionary<string, string> value) { if (value == null) { return false; } UsersConfigOffline = value; return true; } public static bool setPrefabsNames(Dictionary<string, string> value) { if (value == null) { return false; } PrefabToNames = value; return true; } public static bool setPrefabsIgnore(Dictionary<string, bool> value) { if (value == null) { return false; } PrefabsIgnore = value; return true; } public static bool setVBloodNotifyIgnore(Dictionary<string, bool> value) { if (value == null) { return false; } VBloodNotifyIgnore = value; return true; } public static string getDefaultAnnounceValue(string value) { if (value == null) { return value; } if (DefaultAnnounce.ContainsKey(value)) { return DefaultAnnounce[value]; } return value; } public static string getUserOnlineValue(string user) { if (user == null || user == "") { return getDefaultAnnounceValue("newUser"); } if (UsersConfigOnline.ContainsKey(user)) { return UsersConfigOnline[user]; } return getDefaultAnnounceValue("online"); } public static string getUserOfflineValue(string user) { if (user == null || user == "") { return user; } if (UsersConfigOffline.ContainsKey(user)) { return UsersConfigOffline[user]; } return getDefaultAnnounceValue("offline"); } public static string getPrefabNameValue(string prefabName) { if (prefabName == null) { return "NoPrefabName"; } if (PrefabToNames.ContainsKey(prefabName)) { return PrefabToNames[prefabName]; } return PrefabToNames["NoPrefabName"]; } public static bool getPrefabIgnoreValue(string prefabName) { if (prefabName == null) { return true; } if (PrefabsIgnore.ContainsKey(prefabName)) { return PrefabsIgnore[prefabName]; } return true; } public static bool getVBloodNotifyIgnore(string characterName) { if (characterName == null) { return false; } if (VBloodNotifyIgnore.ContainsKey(characterName)) { return true; } return false; } public static bool addVBloodNotifyIgnore(string characterName) { if (VBloodNotifyIgnore.ContainsKey(characterName)) { return true; } VBloodNotifyIgnore.Add(characterName, value: true); SaveDatabase.SaveVBloodNotifyIgnoreConfig(VBloodNotifyIgnore); return true; } public static bool removeVBloodNotifyIgnore(string characterName) { if (VBloodNotifyIgnore.ContainsKey(characterName)) { VBloodNotifyIgnore.Remove(characterName); SaveDatabase.SaveVBloodNotifyIgnoreConfig(VBloodNotifyIgnore); return true; } return true; } public static int getIntervalAutoAnnouncer() { return IntervalAutoAnnouncer; } public static void setIntervalAutoAnnouncer(int intervalAutoAnnouncer) { IntervalAutoAnnouncer = intervalAutoAnnouncer; } public static List<AutoAnnouncerMessage> getAutoAnnouncerMessages() { return AutoAnnouncerMessages; } public static void addAutoAnnouncerMessages(AutoAnnouncerMessage autoAnnouncerMessages) { AutoAnnouncerMessages.Add(autoAnnouncerMessages); } public static void setMessageOfTheDay(List<string> _messageOfTheDay) { MessageOfTheDay = _messageOfTheDay; } public static List<string> getMessageOfTheDay() { return MessageOfTheDay; } } internal class LoadDatabase { public static void LoadAllConfig() { LoadDefaultAnnounce(); LoadUsersConfigOnline(); LoadUsersConfigOffline(); LoadPrefabsName(); LoadPrefabsIgnore(); VBloodNotifyIgnoreConfig(); LoadAutoAnnouncerMessagesConfig(); LoadMessageOfTheDayConfig(); } public static void LoadDefaultAnnounce() { Database.setDefaultAnnounce(JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(Path.Combine(Config.ConfigPath, "default_announce.json")))); } public static void LoadUsersConfigOnline() { Database.setUsersOnline(JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(Path.Combine(Config.ConfigPath, "users_online.json")))); } public static void LoadUsersConfigOffline() { Database.setUsersOffline(JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(Path.Combine(Config.ConfigPath, "users_offline.json")))); } public static void LoadPrefabsName() { Database.setPrefabsNames(JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(Path.Combine(Config.ConfigPath, "prefabs_names.json")))); } public static void LoadPrefabsIgnore() { Database.setPrefabsIgnore(JsonSerializer.Deserialize<Dictionary<string, bool>>(File.ReadAllText(Path.Combine(Config.ConfigPath, "prefabs_names_ignore.json")))); } public static void VBloodNotifyIgnoreConfig() { Database.setVBloodNotifyIgnore(JsonSerializer.Deserialize<Dictionary<string, bool>>(File.ReadAllText(Path.Combine(Config.ConfigPath, "vbloodannounce_ignore_users.json")))); } public static void LoadAutoAnnouncerMessagesConfig() { string content = File.ReadAllText(Path.Combine(Config.ConfigPath, "auto_announcer_messages.json")); foreach (AutoAnnouncerMessage item in new MessageParser().Parse(content)) { Database.addAutoAnnouncerMessages(item); } } public static void LoadMessageOfTheDayConfig() { Database.setMessageOfTheDay(JsonSerializer.Deserialize<List<string>>(File.ReadAllText(Path.Combine(Config.ConfigPath, "message_of_the_day.json")))); } } public enum NotifyFeature { motd, newuser, offline, online, auto, vblood } internal class SaveDatabase { public static readonly string ConfigPath = Path.Combine(Paths.ConfigPath, "Notify"); public static void SaveVBloodNotifyIgnoreConfig(Dictionary<string, bool> VBloodAnnounceIgnoreUsers) { string contents = JsonSerializer.Serialize(VBloodAnnounceIgnoreUsers, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(Path.Combine(ConfigPath, "vbloodannounce_ignore_users.json"), contents); } } } namespace BloodyNotify.Command { [CommandGroup("bn", null)] internal class BloodyNotifyCommand { [Command("online", "o", null, "To reload the configuration of the user messages online, offline or death of the VBlood boss", null, false)] public static void Online(ChatCommandContext ctx) { ctx.Reply("Users Online ---------"); foreach (UserModel item in GameData.Users.Online.OrderBy((UserModel x) => x.IsAdmin)) { if (item.IsAdmin) { ctx.Reply(FontColorChatSystem.Green("[ADMIN]") + " " + FontColorChatSystem.Yellow(item.CharacterName)); } else { ctx.Reply(FontColorChatSystem.Yellow(item.CharacterName) ?? ""); } } } [Command("reload", "rl", null, "To reload the configuration of the user messages online, offline or death of the VBlood boss", null, true)] public static void RealoadMod(ChatCommandContext ctx) { if (!Database.EnabledFeatures[NotifyFeature.offline]) { LoadDatabase.LoadUsersConfigOffline(); } if (!Database.EnabledFeatures[NotifyFeature.online]) { LoadDatabase.LoadUsersConfigOnline(); } if (!Database.EnabledFeatures[NotifyFeature.vblood]) { LoadDatabase.LoadPrefabsName(); LoadDatabase.LoadPrefabsIgnore(); } if (!Database.EnabledFeatures[NotifyFeature.newuser]) { LoadDatabase.LoadDefaultAnnounce(); } if (!Database.EnabledFeatures[NotifyFeature.auto]) { LoadDatabase.LoadAutoAnnouncerMessagesConfig(); } if (!Database.EnabledFeatures[NotifyFeature.motd]) { LoadDatabase.LoadMessageOfTheDayConfig(); } ctx.Reply("Reloaded configuration of BloodyNotify mod."); } [Command("vblood", "vba", "ignore/unignore", "ignore/unignore vblood announce system.", null, false)] public static void Vbloodannounce(ChatCommandContext ctx, string action = "unignore") { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) User user = ctx.User; if (!(action == "ignore")) { if (action == "unignore") { Database.removeVBloodNotifyIgnore(((object)(FixedString64Bytes)(ref user.CharacterName)).ToString()); ctx.Reply(FontColorChatSystem.Green("You will receive notifications about the death of the VBlood. To undo this option use the command " + FontColorChatSystem.Yellow(".notify vbloodannounce ignore"))); } } else { Database.addVBloodNotifyIgnore(((object)(FixedString64Bytes)(ref user.CharacterName)).ToString()); ctx.Reply(FontColorChatSystem.Green("You will not receive any more notifications about the death of the VBlood. To undo this option use the command " + FontColorChatSystem.Yellow(".notify vbloodannounce unignore"))); } } [Command("config", "cfg", "[ auto, motd, newuser, online, offline, vblood ] true/false", "Enabled / Disabled the features of the mod. [ auto, motd, newuser, online, offline, vblood ]", null, true)] public static void ConfigMod(ChatCommandContext ctx, NotifyFeature feature, bool isEnabled) { Database.EnabledFeatures[feature] = isEnabled; string text = feature switch { NotifyFeature.motd => "Message of The Day:", NotifyFeature.newuser => "Announce New User:", NotifyFeature.online => "Announce Online:", NotifyFeature.offline => "Announce Offline:", NotifyFeature.vblood => "VBlood Announcer:", NotifyFeature.auto => "Auto Announcer:", _ => throw new NotImplementedException(), }; string text2 = FontColorChatSystem.Yellow(isEnabled ? "Enabled" : "Disabled"); ctx.Reply(FontColorChatSystem.Green(text + " " + text2)); } } } namespace BloodyNotify.AutoAnnouncer { public class AutoAnnouncerFunction { private static int __indexMessage; public static void OnTimedAutoAnnouncer() { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) List<AutoAnnouncerMessage> autoAnnouncerMessages = Database.getAutoAnnouncerMessages(); if (autoAnnouncerMessages.Count <= 0) { return; } if (autoAnnouncerMessages.Count == 1) { foreach (string messageLine in autoAnnouncerMessages[0].MessageLines) { ServerChatUtils.SendSystemMessageToAllClients(Plugin.SystemsCore.EntityManager, messageLine); } return; } foreach (string messageLine2 in autoAnnouncerMessages[__indexMessage].MessageLines) { ServerChatUtils.SendSystemMessageToAllClients(Plugin.SystemsCore.EntityManager, messageLine2); } __indexMessage++; if (__indexMessage >= autoAnnouncerMessages.Count) { __indexMessage = 0; } } public static void StartAutoAnnouncer() { CoroutineHandler.StartRepeatingCoroutine((Action)AutoAnnouncerAction, (float)Database.getIntervalAutoAnnouncer()); static void AutoAnnouncerAction() { if (Database.EnabledFeatures[NotifyFeature.auto]) { OnTimedAutoAnnouncer(); } } } } } namespace BloodyNotify.AutoAnnouncer.Parser { public class MessageParser { public IEnumerable<AutoAnnouncerMessage> Parse(string content) { if (content == null) { throw new ArgumentNullException("content"); } if (string.IsNullOrWhiteSpace(content)) { yield break; } string[][] array = JsonSerializer.Deserialize<string[][]>(content); string[][] array2 = array; foreach (string[] obj in array2) { AutoAnnouncerMessage autoAnnouncerMessage = new AutoAnnouncerMessage(); string[] array3 = obj; foreach (string item in array3) { autoAnnouncerMessage.MessageLines.Add(item); } yield return autoAnnouncerMessage; } } } } namespace BloodyNotify.AutoAnnouncer.Models { public class AutoAnnouncerMessage { public List<string> MessageLines { get; set; } = new List<string>(); } }