using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CrimsonEcho.Structs;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Network;
using Stunlock.Core;
using Stunlock.Network;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;
using VAMP;
using VAMP.Attributes;
using VAMP.Data;
using VAMP.Models;
using VAMP.Services;
using VAMP.Systems;
using VAMP.Utilities;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CrimsonEcho")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Automated Notifications")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+Branch.master.Sha.574e28bd13b4882f513b0ba312a7c8b7c0cec281.574e28bd13b4882f513b0ba312a7c8b7c0cec281")]
[assembly: AssemblyProduct("CrimsonEcho")]
[assembly: AssemblyTitle("CrimsonEcho")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
[HarmonyPatch(typeof(ServerBootstrapSystem), "OnUserConnected")]
public static class OnUserConnectedPatch
{
public static List<ulong> welcomed = new List<ulong>();
public static void Postfix(ServerBootstrapSystem __instance, NetConnectionId netConnectionId)
{
//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_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: 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_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: 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_021f: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_0200: Unknown result type (might be due to invalid IL or missing references)
//IL_0425: Unknown result type (might be due to invalid IL or missing references)
//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
//IL_03db: Unknown result type (might be due to invalid IL or missing references)
//IL_0240: Unknown result type (might be due to invalid IL or missing references)
//IL_024c: Unknown result type (might be due to invalid IL or missing references)
//IL_0251: Unknown result type (might be due to invalid IL or missing references)
//IL_0256: Unknown result type (might be due to invalid IL or missing references)
//IL_0261: Unknown result type (might be due to invalid IL or missing references)
//IL_0266: Unknown result type (might be due to invalid IL or missing references)
//IL_026b: Unknown result type (might be due to invalid IL or missing references)
//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
//IL_02da: Unknown result type (might be due to invalid IL or missing references)
//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
//IL_02f2: 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)
if (Core.PlayerService == null || !Settings.ToggleMod.Value)
{
return;
}
try
{
EntityManager entityManager = ((ComponentSystemBase)__instance).EntityManager;
int num = __instance._NetEndPointToApprovedUserIndex[netConnectionId];
Entity userEntity = ((Il2CppArrayBase<ServerClient>)(object)__instance._ApprovedUsersLookup)[num].UserEntity;
User componentData = ((EntityManager)(ref entityManager)).GetComponentData<User>(userEntity);
bool isWhiteListed = true;
ModTalk.Invoke("CrimsonKey.IsWhitelisted", new object[1] { componentData.PlatformId }, (Action<object>)delegate(object result)
{
isWhiteListed = (bool)result;
});
if (!isWhiteListed)
{
return;
}
Player val = PlayerService.PlayerFromUser(componentData);
welcomed.Remove(componentData.PlatformId);
if (((FixedString64Bytes)(ref componentData.CharacterName)).IsEmpty)
{
return;
}
string text = ((object)(FixedString64Bytes)(ref componentData.CharacterName)).ToString();
if (Database.Messages.First((MessagePair x) => x.Key == "PlayerOnline").IsEnabled() && Settings.TogglePlayerOnline.Value && (!val.IsAdminCapable || !Settings.ShadowAdmin.Value))
{
ChatUtil.SystemSendAllExcept(componentData, Database.Messages.First((MessagePair x) => x.Key == "PlayerOnline").ToString(text));
}
if (Database.Messages.First((MessagePair x) => x.Key == "MOTD").IsEnabled() && Settings.ToggleMOTD.Value)
{
ChatUtil.SystemSendUser(componentData, Database.Messages.First((MessagePair x) => x.Key == "MOTD").ToString());
}
if (Database.RandomMessages.Count > 0 && Settings.ToggleRandom.Value)
{
string dailyRandom = Database.GetDailyRandom(Database.RandomMessages);
ChatUtil.SystemSendUser(componentData, dailyRandom.ToString());
}
Entity val2;
if (Settings.ClanPrintout.Value)
{
val2 = val.Clan;
if (!((Entity)(ref val2)).Equals(Entity.Null))
{
List<string> list = new List<string>();
IEnumerable<Player> clanMembersAsPlayers = ClanService.GetClanMembersAsPlayers(val.Clan);
User clanLeader = GetClanLeader(val.Clan);
string text2 = "";
text2 = ((!(EntityUtil.Read<User>(val.User) == clanLeader)) ? (text + ",") : (text + " <color=" + Settings.ClanPrintoutLeaderColor.Value + ">[C]</color>,"));
foreach (Player item in clanMembersAsPlayers)
{
val2 = item.User;
if (((Entity)(ref val2)).Equals(Entity.Null))
{
continue;
}
val2 = item.User;
if (!((Entity)(ref val2)).Equals(val.User))
{
if (EntityUtil.Read<User>(item.User) == clanLeader)
{
list.Add(((FixedString64Bytes)(ref clanLeader.CharacterName)).Value + " <color=" + Settings.ClanPrintoutLeaderColor.Value + ">[C]</color>");
}
else
{
list.Add(item.Name);
}
}
}
if (list.Count >= 1)
{
ChatUtil.SystemSendUser(componentData, $"<color={Settings.ClanPrintoutAccentColor.Value}>Clan:</color> {text2} {string.Join(", ", list)}");
}
}
}
if (Settings.ToggleClanless.Value)
{
val2 = val.Clan;
if (((Entity)(ref val2)).Equals(Entity.Null))
{
ChatUtil.SystemSendUser(componentData, Database.Messages.First((MessagePair x) => x.Key == "Clanless").Value);
}
}
welcomed.Add(componentData.PlatformId);
}
catch (Exception ex)
{
((BasePlugin)Plugin.Instance).Log.LogError((object)ex.Message);
}
}
public static int GetClanLeaderIndex(DynamicBuffer<ClanMemberStatus> clanBuffer)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < clanBuffer.Length; i++)
{
ClanMemberStatus val = clanBuffer[i];
if (((object)(ClanRoleEnum)(ref val.ClanRole)).Equals((object)(ClanRoleEnum)2))
{
return i;
}
}
return -1;
}
public static User GetClanLeader(Entity clan)
{
//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_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
int clanLeaderIndex = GetClanLeaderIndex(EntityUtil.ReadBuffer<ClanMemberStatus>(clan));
return EntityUtil.Read<User>(EntityUtil.ReadBuffer<SyncToUserBuffer>(clan)[clanLeaderIndex].UserEntity);
}
}
[HarmonyPatch(typeof(ServerBootstrapSystem), "OnUserDisconnected")]
public static class OnUserDisconnectedPatch
{
private static void Prefix(ServerBootstrapSystem __instance, NetConnectionId netConnectionId, ConnectionStatusChangeReason connectionStatusReason, string extraData)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: 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_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
if (Core.PlayerService == null)
{
Core.Initialize();
}
if (!Settings.ToggleMod.Value)
{
return;
}
try
{
int num = __instance._NetEndPointToApprovedUserIndex[netConnectionId];
ServerClient val = ((Il2CppArrayBase<ServerClient>)(object)__instance._ApprovedUsersLookup)[num];
EntityManager entityManager = ((ComponentSystemBase)__instance).EntityManager;
User componentData = ((EntityManager)(ref entityManager)).GetComponentData<User>(val.UserEntity);
Player val2 = PlayerService.PlayerFromUser(componentData);
if (!((FixedString64Bytes)(ref componentData.CharacterName)).IsEmpty)
{
string text = ((object)(FixedString64Bytes)(ref componentData.CharacterName)).ToString();
if (Database.Messages.First((MessagePair x) => x.Key == "PlayerOffline").IsEnabled() && Settings.TogglePlayerOffline.Value && (!val2.IsAdminCapable || !Settings.ShadowAdmin.Value))
{
ChatUtil.SystemSendAll(Database.Messages.First((MessagePair x) => x.Key == "PlayerOffline").ToString(text));
}
}
OnUserConnectedPatch.welcomed.Remove(componentData.PlatformId);
}
catch
{
}
}
}
[HarmonyPatch(typeof(Destroy_TravelBuffSystem), "OnUpdate")]
public class Destroy_TravelBuffSystem_Patch
{
private static void Postfix(Destroy_TravelBuffSystem __instance)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: 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_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: 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_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: 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_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: 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_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: 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_00a8: 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_00b1: 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_00b8: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_029b: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
//IL_0288: Unknown result type (might be due to invalid IL or missing references)
if (Core.PlayerService == null || !Settings.ToggleMod.Value)
{
return;
}
EntityQuery _query_615927226_ = __instance.__query_615927226_0;
Enumerator<Entity> enumerator = ((EntityQuery)(ref _query_615927226_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).GetEnumerator();
while (enumerator.MoveNext())
{
Entity current = enumerator.Current;
EntityManager entityManager = ((ComponentSystemBase)__instance).EntityManager;
PrefabGUID componentData = ((EntityManager)(ref entityManager)).GetComponentData<PrefabGUID>(current);
if (!((PrefabGUID)(ref componentData)).Equals(Prefabs.AB_Interact_TombCoffinSpawn_Travel))
{
continue;
}
entityManager = ((ComponentSystemBase)__instance).EntityManager;
Entity owner = ((EntityManager)(ref entityManager)).GetComponentData<EntityOwner>(current).Owner;
entityManager = ((ComponentSystemBase)__instance).EntityManager;
if (!((EntityManager)(ref entityManager)).HasComponent<PlayerCharacter>(owner))
{
continue;
}
entityManager = ((ComponentSystemBase)__instance).EntityManager;
Entity userEntity = ((EntityManager)(ref entityManager)).GetComponentData<PlayerCharacter>(owner).UserEntity;
entityManager = ((ComponentSystemBase)__instance).EntityManager;
User componentData2 = ((EntityManager)(ref entityManager)).GetComponentData<User>(userEntity);
if (OnUserConnectedPatch.welcomed.Contains(componentData2.PlatformId))
{
continue;
}
Player val = PlayerService.PlayerFromUser(componentData2);
if (Database.Messages.First((MessagePair x) => x.Key == "NewPlayerWelcome").IsEnabled() && Settings.ToggleNewPlayerWelcome.Value)
{
ChatUtil.SystemSendUser(componentData2, Database.Messages.First((MessagePair x) => x.Key == "NewPlayerWelcome").ToString(componentData2));
}
if (Database.Messages.First((MessagePair x) => x.Key == "NewPlayerAnnounce").IsEnabled() && Settings.ToggleNewPlayerAnnounce.Value && (!val.IsAdminCapable || !Settings.ShadowAdmin.Value))
{
ChatUtil.SystemSendAllExcept(componentData2, Database.Messages.First((MessagePair x) => x.Key == "NewPlayerAnnounce").ToString(componentData2));
}
if (Database.Messages.First((MessagePair x) => x.Key == "NewPlayerMOTD").IsEnabled() && Settings.ToggleNewPlayerMOTD.Value)
{
ChatUtil.SystemSendUser(componentData2, Database.Messages.First((MessagePair x) => x.Key == "NewPlayerMOTD").ToString());
}
if (Database.RandomMessages.Count > 0 && Settings.ToggleNewPlayerRandom.Value)
{
string dailyRandom = Database.GetDailyRandom(Database.RandomMessages);
ChatUtil.SystemSendUser(componentData2, dailyRandom.ToString());
}
OnUserConnectedPatch.welcomed.Add(componentData2.PlatformId);
}
}
}
public struct MessagePair
{
public string Key { get; set; }
public string Value { get; set; }
public MessagePair(string key, string value)
{
Key = key;
Value = value;
}
public bool IsEnabled()
{
if (string.IsNullOrEmpty(Value))
{
return false;
}
return true;
}
public override string ToString()
{
return Value;
}
public string ToString(string userName)
{
return Value.Replace("{player}", userName);
}
public string ToString(User user)
{
return ToString(((FixedString64Bytes)(ref user.CharacterName)).Value);
}
public string ToString(Player player, PrefabGUID vblood)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
return Value.Replace("{vblood.long}", VBloods.ToString(vblood)).Replace("{vblood.short}", VBloods.ToShortString(vblood)).Replace("{vblood}", ((object)(PrefabGUID)(ref vblood)).ToString())
.Replace("{player}", player.Name);
}
}
namespace CrimsonEcho
{
[BepInPlugin("CrimsonEcho", "CrimsonEcho", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BasePlugin
{
private Harmony _harmony;
public static Plugin Instance { get; private set; }
public static Harmony Harmony => Instance._harmony;
public static ManualLogSource LogInstance => ((BasePlugin)Instance).Log;
public static Settings Settings { get; private set; }
public static string ConfigFiles => Path.Combine(Paths.ConfigPath, "CrimsonEcho");
public Database Database { get; private set; }
public override void Load()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
Instance = this;
Settings = default(Settings);
Settings.InitConfig();
_harmony = new Harmony("CrimsonEcho");
_harmony.PatchAll(Assembly.GetExecutingAssembly());
Events.OnCoreLoaded = (Action)Delegate.Combine(Events.OnCoreLoaded, new Action(Loaded));
}
public void Loaded()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
Database = new Database();
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("CrimsonEcho");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!");
}
log.LogInfo(val);
Core.StartCoroutine(AutoMessageLoop());
}
private IEnumerator AutoMessageLoop()
{
int loopsForAutoMessage = 0;
while (true)
{
yield return (object)new WaitForSeconds(60f);
loopsForAutoMessage++;
if (loopsForAutoMessage % Settings.AutoMessageInterval.Value == 0 && Database.AutoMessages.Count > 0)
{
Database.SendAutoMessage();
loopsForAutoMessage = 0;
}
if (Database.Announcements == null || Database.Announcements.Count <= 0)
{
continue;
}
DateTime dateTime = (Settings.TimesInUTC.Value ? DateTime.UtcNow : DateTime.Now);
List<Announcement> list = new List<Announcement>();
foreach (Announcement announcement in Database.Announcements)
{
if ((!announcement.DayOfWeek.HasValue || announcement.DayOfWeek == dateTime.DayOfWeek) && announcement.Time.Hour == dateTime.Hour && announcement.Time.Minute == dateTime.Minute)
{
ChatUtil.SystemSendAll(announcement.Message);
if (announcement.OneTime)
{
list.Add(announcement);
}
}
}
if (list.Count <= 0)
{
continue;
}
foreach (Announcement item in list)
{
Database.Announcements.Remove(item);
}
Database.SaveAnnouncements();
}
}
public override bool Unload()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
return true;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "CrimsonEcho";
public const string PLUGIN_NAME = "CrimsonEcho";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace CrimsonEcho.Structs
{
public struct Announcement
{
public string Message { get; set; }
public DayOfWeek? DayOfWeek { get; set; }
public TimeOnly Time { get; set; }
public bool OneTime { get; set; }
public Announcement(string message, DayOfWeek? day, TimeOnly time, bool oneTime)
{
Message = message;
DayOfWeek = day;
Time = time;
OneTime = oneTime;
}
public override string ToString()
{
return Message;
}
}
public class AnnouncementConverter : JsonConverter<Announcement>
{
private const string TimeFormat = "HH:mm";
public override Announcement Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException("Expected start of object");
}
string message = string.Empty;
DayOfWeek? day = null;
TimeOnly time = new TimeOnly(0, 0);
bool oneTime = false;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return new Announcement(message, day, time, oneTime);
}
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException("Expected property name");
}
string @string = reader.GetString();
reader.Read();
switch (@string)
{
case "Message":
message = reader.GetString();
break;
case "DayOfWeek":
{
if (reader.TokenType == JsonTokenType.Null)
{
day = null;
break;
}
string string3 = reader.GetString();
DayOfWeek result;
if (string.IsNullOrEmpty(string3) || string3.Equals("Daily", StringComparison.OrdinalIgnoreCase))
{
day = null;
}
else if (Enum.TryParse<DayOfWeek>(string3, ignoreCase: true, out result))
{
day = result;
}
break;
}
case "Time":
{
string string2 = reader.GetString();
try
{
time = TimeOnly.ParseExact(string2 ?? "00:00", "HH:mm");
}
catch
{
time = TimeOnly.Parse(string2 ?? "00:00");
}
break;
}
case "OneTime":
oneTime = reader.GetBoolean();
break;
}
}
throw new JsonException("Expected end of object");
}
public override void Write(Utf8JsonWriter writer, Announcement value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WritePropertyName("Message");
writer.WriteStringValue(value.Message);
writer.WritePropertyName("DayOfWeek");
if (value.DayOfWeek.HasValue)
{
writer.WriteStringValue(value.DayOfWeek.Value.ToString());
}
else
{
writer.WriteStringValue("Daily");
}
writer.WritePropertyName("Time");
writer.WriteStringValue(value.Time.ToString("HH:mm"));
writer.WritePropertyName("OneTime");
writer.WriteBooleanValue(value.OneTime);
writer.WriteEndObject();
}
}
public class AutoMessage
{
public string Content { get; set; }
[JsonPropertyName("isFirst")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool IsFirst { get; set; }
public AutoMessage()
{
}
public AutoMessage(string content, bool isFirst = false)
{
Content = content;
IsFirst = isFirst;
}
public override string ToString()
{
return Content;
}
}
public class Database
{
public static readonly JsonSerializerOptions prettyJsonOptions = new JsonSerializerOptions
{
WriteIndented = true,
IncludeFields = true,
AllowTrailingCommas = true,
ReadCommentHandling = JsonCommentHandling.Skip,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
Converters = { (JsonConverter)new AnnouncementConverter() }
};
[FileReload("MessagesLoad")]
public static string MessageFile = Path.Combine(Plugin.ConfigFiles, "messages.json");
[FileReload("AutoMessageLoad")]
public static string AutoMessageFile = Path.Combine(Plugin.ConfigFiles, "auto_messages.json");
[FileReload("RandomMessageLoad")]
public static string RandomFile = Path.Combine(Plugin.ConfigFiles, "daily_randoms.json");
[FileReload("AnnouncementLoad")]
public static string AnnouncementFile = Path.Combine(Plugin.ConfigFiles, "announcements.json");
public static List<MessagePair> Messages;
public static List<string> RandomMessages;
public static List<AutoMessage> AutoMessages;
public static List<Announcement> Announcements;
private static int lastSentAuto = 0;
public Database()
{
LoadDatabase();
}
private static void LoadDatabase()
{
if (!Directory.Exists(Plugin.ConfigFiles))
{
Directory.CreateDirectory(Plugin.ConfigFiles);
}
MessagesLoad();
RandomMessageLoad();
AutoMessageLoad();
AnnouncementLoad();
}
private static void MessagesLoad()
{
try
{
List<MessagePair> defaultMessages = GetDefaultMessages();
if (File.Exists(MessageFile))
{
string json = File.ReadAllText(MessageFile, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
List<MessagePair> list = JsonSerializer.Deserialize<List<MessagePair>>(json, prettyJsonOptions);
bool flag = false;
foreach (MessagePair defaultMsg in defaultMessages)
{
if (!list.Any((MessagePair m) => m.Key == defaultMsg.Key))
{
list.Add(defaultMsg);
flag = true;
}
}
Messages = list;
if (flag)
{
json = JsonSerializer.Serialize(Messages, prettyJsonOptions);
File.WriteAllText(MessageFile, json, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
}
else
{
Messages = defaultMessages;
string contents = JsonSerializer.Serialize(Messages, prettyJsonOptions);
File.WriteAllText(MessageFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
}
catch
{
Messages = (from m in GetDefaultMessages()
select new MessagePair(m.Key, "")).ToList();
Plugin.LogInstance.LogInfo((object)"Messages not loaded.");
}
}
private static List<MessagePair> GetDefaultMessages()
{
return new List<MessagePair>(7)
{
new MessagePair("PlayerOnline", "{player} is now online."),
new MessagePair("PlayerOffline", "{player} is now offline."),
new MessagePair("NewPlayerWelcome", "Welcome to the server {player}!"),
new MessagePair("NewPlayerAnnounce", "{player} has joined the server for the first time. Say hello!"),
new MessagePair("NewPlayerMOTD", ""),
new MessagePair("MOTD", ""),
new MessagePair("Clanless", "Consider joining a clan!")
};
}
private static void RandomMessageLoad()
{
try
{
if (File.Exists(RandomFile))
{
RandomMessages = JsonSerializer.Deserialize<List<string>>(File.ReadAllText(RandomFile, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)), prettyJsonOptions);
return;
}
RandomMessages = new List<string>(3) { "Dracula's Generals laugh at your attempts.", "But can you pet the Winged Horror?", "Who can be trusted when all creatures of the night are ready to siege?" };
string contents = JsonSerializer.Serialize(RandomMessages, prettyJsonOptions);
File.WriteAllText(RandomFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
catch
{
RandomMessages = new List<string>();
Plugin.LogInstance.LogInfo((object)"Random messages not loaded.");
}
}
private static void AnnouncementLoad()
{
try
{
if (File.Exists(AnnouncementFile))
{
Announcements = JsonSerializer.Deserialize<List<Announcement>>(File.ReadAllText(AnnouncementFile, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)), prettyJsonOptions);
return;
}
Announcements = new List<Announcement>(2)
{
new Announcement("Brought to you by CrimsonMods", null, new TimeOnly(12, 0), oneTime: false),
new Announcement("It's Wednesday!", DayOfWeek.Wednesday, new TimeOnly(17, 0), oneTime: false)
};
SaveAnnouncements();
}
catch (Exception ex)
{
Announcements = new List<Announcement>();
Plugin.LogInstance.LogInfo((object)"Announcements not loaded.");
Plugin.LogInstance.LogInfo((object)ex.ToString());
}
}
private static void AutoMessageLoad()
{
try
{
if (File.Exists(AutoMessageFile))
{
AutoMessages = JsonSerializer.Deserialize<List<AutoMessage>>(File.ReadAllText(AutoMessageFile, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)), prettyJsonOptions);
lastSentAuto = 0;
return;
}
AutoMessages = new List<AutoMessage>(2)
{
new AutoMessage("Join our discord for more information!", isFirst: true),
new AutoMessage("VAMP Powered Development!")
};
string contents = JsonSerializer.Serialize(AutoMessages, prettyJsonOptions);
File.WriteAllText(AutoMessageFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
catch (Exception ex)
{
AutoMessages = new List<AutoMessage>();
Plugin.LogInstance.LogInfo((object)"Auto messages not loaded.");
Plugin.LogInstance.LogInfo((object)ex.ToString());
}
}
public static T GetDailyRandom<T>(IList<T> collection)
{
if (collection == null || collection.Count == 0)
{
return default(T);
}
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
int index = (int)((DateTime.UtcNow.Date - dateTime).TotalDays % (double)collection.Count);
return collection[index];
}
public static void SendAutoMessage()
{
if (AutoMessages.Count == 0)
{
return;
}
if (lastSentAuto == 0)
{
for (int i = 0; i < AutoMessages.Count; i++)
{
if (AutoMessages[i].IsFirst)
{
lastSentAuto = i;
break;
}
}
}
ChatUtil.SystemSendAll(AutoMessages[lastSentAuto].Content);
lastSentAuto = (lastSentAuto + 1) % AutoMessages.Count;
}
public static void SaveAnnouncements()
{
string text = "Announcements are intended to be pre-scheduled and will be sent at the time specified." + Environment.NewLine + "The time is based on the server's timezone (24:00 hour clock), but can be switched to UTC in CrimsonEcho.cfg" + Environment.NewLine + "DayOfWeek must be one of the following values: " + Environment.NewLine + "Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, or Daily" + Environment.NewLine + "Setting OneTime to true will automatically remove the announcement from the list after broadcasting to the server." + Environment.NewLine + "Note: Saved changes will take effect immediately, no server restart is required.";
string contents = JsonUtil.SerializeWithComments<List<Announcement>>(Announcements, text, prettyJsonOptions);
File.WriteAllText(AnnouncementFile, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
public readonly struct Settings
{
private static readonly List<string> OrderedSections = new List<string> { "Toggles", "Onboarding", "Customization" };
public static ConfigEntry<bool> ToggleMod { get; private set; }
public static ConfigEntry<bool> TimesInUTC { get; private set; }
public static ConfigEntry<bool> TogglePlayerOnline { get; private set; }
public static ConfigEntry<bool> TogglePlayerOffline { get; private set; }
public static ConfigEntry<bool> ToggleMOTD { get; private set; }
public static ConfigEntry<bool> ToggleRandom { get; private set; }
public static ConfigEntry<bool> ToggleClanless { get; private set; }
public static ConfigEntry<bool> ToggleNewPlayerWelcome { get; private set; }
public static ConfigEntry<bool> ToggleNewPlayerAnnounce { get; private set; }
public static ConfigEntry<bool> ToggleNewPlayerMOTD { get; private set; }
public static ConfigEntry<bool> ToggleNewPlayerRandom { get; private set; }
public static ConfigEntry<int> AutoMessageInterval { get; private set; }
public static ConfigEntry<bool> ShadowAdmin { get; private set; }
public static ConfigEntry<bool> ClanPrintout { get; private set; }
public static ConfigEntry<string> ClanPrintoutAccentColor { get; private set; }
public static ConfigEntry<string> ClanPrintoutLeaderColor { get; private set; }
public static void InitConfig()
{
ToggleMod = InitConfigEntry(OrderedSections[0], "Toggle", defaultValue: true, "If true the mod will be usable; otherwise it will be disabled.");
TogglePlayerOnline = InitConfigEntry(OrderedSections[0], "TogglePlayerOnline", defaultValue: true, "If true, the player online message will be shown.");
TogglePlayerOffline = InitConfigEntry(OrderedSections[0], "TogglePlayerOffline", defaultValue: true, "If true, the player offline message will be shown.");
ToggleMOTD = InitConfigEntry(OrderedSections[0], "ToggleMOTD", defaultValue: true, "If true, the MOTD message will be shown.");
ToggleRandom = InitConfigEntry(OrderedSections[0], "ToggleRandom", defaultValue: true, "If true, the random message will be shown.");
ClanPrintout = InitConfigEntry(OrderedSections[0], "ToggleClanPrintout", defaultValue: false, "If true, the clan printout message will be shown on connection with list of members.");
ToggleClanless = InitConfigEntry(OrderedSections[0], "ToggleClanless", defaultValue: false, "If true, the clanless message will be shown.");
ToggleNewPlayerWelcome = InitConfigEntry(OrderedSections[1], "ToggleNewPlayerWelcome", defaultValue: true, "If true, the new player welcome message will be shown.");
ToggleNewPlayerAnnounce = InitConfigEntry(OrderedSections[1], "ToggleNewPlayerAnnounce", defaultValue: true, "If true, the new player announce message will be shown.");
ToggleNewPlayerMOTD = InitConfigEntry(OrderedSections[1], "ToggleNewPlayerMOTD", defaultValue: true, "If true, the new player MOTD message will be shown.");
ToggleNewPlayerRandom = InitConfigEntry(OrderedSections[1], "ToggleNewPlayerRandom", defaultValue: true, "If true, the random message will be shown for new players.");
TimesInUTC = InitConfigEntry(OrderedSections[2], "TimesInUTC", defaultValue: false, "If true, times in config files will be read as UTC times instead of the server's local time.");
AutoMessageInterval = InitConfigEntry(OrderedSections[2], "AutoMessageInterval", 30, "The interval (in minutes) between auto messages.");
ShadowAdmin = InitConfigEntry(OrderedSections[2], "ShadowAdmins", defaultValue: false, "If true, online/offline broadcast messages will not be sent for admins when they login/logoff.");
ClanPrintoutAccentColor = InitConfigEntry(OrderedSections[2], "ClanPrintoutAccentColor", "#def", "The hex color value of the clan printout label.");
ClanPrintoutLeaderColor = InitConfigEntry(OrderedSections[2], "ClanPrintoutLeaderTagColor", "#b7309c", "The hex color value of the clan printout leader tag.");
ReorderConfigSections();
}
private static ConfigEntry<T> InitConfigEntry<T>(string section, string key, T defaultValue, string description)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
ConfigEntry<T> val = ((BasePlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, description);
string text = Path.Combine(Paths.ConfigPath, "CrimsonEcho.cfg");
ConfigEntry<T> val2 = default(ConfigEntry<T>);
if (File.Exists(text) && new ConfigFile(text, true).TryGetEntry<T>(section, key, ref val2))
{
val.Value = val2.Value;
}
return val;
}
private static void ReorderConfigSections()
{
string path = Path.Combine(Paths.ConfigPath, "CrimsonEcho.cfg");
if (!File.Exists(path))
{
return;
}
List<string> list = File.ReadAllLines(path).ToList();
Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
string text = "";
foreach (string item in list)
{
if (item.StartsWith("["))
{
text = item.Trim('[', ']');
dictionary[text] = new List<string> { item };
}
else if (!string.IsNullOrWhiteSpace(text))
{
dictionary[text].Add(item);
}
}
using StreamWriter streamWriter = new StreamWriter(path, append: false);
foreach (string orderedSection in OrderedSections)
{
if (!dictionary.ContainsKey(orderedSection))
{
continue;
}
foreach (string item2 in dictionary[orderedSection])
{
streamWriter.WriteLine(item2);
}
streamWriter.WriteLine();
}
}
}
}