

using System;
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.Text;
using EventsIO.Interfaces;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("EventIO")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyProduct("EventIO")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ab7abff2-5203-43d0-88ed-aebd4b6a130c")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace EventsIO
{
public class EventsData : IEventsData
{
public string Username { get; set; }
public string Cost { get; set; }
public string EventID { get; set; }
public string Lang { get; set; }
public string ExtraInfo { get; set; }
public override string ToString()
{
return "EventsData: " + Username + " " + Cost + " " + EventID + " " + Lang + " " + ExtraInfo;
}
}
public class EventsDataEncoder : IEventsDataEncoder, IEventsDataEncoderParams
{
internal static readonly string clientAppSep = "&";
internal static readonly char clientAppSepChar = '&';
internal static readonly string clientAppEqual = "=";
internal static readonly char clientAppEqualChar = '=';
protected static readonly Dictionary<string, string> symbolCodes = new Dictionary<string, string>
{
{ clientAppSep, "%encode_amp%" },
{ clientAppEqual, "%encode_equal%" }
};
string IEventsDataEncoderParams.ClientAppSep => clientAppSep;
char IEventsDataEncoderParams.ClientAppSepChar => clientAppSepChar;
string IEventsDataEncoderParams.ClientAppEqual => clientAppEqual;
char IEventsDataEncoderParams.ClientAppEqualChar => clientAppEqualChar;
public virtual string Encode(string s)
{
foreach (KeyValuePair<string, string> symbolCode in symbolCodes)
{
s = s?.Replace(symbolCode.Key, symbolCode.Value);
}
return s;
}
public virtual string Decode(string s)
{
foreach (KeyValuePair<string, string> symbolCode in symbolCodes)
{
s = s?.Replace(symbolCode.Value, symbolCode.Key);
}
return s;
}
}
public class EventsDataParser : IEventsDataParser
{
protected readonly Action<string> log;
protected readonly IEventsDataEncoder encoder;
protected readonly IEventsDataEncoderParams encoderParams;
public bool isLogInfoError = true;
public bool isLogSkipEmpty;
public EventsDataParser(Action<string> log = null)
{
this.log = log;
encoderParams = (IEventsDataEncoderParams)(encoder = new EventsDataEncoder());
}
protected virtual void ParserLog(string s)
{
log?.Invoke(s);
}
public virtual IEventsData ParseEvent(string data)
{
EventsData eventsData = new EventsData();
string[] array = data.Split(new char[1] { encoderParams.ClientAppSepChar }, StringSplitOptions.RemoveEmptyEntries);
if (array == null)
{
if (isLogInfoError)
{
ParserLog("get event info error. Wrong args.");
}
return eventsData;
}
string[] array2 = array;
foreach (string text in array2)
{
string[] array3 = text.Split(new char[1] { encoderParams.ClientAppEqualChar }, StringSplitOptions.RemoveEmptyEntries);
if (array3.Length != 2)
{
if (isLogSkipEmpty)
{
ParserLog("skip empty item: " + text);
}
continue;
}
string text2 = encoder.Decode(array3[0]);
string text3 = encoder.Decode(array3[1]);
switch (text2.ToLowerInvariant())
{
case "username":
eventsData.Username = text3;
break;
case "eventid":
eventsData.EventID = text3;
break;
case "cost":
eventsData.Cost = text3;
break;
case "lang":
eventsData.Lang = text3;
break;
case "extrainfo":
eventsData.ExtraInfo = text3;
break;
}
}
return eventsData;
}
}
public class EventsGenerator : IEventsGenerator
{
protected internal enum FieldNames
{
UserName,
EventID,
Cost,
Lang,
ExtraInfo
}
protected EventsData data;
protected readonly IEventsDataEncoder encoder;
protected readonly IEventsDataEncoderParams encoderParams;
public EventsGenerator()
{
data = new EventsData();
encoderParams = (IEventsDataEncoderParams)(encoder = new EventsDataEncoder());
}
public virtual void SetCost(string s)
{
data.Cost = encoder.Encode(s);
}
public virtual void SetEventID(string s)
{
data.EventID = encoder.Encode(s);
}
public virtual void SetLang(string s)
{
data.Lang = encoder.Encode(s);
}
public virtual void SetUsername(string s)
{
data.Username = encoder.Encode(s);
}
public virtual void SetExtraInfo(string s)
{
data.ExtraInfo = encoder.Encode(s);
}
public virtual string Generate()
{
Dictionary<FieldNames, string> obj = new Dictionary<FieldNames, string>
{
{
FieldNames.UserName,
data.Username
},
{
FieldNames.Cost,
data.Cost
},
{
FieldNames.EventID,
data.EventID
},
{
FieldNames.Lang,
data.Lang
},
{
FieldNames.ExtraInfo,
data.ExtraInfo
}
};
StringBuilder stringBuilder = new StringBuilder(obj.Count);
string clientAppSep = encoderParams.ClientAppSep;
string clientAppEqual = encoderParams.ClientAppEqual;
bool flag = true;
foreach (KeyValuePair<FieldNames, string> item in obj)
{
if (flag)
{
stringBuilder.Append($"{item.Key}{clientAppEqual}{item.Value}");
flag = false;
continue;
}
stringBuilder.Append($"{clientAppSep}{item.Key}{clientAppEqual}{item.Value}");
}
data = new EventsData();
return stringBuilder.ToString();
}
}
public class EventsReaderOnKey : EventsReader, IEventsReaderOnKey, IEventsReader
{
protected readonly Action<IEventsData> processEvent;
protected readonly IEventsDataParser parser;
public EventsReaderOnKey(Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> logError = null)
: base(log, logError)
{
this.processEvent = processEvent;
this.parser = parser;
}
protected virtual void ProcessOnKey(string[] events)
{
if (events == null || events.Length == 0)
{
return;
}
foreach (IEventsData item in events.Select((string item) => parser?.ParseEvent(item)))
{
try
{
ReaderLog($"StartProcessOnKey {item}");
processEvent?.Invoke(item);
}
catch (Exception arg)
{
ReaderLogError($"StartProcessOnKey error: {arg}");
}
}
}
public virtual void ProcessAllOnKey(string[] events)
{
try
{
ProcessOnKey(events);
}
catch (Exception arg)
{
ReaderLogError($"ProcessAllOnKey error: {arg}");
}
}
public virtual void ReadAndProcessAllOnKey(string path, bool isClearFile = true)
{
ProcessAllOnKey(ReadAll(path, isClearFile));
}
}
public class EventsReaderOnFrame : EventsReader, IEventsReaderOnFrame, IEventsReader
{
protected bool isFirstRun = true;
protected readonly float delay;
protected float delayCounter;
protected float initDelay;
protected float initCounter;
protected readonly float checkPeriod;
protected float periodCounter;
protected readonly Action<IEventsData> processEvent;
protected readonly IEventsDataParser parser;
protected IEnumerator<IEventsData> eventsData;
protected readonly string path;
private bool isDelayEveryProcessing;
public bool IsDelayEveryProcessing
{
get
{
return isDelayEveryProcessing;
}
set
{
isDelayEveryProcessing = value;
}
}
protected virtual void StartProcessOnFrame()
{
while (eventsData.MoveNext())
{
try
{
ReaderLog($"StartProcessOnFrame {eventsData.Current}");
processEvent?.Invoke(eventsData.Current);
}
catch (Exception arg)
{
ReaderLogError($"StartProcessOnFrame error: {arg}");
}
}
eventsData = null;
}
protected virtual void StartProcessWithDelayOnFrame()
{
if (eventsData.MoveNext())
{
try
{
ReaderLog($"StartProcessWithDelayOnFrame {eventsData.Current}");
processEvent?.Invoke(eventsData.Current);
return;
}
catch (Exception arg)
{
ReaderLogError($"StartProcessWithDelayOnFrame error: {arg}");
return;
}
}
isFirstRun = false;
eventsData = null;
ReaderLog("StartProcessWithDelayOnFrame end");
}
public EventsReaderOnFrame(string path, Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> errorLog = null, float checkPeriod = 2f, float delay = 1f, float initDelay = 0.5f)
: base(log, errorLog)
{
this.processEvent = processEvent;
this.parser = parser;
this.delay = delay;
this.initDelay = initDelay;
this.path = path;
this.checkPeriod = checkPeriod;
}
public virtual void SetEventsToProcess(string[] events)
{
try
{
if (events == null || events.Length == 0)
{
eventsData = null;
return;
}
ReaderLog($"SetEventsToProcess read {events.Length} events");
eventsData = events.Select((string item) => parser?.ParseEvent(item))?.GetEnumerator();
}
catch (Exception arg)
{
ReaderLogError($"SetEventsToProcess error: {arg}");
}
}
public virtual bool IsProcessEnd()
{
return eventsData == null;
}
public virtual void ProcessAllWithDelayOnFrame(float dt)
{
if (IsProcessEnd())
{
return;
}
try
{
if (isDelayEveryProcessing || isFirstRun)
{
if (initDelay != 0f)
{
initCounter += dt;
if (initCounter >= initDelay)
{
initCounter = 0f;
initDelay = 0f;
StartProcessWithDelayOnFrame();
}
}
else
{
delayCounter += dt;
if (delayCounter >= delay)
{
delayCounter = 0f;
StartProcessWithDelayOnFrame();
}
}
}
else
{
StartProcessOnFrame();
}
}
catch (Exception arg)
{
ReaderLogError($"ProcessAllWithDelay error: {arg}");
}
}
public virtual void ReadAndProcessAllWithDelayOnFrame(float dt)
{
if (IsProcessEnd())
{
periodCounter += dt;
if (periodCounter >= checkPeriod)
{
periodCounter = 0f;
string[] eventsToProcess = ReadAll(path);
SetEventsToProcess(eventsToProcess);
}
}
ProcessAllWithDelayOnFrame(dt);
}
}
public class EventsReader : IEventsReader
{
protected readonly Action<string> log;
protected readonly Action<string> logError;
public EventsReader(Action<string> log = null, Action<string> logError = null)
{
this.log = log;
this.logError = logError;
}
protected virtual void ReaderLog(string s)
{
log?.Invoke(s);
}
protected virtual void ReaderLogError(string s)
{
logError?.Invoke(s);
}
public virtual string[] ReadAllUnsafe(string path, bool isClearFile = true)
{
using FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
using StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8);
char[] separator = new char[2] { '\r', '\n' };
string[] array = streamReader.ReadToEnd().Split(separator, StringSplitOptions.RemoveEmptyEntries);
if (isClearFile && array != null && array.Length >= 1)
{
fileStream.SetLength(0L);
}
return array;
}
public virtual string[] ReadAll(string path, bool isClearFile = true)
{
try
{
return ReadAllUnsafe(path, isClearFile);
}
catch (FileNotFoundException)
{
}
catch (DirectoryNotFoundException)
{
}
catch (Exception arg)
{
ReaderLogError($"read event error: {arg}");
}
return null;
}
}
}
namespace EventsIO.Interfaces
{
public interface IEventsData
{
string Username { get; }
string Cost { get; }
string EventID { get; }
string Lang { get; }
string ExtraInfo { get; }
}
public interface IEventsDataEncoderParams
{
string ClientAppSep { get; }
char ClientAppSepChar { get; }
string ClientAppEqual { get; }
char ClientAppEqualChar { get; }
}
public interface IEventsDataEncoder
{
string Encode(string s);
string Decode(string s);
}
public interface IEventsDataParser
{
IEventsData ParseEvent(string s);
}
public interface IEventsGenerator
{
void SetUsername(string s);
void SetEventID(string s);
void SetCost(string s);
void SetLang(string s);
void SetExtraInfo(string s);
string Generate();
}
public interface IEventsReaderOnKey : IEventsReader
{
void ProcessAllOnKey(string[] events);
void ReadAndProcessAllOnKey(string path, bool isClearFile = true);
}
public interface IEventsReaderOnFrame : IEventsReader
{
void SetEventsToProcess(string[] events);
bool IsProcessEnd();
void ProcessAllWithDelayOnFrame(float dt);
void ReadAndProcessAllWithDelayOnFrame(float dt);
}
public interface IEventsReader
{
string[] ReadAll(string path, bool isClearFile = true);
}
}using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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.Text;
using BepInEx;
using BepInEx.Logging;
using EventsIO;
using EventsIO.Interfaces;
using HarmonyLib;
using ModHelper;
using ModHelper.Interfaces;
using ModHelperUnity;
using ModHelperUnity.Interfaces;
using ModHelperUnity.UtilityGUI;
using RoR2;
using RoR2.CharacterAI;
using RoR2.ConVar;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using WebSocketIO;
using ror2_interactive_mod.Commands;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ror2_interactive_mod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ror2_interactive_mod")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("0fdefecb-0e54-4f2d-90d1-44b98749c3df")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ror2_interactive_mod
{
internal class HelperUnit
{
public static void SpawnUnit(Vector3 pos, GameObject unitPrefab, EliteIndex eliteIndex, TeamIndex teamIndex = 2, bool braindead = false)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: 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_001f: 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_002c: Invalid comparison between Unknown and I4
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Invalid comparison between Unknown and I4
//IL_022e: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Invalid comparison between Unknown and I4
//IL_023d: 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)
try
{
GameObject val = Object.Instantiate<GameObject>(unitPrefab, pos, Quaternion.identity);
CharacterMaster component = val.GetComponent<CharacterMaster>();
NetworkServer.Spawn(val);
component.SpawnBody(pos, Quaternion.identity);
if ((int)eliteIndex != -1)
{
component.inventory.SetEquipmentIndex(EliteCatalog.GetEliteDef(eliteIndex).eliteEquipmentDef.equipmentIndex);
EliteTierDef tierDef = Tools.GetTierDef(eliteIndex);
if (tierDef != null && tierDef.eliteTypes?.Length > 0)
{
EliteDef val2 = tierDef.eliteTypes[0];
float num = (val2?.healthBoostCoefficient ?? 1f) * 10f;
Tools.Logger.LogDebugInfo((object)$"healthBoostCoefficient {val2?.healthBoostCoefficient}");
component.inventory.GiveItem(Items.BoostHp, Mathf.RoundToInt(num));
num = (val2?.damageBoostCoefficient ?? 1f) * 10f;
Tools.Logger.LogDebugInfo((object)$"damageBoostCoefficient {val2?.damageBoostCoefficient}");
component.inventory.GiveItem(Items.BoostDamage, Mathf.RoundToInt(num));
}
}
GameObject bodyObject = component.GetBodyObject();
DeathRewards val3 = bodyObject.GetComponent<DeathRewards>();
if ((Object)(object)val3 == (Object)null)
{
Tools.Log("add rewards");
val3 = bodyObject.AddComponent<DeathRewards>();
}
val3.expReward = (uint)(0.4f * Run.instance.compensatedDifficultyCoefficient);
if (val3.expReward < 3)
{
val3.expReward = 3u;
}
val3.goldReward = (uint)(0.8f * Run.instance.compensatedDifficultyCoefficient);
if (val3.goldReward < 3)
{
val3.goldReward = 3u;
}
if (braindead)
{
Object.Destroy((Object)(object)((Component)component).GetComponent<BaseAI>());
}
if ((int)teamIndex >= -1 && (int)teamIndex < 5)
{
component.teamIndex = teamIndex;
component.GetBody().teamComponent.teamIndex = teamIndex;
}
}
catch (Exception arg)
{
Tools.Log($"SpawnUnit error: {arg}");
}
}
public static string GetBodyName(string name)
{
if (name == null)
{
Tools.Log("GetBodyName error: incorrect name " + name);
return string.Empty;
}
try
{
int num = 0;
foreach (CharacterBody allBodyPrefabBodyBodyComponent in BodyCatalog.allBodyPrefabBodyBodyComponents)
{
if ((Object)(object)allBodyPrefabBodyBodyComponent == (Object)null || ((Object)allBodyPrefabBodyBodyComponent).name == null)
{
num++;
continue;
}
if ((int.TryParse(name, out var result) && num == result) || ((Object)allBodyPrefabBodyBodyComponent).name.Equals(name, StringComparison.InvariantCultureIgnoreCase) || ((Object)allBodyPrefabBodyBodyComponent).name.ToLower().Replace("body", string.Empty).Equals(name, StringComparison.InvariantCultureIgnoreCase))
{
return ((Object)allBodyPrefabBodyBodyComponent).name;
}
num++;
}
}
catch (Exception arg)
{
Tools.Log($"GetBodyName error: {arg}");
}
return string.Empty;
}
public static string GetMasterName(string name)
{
if (name == null)
{
Tools.Log("GetMasterName error: incorrect name");
return string.Empty;
}
try
{
int num = 0;
IEnumerable<CharacterMaster> allAiMasters = MasterCatalog.allAiMasters;
if (allAiMasters == null)
{
Tools.Log("GetMasterName error: MasterCatalog.allAiMasters");
return string.Empty;
}
foreach (CharacterMaster item in allAiMasters)
{
if ((Object)(object)item == (Object)null || ((Object)item).name == null)
{
num++;
continue;
}
if ((int.TryParse(name, out var result) && num == result) || ((Object)item).name.Equals(name, StringComparison.InvariantCultureIgnoreCase) || ((Object)item).name.ToLower().Replace("master", string.Empty).Equals(name, StringComparison.InvariantCultureIgnoreCase))
{
return ((Object)item).name;
}
num++;
}
}
catch (Exception arg)
{
Tools.Log($"GetMasterName error: {arg}");
}
return string.Empty;
}
}
public class HelperEquip
{
public static EquipmentIndex GetEquipFromString(string name)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: 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_0025: Unknown result type (might be due to invalid IL or missing references)
try
{
return EquipmentCatalog.FindEquipmentIndex(name);
}
catch (Exception arg)
{
Tools.Log($"GetEquipFromString error: {arg}");
}
return (EquipmentIndex)(-1);
}
public static ItemIndex GetItemFromString(string name)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: 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_0025: Unknown result type (might be due to invalid IL or missing references)
try
{
return ItemCatalog.FindItemIndex(name);
}
catch (Exception arg)
{
Tools.Log($"GetItemFromString error: {arg}");
}
return (ItemIndex)(-1);
}
}
public class InteractiveMod
{
private WebSocketEventsReader<SettingsData> eventsReader;
private IEventsReaderOnKey eventsReaderByKey;
private IEventsDataParser eventsParser;
private ICommandManager commandManager;
private ITranslation translateManager;
private IComponentTypedNotify notifyManager;
private string keyEventsPath;
private bool isNeedFirstInit = true;
private bool isQuiting;
private GameObject gameObject;
private Dictionary<string, ICommandExecutor> commandsDict;
private float firstDelay = 4f;
public InteractiveMod(BepInExPlugin plugin)
{
gameObject = ((Component)plugin).gameObject;
}
public void Awake()
{
Tools.Log("InteractiveMod Awake");
MainPatcher.InitPatch();
}
public void OnDestroy()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
Tools.Log("InteractiveMod OnDestroy");
if (!isQuiting)
{
Tools.Log("InteractiveMod reinit mod script");
GameObject val = new GameObject();
val.AddComponent(typeof(InteractiveMod));
val.SetActive(true);
Loader.HookObj = val;
}
}
public void OnApplicationQuit()
{
Tools.Log("InteractiveMod OnApplicationQuit");
isQuiting = true;
}
public void InitCommandsWithNotify()
{
commandsDict = new Dictionary<string, ICommandExecutor>
{
{
"spawn_as",
new CommandChangeBody()
},
{
"give_equip",
new CommandGiveEquip()
},
{
"give_item",
new CommandGiveItem()
},
{
"kill_all",
new CommandKillAll()
},
{
"remove_item",
new CommandRemoveItem()
},
{
"spawn_ai",
new CommandSpawnAI()
},
{
"give_item_or_equip",
new CommandGiveItemOrEquip()
}
};
}
private string GetBasePath(string filename)
{
return Path.Combine(UtilitySettings.BaseFolder, filename);
}
public void InitCommands()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
Tools.Log("init HelperCommandManager");
commandManager = (ICommandManager)new HelperCommandManagerFormatted(Tools.Logger);
commandManager.InitFromFile(GetBasePath("commands.data"));
Tools.Log("init HelperLanguages");
translateManager = (ITranslation)new HelperLanguagesFormatted(Tools.Logger);
translateManager.InitFromFile(GetBasePath("langs.data"));
InitCommandsWithNotify();
}
public void Start()
{
Tools.Log("InteractiveMod OnStart");
}
public void FirstInit()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Expected O, but got Unknown
Tools.Log("FirstInit");
eventsParser = (IEventsDataParser)new EventsDataParser((Action<string>)Tools.Log);
Tools.Log("init EventsReaderOnFrame");
if (eventsReader == null)
{
eventsReader = new WebSocketEventsReader<SettingsData>((Action<IEventsData>)ProcessEvent, eventsParser, (Action<string>)Tools.Log, (Action<string>)Tools.Log, 1f, 1f, 0.5f);
eventsReader.InitDefaultSocket(UtilitySettings.BaseFolder, "chaostricks_ror2", 13715, "127.0.0.1");
eventsReader.OpenSocket(true);
}
Tools.Log("init EventsReaderOnKey");
keyEventsPath = GetBasePath("events_key.txt");
eventsReaderByKey = (IEventsReaderOnKey)new EventsReaderOnKey((Action<IEventsData>)ProcessEvent, eventsParser, (Action<string>)Tools.Log, (Action<string>)null);
InitCommands();
if (notifyManager == null)
{
notifyManager = (IComponentTypedNotify)(object)gameObject.AddComponent<TypedNotifyOnGUI>();
}
IComponentTypedNotify obj = notifyManager;
if (obj != null)
{
obj.PostInit(UtilitySettings.BaseFolder, Tools.Logger, (Func<string, byte[]>)null);
}
SettingsManager.LoadSettings();
Tools.Log("InteractiveMod init ended (1.0.0)");
}
private bool ExecuteCommandOnePlayer(ICommandExecutor command, ConCommandArgs args)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
Tools.Log("run command for single player");
args.sender = NetworkUser.readOnlyLocalPlayersList[0];
try
{
command.Execute(args);
return true;
}
catch (Exception arg)
{
Tools.Log($"command run error: {arg}");
return false;
}
}
private bool ExecuteCommandAllPlayers(ICommandExecutor command, ConCommandArgs args)
{
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
if (SettingsManager.Data.isAllPlayers)
{
bool result = true;
foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
{
try
{
Tools.Log("run command for player " + readOnlyInstances?.userName);
args.sender = readOnlyInstances;
command.Execute(args);
}
catch (Exception arg)
{
Tools.Log($"run command for player {readOnlyInstances?.userName} error: {arg}");
result = false;
}
}
return result;
}
return ExecuteCommandOnePlayer(command, args);
}
private bool ExecuteCommand(ICommandExecutor command, string[] args)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
Tools.EnableCheats();
Tools.Log("command: '" + ((ICommand)command).Id + "'");
ConCommandArgs args2 = default(ConCommandArgs);
List<string> list = new List<string>(args);
list.RemoveAt(0);
args2.userArgs = list;
if (command is ICommandTargets)
{
return ExecuteCommandAllPlayers(command, args2);
}
return ExecuteCommandOnePlayer(command, args2);
}
private void ProcessEvent(IEventsData data)
{
string eventID = data.EventID;
if (string.IsNullOrWhiteSpace(eventID))
{
return;
}
if (eventID == UtilitySettings.CommandUpdateSettingsID)
{
SettingsManager.LoadSettings();
Tools.Log("settings reloaded");
return;
}
Tools.Log("try to execute event: '" + eventID + "'");
string text = string.Empty;
string commandData = commandManager.GetCommandData(eventID, true);
string[] array = commandData.Split();
if (array.Length != 0)
{
text = array[0].Trim();
}
if (commandsDict.TryGetValue(text, out var value))
{
if (!ExecuteCommand(value, array))
{
Tools.Log("event '" + eventID + "' executing is failed");
}
}
else
{
Tools.Log("command not found " + text);
}
Tools.Log("event '" + eventID + "' executing is completed");
ICommandNotify val = (ICommandNotify)((value is ICommandNotify) ? value : null);
if (val != null)
{
IComponentTypedNotify obj = notifyManager;
if (obj != null)
{
obj.AddNotifyToQueue(data, translateManager, (Func<string, string>)val.ProcessMsg);
}
}
else
{
IComponentTypedNotify obj2 = notifyManager;
if (obj2 != null)
{
obj2.AddNotifyToQueue(data, translateManager, (Func<string, string>)null);
}
}
}
public bool IsAllPlayersDeadAndNoLifes(IReadOnlyCollection<NetworkUser> list)
{
if (list == null)
{
return true;
}
foreach (NetworkUser item in list)
{
if (item != null)
{
CharacterMaster master = item.master;
if (((master != null) ? new bool?(master.IsDeadAndOutOfLivesServer()) : null) == false)
{
return false;
}
}
}
return true;
}
public bool IsNotReadyForCheckEvent()
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
int num = NetworkUser.readOnlyLocalPlayersList?.Count ?? 0;
if (num <= 0)
{
return true;
}
ReadOnlyCollection<NetworkUser> readOnlyInstancesList = NetworkUser.readOnlyInstancesList;
if (readOnlyInstancesList != null && readOnlyInstancesList.Count > 1)
{
if (IsAllPlayersDeadAndNoLifes(NetworkUser.readOnlyInstancesList))
{
return true;
}
}
else if (IsAllPlayersDeadAndNoLifes(NetworkUser.readOnlyLocalPlayersList))
{
return true;
}
Scene activeScene = SceneManager.GetActiveScene();
string text = ((Scene)(ref activeScene)).name?.ToLower();
return "intro" == text || "title" == text || "lobby" == text || MasterCatalog.allAiMasters == null;
}
public void Update()
{
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
if (Input.GetKeyDown((KeyCode)278))
{
InitCommands();
}
if (IsNotReadyForCheckEvent())
{
return;
}
if (isNeedFirstInit)
{
FirstInit();
isNeedFirstInit = false;
}
firstDelay -= Time.deltaTime;
if (firstDelay > 0f)
{
return;
}
if (Input.GetKey((KeyCode)306) && Input.GetKeyDown((KeyCode)261))
{
eventsReaderByKey.ReadAndProcessAllOnKey(keyEventsPath, false);
}
if (Input.GetKey((KeyCode)306) && Input.GetKeyDown((KeyCode)112))
{
try
{
NetworkUser val = NetworkUser.readOnlyLocalPlayersList[0];
CharacterBody body = val.master.GetBody();
if (Object.op_Implicit((Object)(object)((body != null) ? body.healthComponent : null)))
{
body.healthComponent.Suicide((GameObject)null, (GameObject)null, default(DamageTypeCombo));
}
}
catch (Exception arg)
{
((ILogger)Tools.Logger).Log((object)$"Selfkill error: {arg}");
}
}
((EventsReaderOnFrame)eventsReader).ReadAndProcessAllWithDelayOnFrame(Time.deltaTime);
}
}
internal interface ICommandExecutor : ICommand
{
void Execute(ConCommandArgs args);
}
public class MainPatcher
{
public static void InitPatch()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
try
{
((ILogger)Tools.Logger).Log((object)"HelperPatcher init");
Harmony val = new Harmony("com.Loki.patch");
val.PatchAll();
}
catch (Exception arg)
{
((ILogger)Tools.Logger).Log((object)$"HelperPatcher error: {arg}");
}
}
}
public class SettingsData
{
public bool isAllPlayers = true;
}
public class SettingsManager
{
private static SettingsData data = new SettingsData();
public static SettingsData Data => data;
public static void LoadSettings()
{
try
{
SettingsData settingsData = UtilitySettings.LoadSettings<SettingsData>(Tools.Logger);
if (settingsData != null)
{
data = settingsData;
}
else
{
Tools.Log("LoadSettings using default.");
}
}
catch (Exception arg)
{
Tools.Log($"LoadSettings error: {arg}");
}
}
}
[BepInPlugin("bft.chaostricks", "Chaos Tricks", "1.0.0")]
public class BepInExPlugin : BaseUnityPlugin
{
private ManualLogSource loggerHook;
private InteractiveMod mod;
public const string pluginGuid = "bft.chaostricks";
public const string pluginName = "Chaos Tricks";
public const string pluginVersion = "1.0.0";
public void Awake()
{
loggerHook = ((BaseUnityPlugin)this).Logger;
try
{
UtilitySettings.BaseFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
((ILogger)Tools.Logger).LogClear();
}
catch (Exception ex)
{
ManualLogSource obj = loggerHook;
if (obj != null)
{
obj.LogError((object)ex);
}
}
mod = new InteractiveMod(this);
mod.Awake();
((BaseUnityPlugin)this).Logger.LogInfo((object)"plugin init finished");
}
public void OnDestroy()
{
mod?.OnDestroy();
}
public void Start()
{
mod?.Start();
}
public void Update()
{
mod?.Update();
}
}
public static class Tools
{
private static readonly Lazy<IDebugLogger> instance;
public static IDebugLogger Logger => instance.Value;
public static IParseManager ParseManager { get; }
static Tools()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
instance = new Lazy<IDebugLogger>((Func<IDebugLogger>)(() => (IDebugLogger)new BufferedLogger(UtilitySettings.BaseFolder, "interactive_mod_log.txt", true, 50)));
ParseManager = (IParseManager)new HelperParse((ILogger)(object)Logger);
}
public static void Log(string text)
{
((ILogger)Logger).Log((object)text);
}
public static bool EnableCheats()
{
try
{
if (CheatsConVar.instance.boolValue)
{
return true;
}
Log("try to enable cheats");
Type type = ((object)CheatsConVar.instance).GetType();
if (type == null)
{
Log("can't get type");
return false;
}
FieldInfo field = type.GetField("_boolValue", BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
{
Log("can't get field1");
return false;
}
field.SetValue(CheatsConVar.instance, true);
((BaseConVar)CheatsConVar.instance).SetString("1");
return CheatsConVar.instance.boolValue;
}
catch (Exception arg)
{
Log($"cheats enable error: {arg}");
}
return false;
}
public static EliteTierDef GetTierDef(EliteIndex index)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Invalid comparison between Unknown and I4
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Invalid comparison between Unknown and I4
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
try
{
object value = typeof(CombatDirector).GetField("eliteTiers").GetValue(null);
EliteTierDef[] array = (EliteTierDef[])value;
if (array == null)
{
Log("GetTierDef error: can't get tiers");
return null;
}
if ((int)index <= -1 || (int)index >= EliteCatalog.eliteList.Count)
{
Log("GetTierDef error: index out");
return null;
}
int num = 0;
for (int i = 0; i < array.Length; i++)
{
for (int j = 0; j < array[i].eliteTypes.Length; j++)
{
if (array[i].eliteTypes[j].eliteIndex == index)
{
num = i;
break;
}
}
}
return array[num];
}
catch (Exception arg)
{
Log($"GetTierDef error: {arg}");
return null;
}
}
public static List<string> GetItemsFromFileByListName(string listName, bool isCreateFileIfNotExist = true)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
string text = null;
try
{
text = Path.Combine(UtilitySettings.BaseFolder, listName + ".data");
HelperJson val = new HelperJson(Logger, false);
List<string> list = val.FromFile<List<string>>(text);
if (list == null)
{
list = new List<string>();
}
Log($"Items from file: found {listName} {list.Count}");
foreach (string item in list)
{
Log("found value: " + item);
}
return list;
}
catch (FileNotFoundException)
{
if (isCreateFileIfNotExist)
{
try
{
File.Create(text);
}
catch (Exception arg)
{
Log($"Items from file: create file error {arg}");
}
}
}
catch (Exception arg2)
{
Log($"Items from file: load error {arg2}");
}
return new List<string>();
}
private static string GetTabs(string text, int stringMaxLength)
{
return new string(' ', stringMaxLength - text.Length + 4);
}
public static void DebugPrintPrefabs()
{
//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_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: 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_002e: 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_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0322: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Items:");
GenericStaticEnumerable<ItemIndex, AllItemsEnumerator> allItems = ItemCatalog.allItems;
AllItemsEnumerator enumerator = allItems.GetEnumerator();
try
{
while (((AllItemsEnumerator)(ref enumerator)).MoveNext())
{
ItemIndex current = ((AllItemsEnumerator)(ref enumerator)).Current;
ItemDef itemDef = ItemCatalog.GetItemDef(current);
string localizedStringByToken = Language.currentLanguage.GetLocalizedStringByToken(itemDef.nameToken);
string tabs = GetTabs(((object)(ItemIndex)(ref current)).ToString(), 3);
string tabs2 = GetTabs(((Object)itemDef).name, 25);
stringBuilder.AppendLine($"Item: index {current}{tabs}prefabName {((Object)itemDef).name}{tabs2}gameName {localizedStringByToken}");
}
}
finally
{
((IDisposable)(AllItemsEnumerator)(ref enumerator)).Dispose();
}
stringBuilder.AppendLine("\n---------------\nEquipments:");
GenericStaticEnumerable<EquipmentIndex, AllEquipmentEnumerator> allEquipment = EquipmentCatalog.allEquipment;
AllEquipmentEnumerator enumerator2 = allEquipment.GetEnumerator();
try
{
while (((AllEquipmentEnumerator)(ref enumerator2)).MoveNext())
{
EquipmentIndex current2 = ((AllEquipmentEnumerator)(ref enumerator2)).Current;
EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(current2);
string localizedStringByToken2 = Language.currentLanguage.GetLocalizedStringByToken(equipmentDef.nameToken);
string tabs3 = GetTabs(((object)(EquipmentIndex)(ref current2)).ToString(), 3);
string tabs4 = GetTabs(((Object)equipmentDef).name, 20);
stringBuilder.AppendLine($"Equipment: index {current2}{tabs3}prefabName {((Object)equipmentDef).name}{tabs4}name {localizedStringByToken2}");
}
}
finally
{
((IDisposable)(AllEquipmentEnumerator)(ref enumerator2)).Dispose();
}
stringBuilder.AppendLine("\n---------------\nMasters:");
foreach (CharacterMaster allMaster in MasterCatalog.allMasters)
{
string tabs5 = GetTabs(((Object)allMaster.bodyPrefab).name, 22);
stringBuilder.AppendLine("nMasters: bodyName " + ((Object)allMaster.bodyPrefab).name + tabs5 + "prefabName " + ((Object)allMaster).name);
}
stringBuilder.AppendLine("\n---------------\nMasters AI:");
foreach (CharacterMaster allAiMaster in MasterCatalog.allAiMasters)
{
string tabs6 = GetTabs(((Object)allAiMaster.bodyPrefab).name, 22);
stringBuilder.AppendLine("Masters AI: index " + ((Object)allAiMaster.bodyPrefab).name + tabs6 + "prefabName " + ((Object)allAiMaster).name);
}
stringBuilder.AppendLine("\n---------------\nBody models:");
foreach (CharacterBody allBodyPrefabBodyBodyComponent in BodyCatalog.allBodyPrefabBodyBodyComponents)
{
string bodyName = HelperUnit.GetBodyName(((Object)allBodyPrefabBodyBodyComponent).name);
string tabs7 = GetTabs(((object)(BodyIndex)(ref allBodyPrefabBodyBodyComponent.bodyIndex)).ToString(), 3);
string tabs8 = GetTabs(((Object)allBodyPrefabBodyBodyComponent).name, 28);
stringBuilder.AppendLine($"Equipment: index {allBodyPrefabBodyBodyComponent.bodyIndex}{tabs7}prefabName {((Object)allBodyPrefabBodyBodyComponent).name}{tabs8}{bodyName}");
}
Log(stringBuilder.ToString());
}
}
}
namespace ror2_interactive_mod.Commands
{
public class CommandGiveItemOrEquip : ICommandExecutor, ICommand, ICommandNotify, ICommandTargets
{
public const string name = "give_item_or_equip";
private const string itemsRandomName = "RandomBlue";
private readonly List<string> itemsRandom;
private EquipmentIndex lastEquip;
private ItemIndex lastItem;
private bool lastIsItem;
public string Id => "give_item_or_equip";
public bool IsAllPlayers { get; set; } = true;
public CommandGiveItemOrEquip()
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Invalid comparison between Unknown and I4
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Invalid comparison between Unknown and I4
itemsRandom = Tools.GetItemsFromFileByListName("RandomBlue");
for (int num = itemsRandom.Count - 1; num >= 0; num--)
{
string text = itemsRandom[num];
if ((int)HelperEquip.GetEquipFromString(text) == -1 && (int)HelperEquip.GetItemFromString(text) == -1)
{
Tools.Log("Command give_item_or_equip error: missed equip or item - " + text + " in category RandomBlue");
itemsRandom.RemoveAt(num);
}
}
}
public string ProcessMsg(string msg)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
try
{
string text = ((!lastIsItem) ? EquipmentCatalog.GetEquipmentDef(lastEquip).nameToken : ItemCatalog.GetItemDef(lastItem).nameToken);
string localizedStringByToken = Language.currentLanguage.GetLocalizedStringByToken(text);
msg = msg.Replace("%value%", localizedStringByToken);
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} process msg error: {1}", "give_item_or_equip", arg));
}
return msg;
}
public void Execute(ConCommandArgs args)
{
//IL_0023: 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_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Invalid comparison between Unknown and I4
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Invalid comparison between Unknown and I4
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
try
{
if (((ConCommandArgs)(ref args)).Count < 1)
{
Tools.Log("Command give_item_or_equip wrong args count");
return;
}
NetworkUser sender = args.sender;
if ((Object)(object)sender == (Object)null)
{
Tools.Log("Command give_item_or_equip, error: player not found");
return;
}
NetworkUser sender2 = args.sender;
Inventory val = ((sender2 != null) ? sender2.master.inventory : null);
if ((Object)(object)val == (Object)null)
{
Tools.Log("Command give_item_or_equip, error: inventory not found");
return;
}
string text = ((ConCommandArgs)(ref args))[0];
string text2 = ((!text.Equals("RandomBlue", StringComparison.InvariantCultureIgnoreCase)) ? text : UtilityRandom.GetRandomItemFromList<string>((IList<string>)itemsRandom));
lastItem = (ItemIndex)(-1);
lastEquip = HelperEquip.GetEquipFromString(text2);
if ((int)lastEquip != -1)
{
val.SetEquipmentIndex(lastEquip);
lastIsItem = false;
}
else
{
lastItem = HelperEquip.GetItemFromString(text2);
if ((int)lastItem != -1)
{
val.GiveItem(lastItem, 1);
lastIsItem = true;
}
else
{
Tools.Log("Command give_item_or_equip, error: item/equip not found " + ((ConCommandArgs)(ref args))[0] + " : " + text2);
}
}
Tools.Log("Command give_item_or_equip: player " + sender.masterController.GetDisplayName() + " got " + text2);
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} error: {1}", "give_item_or_equip", arg));
}
}
}
public class CommandGiveItem : ICommandExecutor, ICommand, ICommandNotify, ICommandTargets
{
public const string name = "give_item";
private readonly Dictionary<string, List<string>> itemsLists;
private readonly string[] listNames = new string[5] { "RandomWhite", "RandomGreen", "RandomYellow", "RandomRed", "RandomAll" };
private ItemIndex lastItem;
public bool IsAllPlayers { get; set; } = true;
public string Id => "give_item";
public CommandGiveItem()
{
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Invalid comparison between Unknown and I4
itemsLists = new Dictionary<string, List<string>>(listNames.Length);
string[] array = listNames;
foreach (string text in array)
{
List<string> itemsFromFileByListName = Tools.GetItemsFromFileByListName(text);
itemsLists[text] = itemsFromFileByListName;
for (int num = itemsFromFileByListName.Count - 1; num >= 0; num--)
{
string text2 = itemsFromFileByListName[num];
if ((int)HelperEquip.GetItemFromString(text2) == -1)
{
Tools.Log("Command " + Id + " error: missed item - " + text2 + " in category " + text);
itemsFromFileByListName.RemoveAt(num);
}
}
}
}
public string ProcessMsg(string msg)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
try
{
ItemDef itemDef = ItemCatalog.GetItemDef(lastItem);
string localizedStringByToken = Language.currentLanguage.GetLocalizedStringByToken(itemDef.nameToken);
msg = msg.Replace("%value%", localizedStringByToken);
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} process msg error: {1}", "give_item", arg));
}
return msg;
}
public void Execute(ConCommandArgs args)
{
//IL_0023: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Invalid comparison between Unknown and I4
//IL_0100: 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)
try
{
if (((ConCommandArgs)(ref args)).Count < 1)
{
Tools.Log("Command give_item wrong args count");
return;
}
NetworkUser sender = args.sender;
if ((Object)(object)sender == (Object)null)
{
Tools.Log("Command give_item, error: player not found");
return;
}
NetworkUser sender2 = args.sender;
Inventory val = ((sender2 != null) ? sender2.master.inventory : null);
if ((Object)(object)val == (Object)null)
{
Tools.Log("Command give_item, error: inventory not found");
return;
}
if (((ConCommandArgs)(ref args)).Count < 2 || !int.TryParse(((ConCommandArgs)(ref args))[1], out var result))
{
result = 1;
}
string text = ((ConCommandArgs)(ref args))[0];
string text2 = ((!itemsLists.ContainsKey(text)) ? text : UtilityRandom.GetRandomItemFromList<string>((IList<string>)itemsLists[text]));
ItemIndex val2 = (lastItem = HelperEquip.GetItemFromString(text2));
if ((int)val2 != -1)
{
val.GiveItem(val2, result);
Tools.Log(string.Format("Command {0}: player {1} got {2} named {3}", "give_item", sender.masterController.GetDisplayName(), val2, text2));
}
else
{
Tools.Log("Command give_item, error: item " + text2 + " from " + text + " not found");
}
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} error: {1}", "give_item", arg));
}
}
}
public class CommandSpawnAI : ICommandExecutor, ICommand, ICommandNotify, ICommandTargets
{
public const string name = "spawn_ai";
private readonly Dictionary<string, List<string>> enemiesLists;
private readonly string[] listNames = new string[2] { "T1Mobs", "T2Mobs" };
public string Id => "spawn_ai";
public bool IsAllPlayers { get; set; } = true;
public CommandSpawnAI()
{
enemiesLists = new Dictionary<string, List<string>>(listNames.Length);
string[] array = listNames;
foreach (string text in array)
{
List<string> itemsFromFileByListName = Tools.GetItemsFromFileByListName(text);
enemiesLists[text] = itemsFromFileByListName;
for (int num = itemsFromFileByListName.Count - 1; num >= 0; num--)
{
string text2 = itemsFromFileByListName[num];
if ((Object)(object)GetUnitPrefabByName(text2, text) == (Object)null)
{
Tools.Log("Command " + Id + " error: missed enemy - " + text2 + " in category " + text);
itemsFromFileByListName.RemoveAt(num);
}
}
}
}
public string ProcessMsg(string msg)
{
return msg;
}
private GameObject GetUnitPrefabByName(string unitName, string categoryTextLog = null)
{
string text = ((categoryTextLog == null) ? string.Empty : (" in category " + categoryTextLog));
if (string.IsNullOrWhiteSpace(unitName))
{
Tools.Log("Command spawn_ai error: missed mob with name " + unitName + text);
return null;
}
string masterName = HelperUnit.GetMasterName(unitName);
GameObject val = MasterCatalog.FindMasterPrefab(masterName);
if ((Object)(object)val == (Object)null)
{
Tools.Log("Command spawn_ai error: missed prefab for mob " + masterName + " with name " + unitName + text);
return null;
}
return val;
}
private GameObject GetUnitPrefab(string unitCategory)
{
string unitName = ((!enemiesLists.ContainsKey(unitCategory)) ? unitCategory : UtilityRandom.GetRandomItemFromList<string>((IList<string>)enemiesLists[unitCategory]));
return GetUnitPrefabByName(unitName, unitCategory);
}
public void Execute(ConCommandArgs args)
{
//IL_0023: 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_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Unknown result type (might be due to invalid IL or missing references)
//IL_025b: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Unknown result type (might be due to invalid IL or missing references)
//IL_027d: Unknown result type (might be due to invalid IL or missing references)
//IL_0282: Unknown result type (might be due to invalid IL or missing references)
//IL_0286: Unknown result type (might be due to invalid IL or missing references)
//IL_028b: Unknown result type (might be due to invalid IL or missing references)
//IL_0290: Unknown result type (might be due to invalid IL or missing references)
//IL_029c: Unknown result type (might be due to invalid IL or missing references)
//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
try
{
if (((ConCommandArgs)(ref args)).Count < 1)
{
Tools.Log("Command spawn_ai wrong args count");
return;
}
NetworkUser sender = args.sender;
NetworkUser sender2 = args.sender;
Inventory val = ((sender2 != null) ? sender2.master.inventory : null);
if ((Object)(object)sender == (Object)null)
{
Tools.Log("Command spawn_ai, error: player not found");
return;
}
float result = 1f;
if (((ConCommandArgs)(ref args)).Count > 1 && !float.TryParse(((ConCommandArgs)(ref args))[1], out result))
{
Tools.Log("Command spawn_ai can't parse spawn range min offset " + ((ConCommandArgs)(ref args))[1]);
return;
}
float result2 = 2f;
if (((ConCommandArgs)(ref args)).Count > 2 && !float.TryParse(((ConCommandArgs)(ref args))[2], out result2))
{
Tools.Log("Command spawn_ai can't parse spawn range max offset " + ((ConCommandArgs)(ref args))[2]);
return;
}
if (result > result2)
{
Tools.Log(string.Format("Command {0} error: spawn range min offset {1} > max offset {2}", "spawn_ai", result, result2));
return;
}
int result3 = 1;
if (((ConCommandArgs)(ref args)).Count > 3 && !int.TryParse(((ConCommandArgs)(ref args))[3], out result3))
{
Tools.Log("Command spawn_ai can't parse count of unit " + ((ConCommandArgs)(ref args))[3]);
return;
}
if (result3 <= 0)
{
Tools.Log(string.Format("Command {0} error: incorrect count {1}", "spawn_ai", result3));
return;
}
EliteIndex eliteIndex = default(EliteIndex);
if (((ConCommandArgs)(ref args)).Count <= 4 || !Tools.ParseManager.TryParseEnum<EliteIndex>(((ConCommandArgs)(ref args))[4], ref eliteIndex, (EliteIndex)0))
{
eliteIndex = (EliteIndex)(-1);
}
bool braindead = default(bool);
if (((ConCommandArgs)(ref args)).Count <= 5 || !Tools.ParseManager.TryParseBool(((ConCommandArgs)(ref args))[5], ref braindead, false))
{
braindead = false;
}
TeamIndex teamIndex = default(TeamIndex);
if (((ConCommandArgs)(ref args)).Count <= 6 || !Tools.ParseManager.TryParseEnum<TeamIndex>(((ConCommandArgs)(ref args))[6], ref teamIndex, (TeamIndex)0))
{
teamIndex = (TeamIndex)2;
}
string text = ((ConCommandArgs)(ref args))[0];
for (int i = 0; i < result3; i++)
{
Vector3 position = ((Component)sender.master.GetBody()).transform.position;
int num = ((text == "ClayBoss") ? 5 : 2);
Vector3 val2 = position;
float num2 = result;
float num3 = result2;
float num4 = num;
LayerIndex world = LayerIndex.world;
position = MathUtility.FindRandomSpawnPointNearPositionFixY(val2, num2, num3, num4, ((LayerIndex)(ref world)).mask);
GameObject unitPrefab = GetUnitPrefab(text);
HelperUnit.SpawnUnit(position, unitPrefab, eliteIndex, teamIndex, braindead);
Tools.Log("Command spawn_ai spawn " + ((Object)unitPrefab).name);
}
Tools.Log(string.Format("Command {0} total spawns count {1}", "spawn_ai", result3));
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} error: {1}", "spawn_ai", arg));
}
}
}
public class CommandRemoveItem : ICommandExecutor, ICommand, ICommandNotify, ICommandTargets
{
public const string name = "remove_item";
public string Id => "remove_item";
public bool IsAllPlayers { get; set; } = true;
public string ProcessMsg(string msg)
{
return msg;
}
public void Execute(ConCommandArgs args)
{
//IL_0023: 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_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Invalid comparison between Unknown and I4
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
try
{
if (((ConCommandArgs)(ref args)).Count < 1)
{
Tools.Log("Command remove_item wrong args count");
return;
}
NetworkUser sender = args.sender;
if ((Object)(object)sender == (Object)null)
{
Tools.Log("Command remove_item, error: player not found");
return;
}
NetworkUser sender2 = args.sender;
Inventory val = ((sender2 != null) ? sender2.master.inventory : null);
if ((Object)(object)val == (Object)null)
{
Tools.Log("Command remove_item, error: inventory not found");
return;
}
if ("all".Equals(((ConCommandArgs)(ref args))[0], StringComparison.InvariantCultureIgnoreCase))
{
val.CopyItemsFrom(new GameObject().AddComponent<Inventory>());
Tools.Log("Command remove_item: removing inventory");
return;
}
if (((ConCommandArgs)(ref args)).Count < 2)
{
Tools.Log("Command remove_item wrong args count.");
return;
}
ItemIndex itemFromString = HelperEquip.GetItemFromString(((ConCommandArgs)(ref args))[0]);
if ((int)itemFromString != -1)
{
int result;
if ("all".Equals(((ConCommandArgs)(ref args))[1], StringComparison.InvariantCultureIgnoreCase))
{
result = val.GetItemCount(itemFromString);
}
else
{
int.TryParse(((ConCommandArgs)(ref args))[1], out result);
}
if (result > 0)
{
val.RemoveItem(itemFromString, result);
}
Tools.Log(string.Format("Command {0}: removed {1} {2} from {3}", "remove_item", result, itemFromString, sender.masterController.GetDisplayName()));
}
else
{
Tools.Log("Command remove_item: item " + ((ConCommandArgs)(ref args))[0] + " not found");
}
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} error: {1}", "remove_item", arg));
}
}
}
public class CommandKillAll : ICommandExecutor, ICommand, ICommandNotify
{
public const string name = "kill_all";
public string Id => "kill_all";
public string ProcessMsg(string msg)
{
return msg;
}
public void Execute(ConCommandArgs args)
{
//IL_002c: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
try
{
TeamIndex val = default(TeamIndex);
if (((ConCommandArgs)(ref args)).Count == 0 || !Tools.ParseManager.TryParseEnum<TeamIndex>(((ConCommandArgs)(ref args))[0], ref val, (TeamIndex)0))
{
val = (TeamIndex)2;
}
int num = 0;
CharacterMaster[] array = Object.FindObjectsOfType<CharacterMaster>();
foreach (CharacterMaster val2 in array)
{
if (val2.teamIndex == val)
{
CharacterBody val3 = ((val2 != null) ? val2.GetBody() : null);
if (Object.op_Implicit((Object)(object)((val3 != null) ? val3.healthComponent : null)))
{
val3.healthComponent.Suicide((GameObject)null, (GameObject)null, default(DamageTypeCombo));
num++;
}
}
}
Tools.Log(string.Format("Command {0}: killed {1} of team {2}", "kill_all", num, val));
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} error: {1}", "kill_all", arg));
}
}
}
public class CommandChangeBody : ICommandExecutor, ICommand, ICommandNotify, ICommandTargets
{
public const string name = "spawn_as";
private string lastMasterBodyName;
private readonly List<string> bodyRandom;
private const string bodyRandomName = "RandomBody";
public string Id => "spawn_as";
public bool IsAllPlayers { get; set; } = true;
public CommandChangeBody()
{
bodyRandom = Tools.GetItemsFromFileByListName("RandomBody");
}
public string ProcessMsg(string msg)
{
try
{
msg = msg.Replace("%value%", lastMasterBodyName);
Tools.Log("trans " + lastMasterBodyName);
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} process msg error: {1}", "spawn_as", arg));
}
return msg;
}
private void Respawn(CharacterMaster master)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
master.Respawn(((Component)master.GetBody()).transform.position, ((Component)master.GetBody()).transform.rotation, false);
}
public void Execute(ConCommandArgs args)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Expected O, but got Unknown
try
{
if (((ConCommandArgs)(ref args)).Count < 1)
{
Tools.Log("Command spawn_as wrong args count");
return;
}
NetworkUser sender = args.sender;
if ((Object)(object)sender == (Object)null)
{
Tools.Log("Command spawn_as, error: player not found");
return;
}
CharacterMaster master = sender.master;
if (!Object.op_Implicit((Object)(object)master.GetBody()))
{
Tools.Log("Command spawn_as, error: can't find player body. Probably player despawned.");
return;
}
string text = ((ConCommandArgs)(ref args))[0];
string currentName = ((Object)sender.master.GetBody()).name;
int num = currentName.IndexOf("(");
if (num != -1)
{
currentName = currentName.Substring(0, num);
}
currentName = HelperUnit.GetBodyName(currentName);
Tools.Log("current body base " + ((Object)sender.master.GetBody()).name + ", processed " + currentName);
if (text.Equals("RandomBody", StringComparison.InvariantCultureIgnoreCase))
{
List<string> list = bodyRandom.Where((string name) => !string.Equals(HelperUnit.GetBodyName(name), currentName, StringComparison.OrdinalIgnoreCase)).ToList();
text = UtilityRandom.GetRandomItemFromList<string>((IList<string>)list);
}
text = HelperUnit.GetBodyName(text);
if (string.IsNullOrWhiteSpace(text))
{
Tools.Log("Command spawn_as, error: can't find body index " + text);
return;
}
GameObject bodyPrefab = BodyCatalog.FindBodyPrefab(text);
master.bodyPrefab = bodyPrefab;
Tools.Log("Command spawn_as: " + sender.userName + " is spawning as " + text);
BoolConVar val = (BoolConVar)(typeof(Stage).GetField("stage1PodConVar")?.GetValue(null));
if (val != null)
{
bool value = val.value;
val.SetBool(false);
Respawn(master);
val.SetBool(value);
}
else
{
Respawn(master);
}
lastMasterBodyName = master.GetBody().GetDisplayName();
Tools.Log("Command spawn_as: spawning " + lastMasterBodyName + " end");
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} error: {1}", "spawn_as", arg));
}
}
}
public class CommandGiveEquip : ICommandExecutor, ICommand, ICommandNotify, ICommandTargets
{
public const string name = "give_equip";
private const string equipRandomName = "RandomEquip";
private readonly List<string> equipRandom;
private EquipmentIndex lastEquip;
public string Id => "give_equip";
public bool IsAllPlayers { get; set; } = true;
public CommandGiveEquip()
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Invalid comparison between Unknown and I4
equipRandom = Tools.GetItemsFromFileByListName("RandomEquip");
for (int num = equipRandom.Count - 1; num >= 0; num--)
{
string text = equipRandom[num];
if ((int)HelperEquip.GetEquipFromString(text) == -1)
{
Tools.Log("Command give_equip error: missed equip item - " + text + " in category RandomEquip");
equipRandom.RemoveAt(num);
}
}
}
public string ProcessMsg(string msg)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
try
{
EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(lastEquip);
string localizedStringByToken = Language.currentLanguage.GetLocalizedStringByToken(equipmentDef.nameToken);
msg = msg.Replace("%value%", localizedStringByToken);
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} process msg error: {1}", "give_equip", arg));
}
return msg;
}
public void Execute(ConCommandArgs args)
{
//IL_0023: 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_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_00b6: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Invalid comparison between Unknown and I4
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: 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)
try
{
if (((ConCommandArgs)(ref args)).Count < 1)
{
Tools.Log("Command give_equip wrong args count");
return;
}
NetworkUser sender = args.sender;
if ((Object)(object)sender == (Object)null)
{
Tools.Log("Command give_equip, error: player not found");
return;
}
NetworkUser sender2 = args.sender;
Inventory val = ((sender2 != null) ? sender2.master.inventory : null);
if ((Object)(object)val == (Object)null)
{
Tools.Log("Command give_equip, error: inventory not found");
return;
}
string text = ((ConCommandArgs)(ref args))[0];
string text2 = ((!text.Equals("RandomEquip", StringComparison.InvariantCultureIgnoreCase)) ? text : UtilityRandom.GetRandomItemFromList<string>((IList<string>)equipRandom));
EquipmentIndex val2 = (lastEquip = HelperEquip.GetEquipFromString(text2));
if ((int)val2 != -1)
{
val.SetEquipmentIndex(val2);
}
else
{
Tools.Log(string.Format("Command {0}, error: item not found {1} : {2}", "give_equip", ((ConCommandArgs)(ref args))[0], val2));
}
Tools.Log(string.Format("Command {0}: player {1} got {2}", "give_equip", sender.masterController.GetDisplayName(), val2));
}
catch (Exception arg)
{
Tools.Log(string.Format("Command {0} error: {1}", "give_equip", arg));
}
}
}
}using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using EventsIO;
using EventsIO.Interfaces;
using ModHelper.Interfaces;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ModHelper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyProduct("ModHelper")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8d858f35-342c-4916-8e50-2b2cfd18640d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ModHelper
{
public class CommandArgsValidator
{
private readonly ILogger logger;
public CommandArgsValidator(ILogger logger)
{
this.logger = logger;
}
public bool IsZeroArgs(IEnumerable<string> args)
{
int num = args?.Count() ?? 0;
if (num != 0)
{
logger?.LogWarning($"CommandArgsValidator wrong args count {num} (must be 0)");
return false;
}
return true;
}
public bool IsZeroArgs(IEnumerator<string> args)
{
if (args == null || !args.MoveNext())
{
return true;
}
logger?.LogWarning("CommandArgsValidator wrong args count (more than needed)");
return false;
}
private bool IsInvalidArgsCount(IEnumerator<string> args)
{
if (args == null || !args.MoveNext())
{
return true;
}
return false;
}
public bool IsValidInt(IEnumerator<string> args, int minValue, int maxValue, bool isSkippable = false)
{
if (IsInvalidArgsCount(args))
{
if (isSkippable)
{
return true;
}
logger?.LogWarning("CommandArgsValidator wrong args count");
return false;
}
try
{
int num = int.Parse(args.Current);
if (num < minValue || num > maxValue)
{
string obj = $"CommandArgsValidator wrong integer value {num} (must be in range from {minValue} to {maxValue})";
logger?.LogWarning(obj);
return false;
}
}
catch (Exception arg)
{
logger?.LogWarning($"CommandArgsValidator can't parse integer value from '{args.Current}', {arg}");
return false;
}
return true;
}
public bool IsValidFloat(IEnumerator<string> args, float minValue, float maxValue, bool isSkippable = false)
{
if (IsInvalidArgsCount(args))
{
if (isSkippable)
{
return true;
}
logger?.LogWarning("CommandArgsValidator wrong args count");
return false;
}
try
{
float num = float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat);
if (num < minValue || num > maxValue)
{
string obj = $"CommandArgsValidator wrong float value {num} (must be in range from {minValue} to {maxValue})";
logger?.LogWarning(obj);
return false;
}
}
catch (Exception arg)
{
logger?.LogWarning($"CommandArgsValidator can't parse float value from '{args.Current}', {arg}");
}
return true;
}
public bool IsValidString(IEnumerator<string> args, Func<string, bool> validator, bool isSkippable = false)
{
if (IsInvalidArgsCount(args))
{
if (isSkippable)
{
return true;
}
logger?.LogWarning("CommandArgsValidator wrong args count");
return false;
}
if (validator == null || validator(args.Current))
{
return true;
}
logger?.LogWarning("CommandArgsValidator wrong string value " + args.Current);
return false;
}
public bool IsValidBool(IEnumerator<string> args, bool isSkippable = false)
{
if (IsInvalidArgsCount(args))
{
if (isSkippable)
{
return true;
}
logger?.LogWarning("CommandArgsValidator wrong args count");
return false;
}
try
{
bool.Parse(args.Current.ToLower());
}
catch (Exception arg)
{
logger?.LogWarning($"CommandArgsValidator can't parse bool value from '{args.Current}', {arg}");
return false;
}
return true;
}
}
public class PeriodicTaskData
{
public string id;
public float period;
internal float periodCalculated;
public int triggerTimes;
public bool isInfiniteRepeates = true;
public Action periodicAction;
public Action finishAction;
public override string ToString()
{
return "id=" + id + ", " + $"period={period}s, " + $"calc_period={periodCalculated}s, " + $"triggerTimes={triggerTimes}, " + $"isInfiniteRepeates={isInfiniteRepeates}";
}
}
public class TimerTaskData
{
public string id;
public float duration;
public Action finishAction;
public override string ToString()
{
return $"id={id}, duration={duration}s";
}
}
public class BufferedLogger : HelperDebugLog, IDisposable
{
protected readonly Queue<string> queue;
protected readonly int bufferRecordsCount;
private bool isDisposed;
public BufferedLogger(string folderPath = null, string logFileName = null, bool isDebug = false, int bufferRecordsCount = 10)
: base(folderPath, logFileName, isDebug)
{
this.bufferRecordsCount = bufferRecordsCount;
queue = new Queue<string>();
}
public virtual void Flush(bool isNeedClearQueue = false)
{
Queue<string> obj = queue;
if (obj == null || obj.Count != 0)
{
WriteToFile(string.Join("\n", queue.ToArray()));
if (isNeedClearQueue)
{
queue.Clear();
}
}
}
public override void Log(object obj)
{
if (obj != null && isLogFile)
{
queue.Enqueue($"{LogTime} {obj}");
if (queue.Count >= bufferRecordsCount)
{
Flush(isNeedClearQueue: true);
}
}
}
protected virtual void Dispose(bool isDisposing)
{
if (!isDisposed)
{
isDisposed = true;
Queue<string> obj = queue;
if (obj != null && obj.Count > 0)
{
Flush();
}
}
}
public void Dispose()
{
Dispose(isDisposing: true);
GC.SuppressFinalize(this);
}
~BufferedLogger()
{
Dispose(isDisposing: false);
}
}
public static class HelperGroups
{
public static Dictionary<string, List<string>> GenerateNewEmptyGroupsDict()
{
return new Dictionary<string, List<string>>(StringComparer.InvariantCultureIgnoreCase);
}
private static bool SafeApplyValidator(Func<string, bool> groupItemValidator, string itemName, ILogger logger = null)
{
try
{
return groupItemValidator?.Invoke(itemName) ?? true;
}
catch (Exception arg)
{
logger?.LogError($"RandomGroup.SafeApplyValidator unexpected error: {arg}");
}
return false;
}
public static void InitGroupsFromFiles(string dataDir, Dictionary<string, List<string>> groups, string groupsPrefix, Func<string, bool> groupItemValidator = null, IDebugLogger logger = null)
{
try
{
if (string.IsNullOrEmpty(groupsPrefix))
{
logger?.LogError("RandomGroup error: wrong groupsPrefix " + groupsPrefix);
return;
}
string[] files = Directory.GetFiles(dataDir);
foreach (string path in files)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
if (fileNameWithoutExtension.StartsWith(groupsPrefix))
{
groups[fileNameWithoutExtension] = GetItemsFromFile(path, logger);
}
}
foreach (KeyValuePair<string, List<string>> group in groups)
{
logger?.LogDebugInfo("RandomGroup validate list " + group.Key + ":");
List<string> list = new List<string>();
foreach (string item in group.Value)
{
if (!SafeApplyValidator(groupItemValidator, item, logger))
{
logger?.LogWarning("invalid name " + item);
list.Add(item);
}
}
if (list.Count > 0)
{
foreach (string item2 in list)
{
group.Value.Remove(item2);
}
logger?.LogWarning("list " + group.Key + " is invalid");
}
else
{
logger?.LogDebugInfo("list " + group.Key + " is valid");
}
}
}
catch (Exception arg)
{
logger?.LogError($"RandomGroup.InitGroupsFromFiles unexpected error: {arg}");
}
}
public static Dictionary<string, List<string>> GenerateGroupsFromFiles(string dataDir, string groupsPrefix, Func<string, bool> groupItemValidator = null, IDebugLogger logger = null)
{
Dictionary<string, List<string>> dictionary = GenerateNewEmptyGroupsDict();
InitGroupsFromFiles(dataDir, dictionary, groupsPrefix, groupItemValidator, logger);
return dictionary;
}
public static List<string> GetItemsFromFile(string path, IDebugLogger logger = null)
{
try
{
List<string> list = new HelperJson(logger).FromFile<List<string>>(path);
if (list == null)
{
list = new List<string>();
}
logger?.LogInfo($"Items from file {path}: found {list.Count}");
foreach (string item in list)
{
logger?.LogDebugInfo("value " + item);
}
return list;
}
catch (Exception arg)
{
logger?.LogError($"HelperGroups.GetItemsFromFile unexpected error: {arg}");
}
return new List<string>();
}
public static bool IsValidGroupName(Dictionary<string, List<string>> dict, string name)
{
return dict?.ContainsKey(name) ?? false;
}
public static void PrintGroups(Dictionary<string, List<string>> dict, ILogger logger, string groupsName = "default_name")
{
if (logger == null)
{
return;
}
if (dict == null || dict.Count == 0)
{
logger?.LogWarning("No groups found for " + groupsName);
return;
}
logger?.LogInfo("---------------Groups " + groupsName + " list---------------");
foreach (KeyValuePair<string, List<string>> item in dict)
{
logger?.LogInfo(item.Key ?? "");
}
logger?.LogInfo("---------------Groups " + groupsName + " list end---------------");
}
}
public class HelperJson : IJsonUtil
{
private class ContainerObjAndInt
{
public object valueObj;
public int valueInt;
}
private class ContainerStringAndInt
{
public string valueString;
public int valueInt;
}
private ILogger logger;
private const char startClass = '{';
private const char endClass = '}';
private const char startArray = '[';
private const char endArray = ']';
private const char isHasNextField = ',';
private const char special = '\\';
private const char startString = '"';
private const char nameValueSeparator = ':';
private char[] ignoreChars = new char[9] { ' ', '\n', '\r', '\t', '\b', '\f', '\0', '{', '[' };
private string logMsgBaseError = "HelperJson error:";
private string logMsgBase = "HelperJson:";
private bool isVerboseDebugLog;
private void VerboseDebugLog(string s)
{
if (isVerboseDebugLog)
{
logger?.LogInfo("[DEBUG] " + s);
}
}
public HelperJson(IDebugLogger logger = null, bool isVerboseDebugLog = false)
{
this.logger = logger;
this.isVerboseDebugLog = isVerboseDebugLog;
}
public T FromFile<T>(string path) where T : class
{
string s;
using (StreamReader streamReader = new StreamReader(path))
{
s = streamReader.ReadToEnd();
}
return FromString<T>(s);
}
public T FromString<T>(string s) where T : class
{
return GetFromString(typeof(T), s, 0).valueObj as T;
}
private char GetSpecialChar(char c)
{
_ = 34;
return c;
}
private void SetFieldClass<T, R>(T instance, string fieldName, R fieldValue) where T : class where R : class
{
Type type = instance.GetType();
VerboseDebugLog("type=" + type.Name + ", field=" + fieldName);
type.GetField(fieldName).SetValue(instance, fieldValue);
}
private ContainerStringAndInt ParseNextStringValue(string s, int index, bool isSkipSep = true)
{
StringBuilder stringBuilder = new StringBuilder();
bool flag = false;
int i;
for (i = index; i < s.Length; i++)
{
char c = s[i];
VerboseDebugLog($"{logMsgBase} ParseNextStringValue for process {c}");
if (!flag)
{
i = SkipIgnoredChars(s, i, isSkipHasNextField: false, isSkipSep);
if (i >= s.Length)
{
logger?.Log(logMsgBaseError + " class field value parsing internal issue. Set default value.");
break;
}
c = s[i];
if (c == '"')
{
flag = true;
VerboseDebugLog(logMsgBase + " ParseNextStringValue is startString case");
continue;
}
if (c == ']' || c == '}')
{
break;
}
if (c == ',' || c == ':')
{
i = SkipIgnoredChars(s, i, isSkipHasNextField: true, isSkipSep);
break;
}
}
else if (c == '\\')
{
VerboseDebugLog(logMsgBase + " ParseNextStringValue is special case");
i++;
if (i >= s.Length)
{
logger?.Log(logMsgBaseError + " class field value parsing internal issue with special symbols. Set default value.");
break;
}
c = GetSpecialChar(s[i]);
if (c != '"')
{
stringBuilder.Append('\\');
}
}
else if (c == '"')
{
VerboseDebugLog(logMsgBase + " ParseNextStringValue is startString end case");
i = SkipIgnoredChars(s, ++i, isSkipHasNextField: true, isSkipSep);
break;
}
VerboseDebugLog($"{logMsgBase} ParseNextStringValue append {c}");
stringBuilder.Append(c);
}
string text = stringBuilder.ToString();
VerboseDebugLog($"{logMsgBase} ParseNextStringValue {text}, end at index {i}");
return new ContainerStringAndInt
{
valueString = text,
valueInt = i
};
}
private ContainerStringAndInt GetNextFieldName(string s, int index)
{
VerboseDebugLog(logMsgBase + " GetNextFieldName");
return ParseNextStringValue(s, index, isSkipSep: false);
}
private ContainerObjAndInt GetNextValue(Type valueType, string s, int index, bool isSkipSep)
{
VerboseDebugLog(logMsgBase + " GetNextValue");
int num = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep);
if (num >= s.Length)
{
logger?.LogError(logMsgBaseError + " class parsing internal issue at value type " + valueType.Name + ". Set default value.");
}
if (valueType.IsPrimitive)
{
ContainerStringAndInt containerStringAndInt = ParseNextStringValue(s, num, isSkipSep);
try
{
TypeCode typeCode = Type.GetTypeCode(valueType);
object valueObj;
if ((uint)(typeCode - 5) <= 10u)
{
if (double.TryParse(containerStringAndInt.valueString, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
{
valueObj = Convert.ChangeType(result, valueType);
}
else
{
valueObj = Activator.CreateInstance(valueType);
logger?.Log(logMsgBaseError + " incorrect convert, use default.");
logger?.Log("Read value: " + containerStringAndInt.valueString + ", type: " + valueType.Name);
}
}
else
{
valueObj = Convert.ChangeType(containerStringAndInt.valueString, valueType);
}
return new ContainerObjAndInt
{
valueObj = valueObj,
valueInt = containerStringAndInt.valueInt
};
}
catch (Exception arg)
{
logger?.Log($"{logMsgBaseError} incorrect format, use default. Msg: {arg}");
logger?.Log("read value: " + containerStringAndInt.valueString + ", type: " + valueType.Name);
return new ContainerObjAndInt
{
valueObj = Activator.CreateInstance(valueType),
valueInt = containerStringAndInt.valueInt
};
}
}
if (valueType.IsAssignableFrom(typeof(string)))
{
ContainerStringAndInt containerStringAndInt2 = ParseNextStringValue(s, num, isSkipSep);
return new ContainerObjAndInt
{
valueObj = containerStringAndInt2.valueString,
valueInt = containerStringAndInt2.valueInt
};
}
ContainerObjAndInt fromString = GetFromString(valueType, s, num);
return new ContainerObjAndInt
{
valueObj = fromString.valueObj,
valueInt = fromString.valueInt
};
}
private int SkipIgnoredChars(string s, int index, bool isSkipHasNextField = false, bool isSkipSep = false)
{
for (int i = index; i < s.Length; i++)
{
if (ignoreChars.Contains(s[i]))
{
VerboseDebugLog($"skip char '{s[i]}'");
continue;
}
if (isSkipHasNextField && s[i] == ',')
{
VerboseDebugLog($"skip char '{s[i]}'");
continue;
}
if (isSkipSep && s[i] == ':')
{
VerboseDebugLog($"skip char '{s[i]}'");
continue;
}
return i;
}
return s.Length;
}
private ContainerObjAndInt ParseIListByItemType(Type itemType, string s, int index)
{
if (!(Activator.CreateInstance(typeof(List<>).MakeGenericType(itemType)) is IList list))
{
logger?.LogError(logMsgBaseError + " can't create IList for item type " + itemType.Name);
return new ContainerObjAndInt
{
valueObj = null,
valueInt = s.Length
};
}
do
{
ContainerObjAndInt nextValue = GetNextValue(itemType, s, index, isSkipSep: true);
object valueObj = nextValue.valueObj;
index = nextValue.valueInt;
list.Add(valueObj);
index = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep: true);
}
while (index < s.Length && s[index] != ']' && s[index] != '}');
return new ContainerObjAndInt
{
valueObj = list,
valueInt = index + 1
};
}
private ContainerObjAndInt ParseIList(Type resultType, string s, int index)
{
Type itemType = ((!resultType.IsGenericType) ? resultType.GetElementType() : resultType.GetGenericArguments()[0]);
return ParseIListByItemType(itemType, s, index);
}
private ContainerObjAndInt ParseArray(Type resultType, string s, int index)
{
Type elementType = resultType.GetElementType();
ContainerObjAndInt containerObjAndInt = ParseIListByItemType(elementType, s, index);
Array array;
if (containerObjAndInt.valueObj is IList list)
{
array = Array.CreateInstance(elementType, list.Count);
for (int i = 0; i < array.Length; i++)
{
array.SetValue(list[i], i);
}
}
else
{
logger?.Log(logMsgBaseError + " create empty Array");
array = Array.CreateInstance(elementType, 0);
}
return new ContainerObjAndInt
{
valueObj = array,
valueInt = containerObjAndInt.valueInt
};
}
private ContainerObjAndInt ParseIDictionary(Type dictType, string s, int index)
{
Type[] genericArguments = dictType.GetGenericArguments();
if (genericArguments.Length != 2)
{
logger?.Log(logMsgBaseError + " can't create IDictionary, invalid args");
}
if (dictType.IsGenericType)
{
if (!dictType.IsGenericTypeDefinition)
{
dictType = dictType.GetGenericTypeDefinition();
}
dictType = dictType.MakeGenericType(genericArguments);
}
if (!(Activator.CreateInstance(dictType) is IDictionary dictionary))
{
string name = dictType.GetType().Name;
logger?.Log(logMsgBaseError + " can't create IDictionary " + name + " for item type " + genericArguments[0].Name + ", " + genericArguments[1].Name);
return new ContainerObjAndInt
{
valueObj = null,
valueInt = s.Length
};
}
Type valueType = genericArguments[0];
Type valueType2 = genericArguments[1];
do
{
ContainerObjAndInt nextValue = GetNextValue(valueType, s, index, isSkipSep: false);
index = nextValue.valueInt;
ContainerObjAndInt nextValue2 = GetNextValue(valueType2, s, index, isSkipSep: true);
index = nextValue2.valueInt;
dictionary.Add(nextValue.valueObj, nextValue2.valueObj);
VerboseDebugLog($"{logMsgBase} dict add key {nextValue.valueObj}");
index = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep: true);
}
while (index < s.Length && s[index] != '}' && s[index] != ']');
return new ContainerObjAndInt
{
valueObj = dictionary,
valueInt = index + 1
};
}
private bool IsTypeOf(Type targetType, Type sourceType, int argsCount)
{
if (sourceType.IsAssignableFrom(targetType))
{
VerboseDebugLog(logMsgBase + " is " + targetType.Name);
return true;
}
Type[] types = sourceType.Assembly.GetTypes();
foreach (Type type in types)
{
if (!type.IsClass)
{
continue;
}
Type[] interfaces = type.GetInterfaces();
foreach (Type type2 in interfaces)
{
if (type2.IsGenericType && (object)type2.GetGenericTypeDefinition() == targetType && sourceType.GetGenericArguments().Length == argsCount)
{
VerboseDebugLog(logMsgBase + " is " + targetType.Name + " assembly interface");
return true;
}
}
}
return false;
}
private ContainerObjAndInt GetFromString(Type resultType, string s, int index)
{
try
{
VerboseDebugLog(logMsgBase + " GetFromString");
if (resultType.IsArray)
{
VerboseDebugLog(logMsgBase + " is array");
return ParseArray(resultType, s, index);
}
if (resultType.IsAssignableFrom(typeof(IList)) || IsTypeOf(typeof(IList<>), resultType, 1))
{
return ParseIList(resultType, s, index);
}
if (resultType.IsAssignableFrom(typeof(IDictionary)) || IsTypeOf(typeof(IDictionary<, >), resultType, 2))
{
return ParseIDictionary(resultType, s, index);
}
if (resultType.IsGenericType && !resultType.IsGenericTypeDefinition)
{
Type[] genericArguments = resultType.GetGenericArguments();
resultType = resultType.GetGenericTypeDefinition();
resultType = resultType.MakeGenericType(genericArguments);
}
object obj = Activator.CreateInstance(resultType);
int num = index;
while (num < s.Length && s[num] != ']' && s[num] != '}')
{
ContainerStringAndInt nextFieldName = GetNextFieldName(s, num);
string valueString = nextFieldName.valueString;
if (string.IsNullOrEmpty(valueString?.Trim()))
{
VerboseDebugLog(logMsgBase + " IsNullOrWhiteSpace field " + valueString + ", class type " + resultType.Name);
num = GetNextValue(typeof(string), s, num, isSkipSep: true).valueInt;
continue;
}
num = nextFieldName.valueInt;
FieldInfo field = resultType.GetField(valueString);
VerboseDebugLog(logMsgBase + " field " + valueString + ", class type " + resultType.Name);
if (isVerboseDebugLog)
{
FieldInfo[] fields = resultType.GetFields();
VerboseDebugLog(logMsgBase + " fields in class: ");
FieldInfo[] array = fields;
foreach (FieldInfo fieldInfo in array)
{
VerboseDebugLog(fieldInfo.Name);
}
}
if ((object)field == null)
{
logger?.LogWarning(logMsgBaseError + " can't find field " + valueString + " for type " + resultType.Name + ". Try to skip.");
num = GetNextValue(typeof(string), s, num, isSkipSep: true).valueInt;
}
else
{
ContainerObjAndInt nextValue = GetNextValue(field.FieldType, s, num, isSkipSep: true);
object valueObj = nextValue.valueObj;
num = nextValue.valueInt;
SetFieldClass(obj, valueString, valueObj);
}
}
num = SkipIgnoredChars(s, num + 1, isSkipHasNextField: true, isSkipSep: true);
return new ContainerObjAndInt
{
valueObj = obj,
valueInt = num
};
}
catch (Exception arg)
{
logger?.LogError($"{logMsgBaseError} {arg}");
}
return new ContainerObjAndInt
{
valueObj = null,
valueInt = s.Length
};
}
}
public class HelperDebugLog : HelperLog, IDebugLogger, ILoggerWithConsole, ILogger
{
protected bool isDebug;
public HelperDebugLog(string folderPath = null, string logFileName = null, bool isDebug = false)
: base(folderPath, logFileName)
{
this.isDebug = isDebug;
}
public virtual void LogDebugInfo(object obj)
{
if (isDebug)
{
LogInfo($"[DEBUG] {obj}");
}
}
public virtual void LogDebugWarning(object obj)
{
if (isDebug)
{
LogWarning($"[DEBUG] {obj}");
}
}
public virtual void LogDebugError(object obj)
{
if (isDebug)
{
LogError($"[DEBUG] {obj}");
}
}
}
public class ScheduleManager
{
protected ILogger logger;
protected Dictionary<string, TimerTaskData> timerTasks = new Dictionary<string, TimerTaskData>();
protected Dictionary<string, PeriodicTaskData> periodicTasks = new Dictionary<string, PeriodicTaskData>();
protected List<TimerTaskData> timerTasksNoId = new List<TimerTaskData>();
protected List<PeriodicTaskData> periodicTasksNoId = new List<PeriodicTaskData>();
protected int onUpdateErrorLimit = 10;
public ScheduleManager(ILogger logger = null)
{
this.logger = logger;
}
public void NewTimerTask(TimerTaskData task, bool triggerFinishIfExists = false)
{
if (task == null)
{
logger?.LogInfo($"ScheduleManager new timer task null error. Details info: {task}");
return;
}
if (task.id == null)
{
NewTimerTaskWithOutId(task);
return;
}
if (triggerFinishIfExists && timerTasks.ContainsKey(task.id))
{
SafeRunAction(timerTasks[task.id].finishAction);
}
timerTasks[task.id] = task;
logger?.LogInfo($"ScheduleManager new timer task {task}");
}
public void NewPeriodicTask(PeriodicTaskData task, bool triggerFinishIfExists = false)
{
if (task == null)
{
logger?.LogInfo($"ScheduleManager new periodic task null error. Details info: {task}");
return;
}
task.periodCalculated = task.period;
if (task.id == null)
{
NewPeriodicTaskWithOutId(task);
return;
}
if (triggerFinishIfExists && periodicTasks.ContainsKey(task.id))
{
SafeRunAction(periodicTasks[task.id].finishAction);
}
periodicTasks[task.id] = task;
logger?.LogInfo($"ScheduleManager new periodic task {task}");
}
public void AppendPeriodicTask(PeriodicTaskData task, bool isReplaceAction = false)
{
if (task.id == null || !periodicTasks.ContainsKey(task.id))
{
NewPeriodicTask(task);
return;
}
logger?.LogInfo($"ScheduleManager append periodic task {task}");
PeriodicTaskData periodicTaskData = periodicTasks[task.id];
periodicTaskData.triggerTimes += task.triggerTimes;
if (isReplaceAction)
{
periodicTaskData.finishAction = task.finishAction;
}
}
protected void NewTimerTaskWithOutId(TimerTaskData task)
{
if (task == null)
{
logger?.LogWarning($"ScheduleManager new timer no id task null error. Details info: {task}");
return;
}
timerTasksNoId.Add(task);
logger?.LogInfo($"ScheduleManager new timer no id task {task}");
}
protected void NewPeriodicTaskWithOutId(PeriodicTaskData task)
{
if (task == null)
{
logger?.LogWarning($"ScheduleManager new periodic no id task null error. Details info: {task}");
return;
}
periodicTasksNoId.Add(task);
logger?.LogInfo($"ScheduleManager new periodic no id task {task}");
}
public void AppendTimerTask(TimerTaskData task, bool isReplaceAction = true)
{
if (!timerTasks.ContainsKey(task.id))
{
NewTimerTask(task);
return;
}
logger?.LogInfo($"ScheduleManager append timer task {task}");
TimerTaskData timerTaskData = timerTasks[task.id];
timerTasks[task.id] = task;
task.duration += timerTaskData.duration;
if (!isReplaceAction)
{
task.finishAction = timerTaskData.finishAction;
}
}
public bool IsTaskExists(string id)
{
if (!periodicTasks.ContainsKey(id))
{
return timerTasks.ContainsKey(id);
}
return true;
}
public void RemoveTimerTask(string id)
{
if (timerTasks.Remove(id))
{
logger?.LogInfo("ScheduleManager remove timer task " + id);
}
}
public void RemovePeriodicTask(string id)
{
if (periodicTasks.Remove(id))
{
logger?.LogInfo("ScheduleManager remove periodic task " + id);
}
}
public void RemoveAllTasks(string id)
{
logger?.LogInfo("ScheduleManager RemoveAllTasks with id " + id);
RemoveTimerTask(id);
RemovePeriodicTask(id);
}
public void RemoveAllTasks(bool isSuppressLog = false)
{
timerTasks.Clear();
periodicTasks.Clear();
timerTasksNoId.Clear();
periodicTasksNoId.Clear();
if (!isSuppressLog && logger != null)
{
logger.LogInfo("ScheduleManager RemoveAllTasks");
}
}
protected List<TimerTaskData> ProcessTimersList(ICollection<TimerTaskData> list, float dt)
{
List<TimerTaskData> list2 = new List<TimerTaskData>();
foreach (TimerTaskData item in list)
{
item.duration -= dt;
if (item.duration <= 0f)
{
SafeRunAction(item.finishAction);
list2.Add(item);
logger?.LogInfo("ScheduleManager triggered finish action timer task " + item.id);
}
}
return list2;
}
protected List<PeriodicTaskData> ProcessPeriodicList(ICollection<PeriodicTaskData> list, float dt)
{
List<PeriodicTaskData> list2 = new List<PeriodicTaskData>();
foreach (PeriodicTaskData item in list)
{
item.periodCalculated -= dt;
if (!(item.periodCalculated <= 0f))
{
continue;
}
if (item.isInfiniteRepeates || item.triggerTimes > 0)
{
SafeRunAction(item.periodicAction);
item.periodCalculated = item.period;
if (item.triggerTimes == 1)
{
logger?.LogInfo("ScheduleManager triggered action periodic task " + item.id);
}
}
if (!item.isInfiniteRepeates)
{
item.triggerTimes--;
if (item.triggerTimes <= 0)
{
SafeRunAction(item.finishAction);
list2.Add(item);
logger?.LogInfo("ScheduleManager triggered finish action periodic task " + item.id);
}
}
}
return list2;
}
public void OnUpdate(float dt)
{
try
{
foreach (TimerTaskData item in ProcessTimersList(timerTasks.Values, dt))
{
timerTasks.Remove(item.id);
logger?.LogInfo($"ScheduleManager OnUpdate finished timer task {item}");
}
foreach (PeriodicTaskData item2 in ProcessPeriodicList(periodicTasks.Values, dt))
{
periodicTasks.Remove(item2.id);
logger?.LogInfo($"ScheduleManager OnUpdate finished periodic task {item2}");
}
foreach (TimerTaskData item3 in ProcessTimersList(timerTasksNoId, dt))
{
timerTasksNoId.Remove(item3);
logger?.LogInfo($"ScheduleManager OnUpdate finished timer no id task {item3}");
}
foreach (PeriodicTaskData item4 in ProcessPeriodicList(periodicTasksNoId, dt))
{
periodicTasksNoId.Remove(item4);
logger?.LogInfo($"ScheduleManager OnUpdate finished periodic no id task {item4}");
}
}
catch (Exception arg)
{
if (onUpdateErrorLimit > 0)
{
logger?.LogError($"ScheduleManager unexpected onUpdate error: {arg}");
onUpdateErrorLimit--;
}
}
}
public void FinishImmediatlyTimerTask(string id)
{
if (timerTasks.ContainsKey(id))
{
SafeRunAction(timerTasks[id].finishAction);
timerTasks.Remove(id);
logger?.LogInfo("ScheduleManager finish and remove timer task " + id);
}
}
public void FinishImmediatlyPeriodicTask(string id)
{
if (periodicTasks.ContainsKey(id))
{
SafeRunAction(periodicTasks[id].finishAction);
periodicTasks.Remove(id);
logger?.LogInfo("ScheduleManager finish and remove periodic task " + id);
}
}
public void FinishAllImmediatly(string id)
{
FinishImmediatlyTimerTask(id);
FinishImmediatlyPeriodicTask(id);
}
public void FinishAllImmediatly()
{
foreach (TimerTaskData value in timerTasks.Values)
{
SafeRunAction(value.finishAction);
}
foreach (PeriodicTaskData value2 in periodicTasks.Values)
{
SafeRunAction(value2.finishAction);
}
foreach (TimerTaskData item in timerTasksNoId)
{
SafeRunAction(item.finishAction);
}
foreach (PeriodicTaskData item2 in periodicTasksNoId)
{
SafeRunAction(item2.finishAction);
}
RemoveAllTasks();
}
protected void SafeRunAction(Action action)
{
if (action == null)
{
return;
}
try
{
action();
}
catch (Exception arg)
{
logger?.LogError($"SafeRunAction error: {arg}");
}
}
}
public class UtilityConsole
{
private readonly Dictionary<string, IConsoleCommand> consoleCommandsDict;
private readonly IDebugLogger logger;
private readonly List<string> ignoreValidationCommands;
public bool isLogCheckCommand = true;
public bool isLogCheckCommandParameters = true;
public int logCheckCommandParametersMaxLength = 40;
public bool isLogProcessCommand = true;
public bool isLogProcessCommandParameters = true;
public int logProcessCommandParametersMaxLength = 40;
public UtilityConsole(IDebugLogger logger = null, List<string> ignoreValidationCommands = null)
{
consoleCommandsDict = new Dictionary<string, IConsoleCommand>();
this.logger = logger;
this.ignoreValidationCommands = ignoreValidationCommands;
}
public void RegisterCommand(IConsoleCommand command)
{
if (string.IsNullOrEmpty(command?.Id))
{
logger?.LogWarning("UtilityConsole.RegisterCommand: invalid console command");
}
else
{
consoleCommandsDict[command.Id] = command;
}
}
public static string[] ParseCommandLine(string commandLine)
{
return commandLine.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
}
public static string[] ParseArgs(string command)
{
return command.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
}
private string GetCmdName(string cmd)
{
string[] array = cmd.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (array.Length == 0)
{
return "";
}
return array[0];
}
private void LogCommand(string funcPrefix, string cmd, bool isLog, bool isLogParams, int maxLen)
{
if (logger == null || !isLog)
{
return;
}
if (string.IsNullOrEmpty(cmd))
{
logger.LogWarning(funcPrefix + " null or empty");
}
else if (isLogParams)
{
if (cmd.Length > maxLen)
{
string text = cmd.Substring(0, maxLen);
logger.Log(funcPrefix + " " + text + "...");
}
else
{
logger.Log(funcPrefix + " " + cmd);
}
}
else
{
logger.Log(funcPrefix + " " + GetCmdName(cmd));
}
}
public bool IsValidCommandLine(string commandLine)
{
try
{
if (string.IsNullOrEmpty(commandLine))
{
logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid command line");
return false;
}
string[] array = ParseCommandLine(commandLine);
if (array == null || array.Length < 1)
{
logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid commands count");
return false;
}
bool flag = true;
string[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
string text = array2[i]?.Trim();
LogCommand("UtilityConsole.IsValidCommandLine: check command", text, isLogCheckCommand, isLogCheckCommandParameters, logCheckCommandParametersMaxLength);
string[] array3 = ParseArgs(text);
if (array3 == null || array3.Length < 1)
{
logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid commands count");
flag = false;
continue;
}
string text2 = array3[0];
List<string> list = ignoreValidationCommands;
if (list != null && list.Contains(text2))
{
logger?.LogDebugInfo("UtilityConsole.IsValidCommandLine: validation is ignored for this command");
}
else if (consoleCommandsDict.ContainsKey(text2))
{
bool flag2 = consoleCommandsDict[text2].IsValidCommandArgs(array3.Skip(1));
if (!flag2)
{
logger?.LogDebugError("UtilityConsole.IsValidCommandLine: command with id " + text2 + " is invalid");
}
flag = flag && flag2;
}
else
{
logger?.LogDebugError("UtilityConsole.IsValidCommandLine: can't find custom command with id " + text2);
flag = false;
}
}
return flag;
}
catch (Exception arg)
{
logger?.LogDebugError(string.Format("{0} error: {1}", "UtilityConsole.IsValidCommandLine:", arg));
return false;
}
}
public bool RunCommand(string commandLine, IEventsData data, Action<string> onCustomCommandNotFound = null)
{
try
{
string[] array = ParseCommandLine(commandLine);
foreach (string text in array)
{
LogCommand("UtilityConsole.RunCommand: process command", text, isLogProcessCommand, isLogProcessCommandParameters, logProcessCommandParametersMaxLength);
string[] array2 = ParseArgs(text);
string key = array2[0];
if (consoleCommandsDict.ContainsKey(key))
{
try
{
if (consoleCommandsDict[key] is IConsoleCommandWithData consoleCommandWithData)
{
consoleCommandWithData.Execute(array2.Skip(1), data);
}
else
{
consoleCommandsDict[key].Execute(array2.Skip(1));
}
}
catch (Exception arg)
{
logger?.LogError(string.Format("{0} execute command error {1}", "UtilityConsole.RunCommand:", arg));
}
}
else if (onCustomCommandNotFound != null)
{
onCustomCommandNotFound(text);
}
else
{
logger?.LogError("UtilityConsole.RunCommand: execute command not found error");
}
}
}
catch (Exception arg2)
{
logger?.LogError(string.Format("{0} error {1}", "UtilityConsole.RunCommand:", arg2));
return false;
}
return true;
}
}
public class CommandArgsReader
{
private readonly ILogger logger;
public CommandArgsReader(ILogger logger)
{
this.logger = logger;
}
public int ReadInt(IEnumerator<string> args, int defaultValue = 0)
{
if (args == null || !args.MoveNext())
{
return defaultValue;
}
try
{
return int.Parse(args.Current);
}
catch (Exception arg)
{
logger?.LogWarning($"CommandArgsReader: {arg}");
return defaultValue;
}
}
public float ReadFloat(IEnumerator<string> args, float defaultValue = 0f)
{
if (args == null || !args.MoveNext())
{
return defaultValue;
}
try
{
return float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat);
}
catch (Exception arg)
{
logger?.LogWarning($"CommandArgsReader: {arg}");
return defaultValue;
}
}
public string ReadString(IEnumerator<string> args, string defaultValue = "")
{
if (args == null || !args.MoveNext())
{
return defaultValue;
}
return args.Current;
}
public bool ReadBool(IEnumerator<string> args, bool defaultValue = false)
{
if (args == null || !args.MoveNext())
{
return defaultValue;
}
try
{
return bool.Parse(args.Current.ToLower());
}
catch (Exception arg)
{
logger?.LogWarning($"CommandArgsReader: {arg}");
return defaultValue;
}
}
}
public static class UtilityRandom
{
private static readonly Random rnd = new Random(DateTime.Now.Millisecond);
public static T GetRandomItemFromList<T>(IList<T> list)
{
if (list == null || list.Count <= 0)
{
return default(T);
}
return list[rnd.Next(list.Count)];
}
}
public class HelperCommandManagerFormatted : ICommandManager
{
private Dictionary<string, string> commandsDict;
private readonly IDebugLogger logger;
private readonly string errorString = string.Empty;
public int logCommandMaxLength = 50;
public bool isUseLogCommandLimit = true;
public HelperCommandManagerFormatted(IDebugLogger logger)
{
this.logger = logger;
}
public virtual void InitFromFile(string path)
{
try
{
Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, string>>(path);
commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
CheckLoadedDict();
}
catch (Exception arg)
{
logger?.LogError($"HelperCommandManagerFormatted InitFromFile load: {arg}");
commandsDict = null;
}
}
public virtual void InitFromString(string data)
{
try
{
Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromString<Dictionary<string, string>>(data);
commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
CheckLoadedDict();
}
catch (Exception arg)
{
logger?.LogError($"HelperCommandManagerFormatted InitFromString load: {arg}");
commandsDict = null;
}
}
protected virtual void CheckLoadedDict()
{
if (commandsDict == null)
{
logger?.LogWarning("HelperCommandManagerFormatted: commandsDict null");
return;
}
logger?.LogInfo($"HelperCommandManagerFormatted: found commands {commandsDict.Count}");
foreach (KeyValuePair<string, string> item in commandsDict)
{
logger?.LogDebugInfo("command: key=" + item.Key + ", value=" + GetSubstringCmd(item.Value));
}
}
protected virtual string GetSubstringCmd(string cmd)
{
if (!isUseLogCommandLimit || cmd == null)
{
return cmd;
}
if (cmd.Length <= logCommandMaxLength)
{
return cmd;
}
return cmd.Substring(0, logCommandMaxLength) + "...";
}
public virtual string GetCommandData(string eventKey, bool isLogError = false)
{
if (commandsDict == null)
{
logger?.LogWarning("HelperCommandManagerFormatted GetCommandData: commandsDict null");
return "";
}
try
{
eventKey = eventKey.Trim();
return commandsDict[eventKey] ?? throw new NullReferenceException();
}
catch (Exception arg)
{
if (isLogError)
{
logger?.LogError($"HelperCommandManagerFormatted key {eventKey}, error: {arg}");
}
return errorString;
}
}
public virtual string[] GetCommands()
{
if (commandsDict == null)
{
logger?.LogWarning("HelperCommandManagerFormatted GetCommands: commandsDict null");
return new string[0];
}
List<string> list = new List<string>();
foreach (KeyValuePair<string, string> item in commandsDict)
{
list.Add(item.Value);
}
return list.ToArray();
}
}
public class HelperDictManager : IDictManager
{
private readonly ILogger logger;
private readonly IEventsDataEncoder encoder;
private readonly IEventsDataEncoderParams encoderParams;
public HelperDictManager(ILogger logger = null)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Expected O, but got Unknown
this.logger = logger;
encoderParams = (IEventsDataEncoderParams)(object)(encoder = (IEventsDataEncoder)new EventsDataEncoder());
}
public Dictionary<string, string> ParseDict(string data)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
try
{
string[] array = data.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
if (array == null)
{
logger?.LogError("HelperDictManager error, wrong args. Source: " + data);
return dictionary;
}
string[] array2 = array;
foreach (string text in array2)
{
string[] array3 = text.Split(new char[1] { encoderParams.ClientAppSepChar }, StringSplitOptions.RemoveEmptyEntries);
if (array3.Length != 2)
{
logger?.LogWarning("HelperDictManager, invalid item: " + text);
continue;
}
string text2 = array3[0];
string text3 = array3[1];
if (text3 == null || text2 == null)
{
logger?.LogWarning("HelperDictManager, invalid key/val: " + text2 + "/" + text3);
continue;
}
string key = encoder.Decode(text2).Trim();
string value = encoder.Decode(text3).Trim();
dictionary.Add(key, value);
}
}
catch (Exception arg)
{
logger?.LogError($"HelperDictManager error: {arg}");
}
return dictionary;
}
}
public class HelperCommandManager : ICommandManager
{
private readonly Dictionary<string, string> commandsDict;
private readonly IDebugLogger logger;
private readonly string errorString = string.Empty;
public HelperCommandManager(IDebugLogger logger, string commandsDir, string commandsFname = "commands.data")
{
this.logger = logger;
try
{
string path = Path.Combine(commandsDir, commandsFname);
IDictManager dictManager = new HelperDictManager();
using StreamReader streamReader = new StreamReader(path);
string data = streamReader.ReadToEnd();
Dictionary<string, string> dictionary = dictManager.ParseDict(data);
commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
logger?.LogInfo($"HelperCommandManager: found commands {commandsDict.Count}");
foreach (KeyValuePair<string, string> item in commandsDict)
{
logger?.LogDebugInfo("command: key=" + item.Key + ", value=" + item.Value);
}
}
catch (Exception arg)
{
logger?.LogError($"HelperCommandManager load: {arg}");
commandsDict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
public string GetCommandData(string eventKey, bool isLogError = false)
{
try
{
eventKey = eventKey.Trim();
return commandsDict[eventKey] ?? throw new NullReferenceException();
}
catch (Exception arg)
{
if (isLogError)
{
logger?.LogError($"HelperCommandManager key {eventKey}: {arg}");
}
return errorString;
}
}
public string[] GetCommands()
{
List<string> list = new List<string>();
foreach (KeyValuePair<string, string> item in commandsDict)
{
list.Add(item.Value);
}
return list.ToArray();
}
public virtual void InitFromFile(string path)
{
throw new NotImplementedException();
}
public virtual void InitFromString(string data)
{
throw new NotImplementedException();
}
}
public class HelperEventManager<CustomEvent> : IEventManager<CustomEvent> where CustomEvent : class, IEvent
{
private readonly Dictionary<string, CustomEvent> eventsDict;
private readonly IDebugLogger logger;
public HelperEventManager(IDebugLogger logger)
{
this.logger = logger;
eventsDict = new Dictionary<string, CustomEvent>(StringComparer.OrdinalIgnoreCase);
try
{
Type type = typeof(CustomEvent);
IEnumerable<Type> enumerable = from p in AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly s)
{
try
{
return s.GetTypes();
}
catch (Exception)
{
return new Type[0];
}
})
where p.IsClass && !p.IsAbstract && !p.IsInterface && type.IsAssignableFrom(p)
select p;
logger?.LogInfo($"HelperEventManager: found {enumerable.Count()} events");
foreach (Type item in enumerable)
{
CustomEvent val = Activator.CreateInstance(item) as CustomEvent;
if (val != null)
{
eventsDict.Add(val.Id, val);
logger?.LogDebugInfo("init event '" + val.Id + "' complete");
}
else
{
logger?.LogWarning("init event '" + val.Id + "' failed");
}
}
}
catch (Exception arg)
{
logger?.LogError($"HelperEventManager error: {arg}");
}
}
public HelperEventManager(IDebugLogger logger, IEventManager<IEvent> manager)
{
this.logger = logger;
eventsDict = new Dictionary<string, CustomEvent>(StringComparer.OrdinalIgnoreCase);
string name = typeof(CustomEvent).Name;
try
{
foreach (IEvent item in manager.GetEventsCollection())
{
if (item is CustomEvent val)
{
eventsDict.Add(val.Id, val);
logger?.LogDebugInfo("init event '" + val.Id + "' as '" + name + "' complete");
}
}
}
catch (Exception arg)
{
logger?.LogError($"HelperEventManager: {arg}");
}
}
public IEnumerable<CustomEvent> GetEventsCollection()
{
if (eventsDict != null)
{
return eventsDict.Values;
}
return new List<CustomEvent>();
}
public CustomEvent GetEvent(string eventID, bool isLogError = false)
{
try
{
eventID = eventID.Trim();
return eventsDict[eventID] ?? throw new NullReferenceException();
}
catch (Exception arg)
{
if (isLogError)
{
logger?.LogError($"HelperCommandManager key {eventID}: {arg}");
}
return null;
}
}
}
public class HelperLanguagesFormatted : ITranslation
{
protected Dictionary<string, Text> transDict;
protected readonly IDebugLogger logger;
protected readonly string errorString = "trans_error";
public bool isLogOnlyEnItems;
public bool isSuppressLogItems = true;
public HelperLanguagesFormatted(IDebugLogger logger)
{
this.logger = logger;
}
public virtual void InitFromFile(string path)
{
try
{
Dictionary<string, Text> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, Text>>(path);
transDict = new Dictionary<string, Text>(dictionary, StringComparer.OrdinalIgnoreCase);
CheckLoadedDict();
}
catch (Exception arg)
{
logger?.LogError($"HelperLanguagesFormatted InitFromFile load: {arg}");
transDict = null;
}
}
public virtual void InitFromString(string data)
{
try
{
Dictionary<string, Text> dictionary = UtilityJson.Generate(logger).FromString<Dictionary<string, Text>>(data);
transDict = new Dictionary<string, Text>(dictionary, StringComparer.OrdinalIgnoreCase);
CheckLoadedDict();
}
catch (Exception arg)
{
logger?.LogError($"HelperLanguagesFormatted InitFromString load: {arg}");
transDict = null;
}
}
protected virtual void CheckLoadedDict()
{
if (transDict == null)
{
logger?.LogWarning("HelperLanguagesFormatted: transDict null");
return;
}
logger?.LogInfo($"HelperLanguagesFormatted: found translates {transDict.Count}");
if (isSuppressLogItems || logger == null)
{
return;
}
foreach (KeyValuePair<string, Text> item in transDict)
{
if (isLogOnlyEnItems)
{
logger.LogDebugInfo("key=" + item.Key + ", en=" + item.Value.en);
continue;
}
logger.LogDebugInfo("key=" + item.Key + ", ru=" + item.Value.ru + ", en=" + item.Value.en);
}
}
public virtual string GetTrans(string key, Languages lang)
{
return GetTrans(key, lang.ToString());
}
public virtual string GetTrans(string key, string lang)
{
if (transDict == null)
{
logger?.LogWarning("HelperLanguagesFormatted transDict is null");
return errorString;
}
try
{
key = key.Trim();
lang = lang.Trim();
return transDict[key].GetTrans(lang);
}
catch (Exception arg)
{
logger?.LogError($"HelperLanguagesFormatted key {key} lang {lang}, error: {arg}");
return errorString;
}
}
}
public class HelperLog : ILoggerWithConsole, ILogger
{
protected readonly string path;
protected const string baseLogName = "interactive_mod_log.txt";
public bool isLogConsole = true;
public bool isLogFile = true;
public ConsoleColor infoColor = ConsoleColor.White;
public ConsoleColor warningColor = ConsoleColor.Yellow;
public ConsoleColor errorColor = ConsoleColor.Red;
protected virtual string LogTime => DateTime.Now.ToString("h:mm:ss:fff");
public HelperLog(string logDir)
: this(logDir, "interactive_mod_log.txt")
{
}
public HelperLog(string logDir, string logFname)
{
if (logDir == "" || Directory.Exists(logDir))
{
path = Path.Combine(logDir, logFname);
}
}
protected virtual void WriteToFile(string s)
{
if (path != null)
{
using (StreamWriter streamWriter = new StreamWriter(path, append: true, Encoding.UTF8))
{
streamWriter.WriteLine(s);
}
}
}
public virtual void Log(object obj)
{
if (isLogFile)
{
WriteToFile($"{LogTime} {obj}");
}
}
public virtual void LogConsole(string text, string prefix, ConsoleColor prefixColor)
{
Console.ForegroundColor = prefixColor;
Console.Write(LogTime + " " + prefix + " ");
Console.ResetColor();
Console.WriteLine(text);
}
protected virtual void LogWithConsole(object obj, string prefix, ConsoleColor color)
{
Log($"{prefix} {obj}");
if (isLogConsole)
{
LogConsole(obj.ToString(), prefix, color);
}
}
public virtual void LogInfo(object obj)
{
LogWithConsole(obj, "[INFO]", infoColor);
}
public virtual void LogWarning(object obj)
{
LogWithConsole(obj, "[WARNING]", warningColor);
}
public virtual void LogError(object obj)
{
LogWithConsole(obj, "[ERROR]", errorColor);
}
public virtual void LogInfoConsoleOnly(object obj)
{
if (isLogConsole)
{
LogConsole(obj.ToString(), "[INFO]", infoColor);
}
}
public virtual void LogWarningConsoleOnly(object obj)
{
if (isLogConsole)
{
LogConsole(obj.ToString(), "[WARNING]", warningColor);
}
}
public virtual void LogErrorConsoleOnly(object obj)
{
if (isLogConsole)
{
LogConsole(obj.ToString(), "[ERROR]", errorColor);
}
}
public virtual void LogInfoFileOnly(object obj)
{
Log($"[INFO] {obj}");
}
public virtual void LogWarningFileOnly(object obj)
{
Log($"[WARNING] {obj}");
}
public virtual void LogErrorFileOnly(object obj)
{
Log($"[ERROR] {obj}");
}
public virtual void LogClear()
{
if (path != null)
{
using (new StreamWriter(path))
{
}
}
}
}
public class HelperParse : IParseManager
{
private readonly ILogger logger;
public HelperParse(ILogger logger = null)
{
this.logger = logger;
}
public Type GetEnumUnderlyingType(Type type)
{
if (!type.IsEnum)
{
return type;
}
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (fields == null || fields.Length < 1)
{
return type;
}
return fields[0].FieldType;
}
public bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum))
{
Type typeFromHandle = typeof(TEnum);
try
{
Type enumUnderlyingType = GetEnumUnderlyingType(typeFromHandle);
if ((object)enumUnderlyingType == typeof(int))
{
if (int.TryParse(arg, out var result2) && Enum.IsDefined(typeFromHandle, result2))
{
result = (TEnum)Enum.ToObject(typeFromHandle, result2);
return true;
}
logger?.LogWarning("TryParseEnum can't parse int from " + arg + " for enum " + typeFromHandle.Name);
}
else if ((object)enumUnderlyingType == typeof(sbyte))
{
if (sbyte.TryParse(arg, out var result3) && Enum.IsDefined(typeFromHandle, result3))
{
result = (TEnum)Enum.ToObject(typeFromHandle, result3);
return true;
}
logger?.LogWarning("TryParseEnum can't parse sbyte from " + arg + " for enum " + typeFromHandle.Name);
}
else
{
foreach (TEnum value in Enum.GetValues(typeFromHandle))
{
if (Enum.GetName(typeFromHandle, value).Equals(arg, StringComparison.OrdinalIgnoreCase))
{
result = value;
return true;
}
}
logger?.LogWarning("TryParseEnum can't find item by direct name " + arg + " for enum " + typeFromHandle.Name);
}
}
catch (Exception arg2)
{
logger?.LogError($"TryParseEnum error happened when process {arg} for enum {typeFromHandle.Name}: {arg2}");
}
result = defaultValue;
return false;
}
public bool TryParseBool(string arg, out bool result, bool defaultValue = false)
{
if (bool.TryParse(arg, out result))
{
return true;
}
if (int.TryParse(arg, out var result2))
{
result = result2 != 0;
return true;
}
logger?.LogWarning($"TryParseBool error happened when process {arg}. Will be used default {defaultValue}");
result = defaultValue;
return false;
}
}
public class UtilityJson
{
private static Func<IJsonUtil> customGenerator;
public static IJsonUtil Generate(IDebugLogger logger)
{
if (customGenerator == null)
{
return new HelperJson(logger, File.Exists(".mod_json_debug"));
}
return customGenerator();
}
public static void RegisterCustomGenerator(Func<IJsonUtil> generator)
{
customGenerator = generator;
}
}
public class UtilitySettings
{
public static string CommandUpdateSettingsID => "command_update_parameters";
public static string BaseFolder { get; set; } = "ChaosTricks_InteractiveModData";
public static string SettingsFileName => "settings.txt";
public static string SettingsPath => Path.Combine(BaseFolder, SettingsFileName);
public static T LoadSettings<T>(IDebugLogger logger) where T : class
{
string text = string.Empty;
try
{
text = SettingsPath;
T result = UtilityJson.Generate(logger).FromFile<T>(text);
logger?.LogInfo("settings loaded");
return result;
}
catch (FileNotFoundException)
{
logger?.LogWarning("can't load settings. File not found at " + text + ". Using standard.");
}
catch (Exception arg)
{
logger?.LogError($"can't load settings. Using standard. \n{arg}");
}
T result2 = null;
try
{
result2 = Activator.CreateInstance<T>();
return result2;
}
catch (Exception arg2)
{
logger?.LogError($"can't create default data class. \n{arg2}");
}
return result2;
}
}
public enum Languages
{
ru,
en
}
public class Text
{
public string ru;
public string en;
public Text(string ru, string en)
{
this.ru = ru;
this.en = en;
}
public Text()
{
}
public string GetTrans(Languages lang)
{
if (lang != Languages.en)
{
return ru;
}
return en;
}
public string GetTrans(string lang)
{
if (GetLangFromAppLang(lang) != Languages.en)
{
return ru;
}
return en;
}
private Languages GetLangFromAppLang(string lang)
{
lang = lang?.Trim()?.ToLower();
switch (lang)
{
case "ru":
case "russian":
case "rus":
case "русский":
case "ру":
case "рус":
return Languages.ru;
default:
return Languages.en;
}
}
}
public class HelperLanguages : ITranslation
{
private readonly Dictionary<string, Text> transDict;
private readonly ILogger logger;
private readonly string errorString = "trans_error";
public HelperLanguages(ILogger logger, string langsDir, string langsFname = "langs.data")
{
this.logger = logger;
try
{
string path = Path.Combine(langsDir, langsFname);
IDictManager dictManager = new HelperDictManager(logger);
using (StreamReader streamReader = new StreamReader(path))
{
string data = streamReader.ReadToEnd();
Dictionary<string, string> source = dictManager.ParseDict(data);
transDict = GetTransDict(source);
}
logger?.LogInfo($"HelperLanguages: found translates {transDict.Count}");
}
catch (Exception arg)
{
logger?.LogError($"HelperLanguages load: {arg}");
transDict = new Dictionary<string, Text>(StringComparer.OrdinalIgnoreCase);
}
}
protected Dictionary<string, Text> GetTransDict(Dictionary<string, string> source)
{
Dictionary<string, Text> dictionary = new Dictionary<string, Text>(StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, string> item in source)
{
string[] array = item.Value.Split(new string[1] { "%lang%" }, StringSplitOptions.RemoveEmptyEntries);
if (array == null || array.Length != 2)
{
logger?.LogError("HelperLanguages parse item: " + item.Key);
continue;
}
string ru = array[0];
string en = array[1];
dictionary.Add(item.Key, new Text(ru, en));
}
return dictionary;
}
public string GetTrans(string key, Languages lang)
{
return GetTrans(key, lang.ToString());
}
public string GetTrans(string key, string lang)
{
try
{
key = key.Trim();
lang = lang.Trim();
return transDict[key].GetTrans(lang);
}
catch (Exception arg)
{
logger?.LogError($"HelperLanguages key {key} lang {lang}: {arg}");
return errorString;
}
}
public virtual void InitFromFile(string path)
{
throw new NotImplementedException();
}
public void InitFromString(string data)
{
throw new NotImplementedException();
}
}
}
namespace ModHelper.Interfaces
{
public interface ICommandTargets
{
bool IsAllPlayers { get; }
}
public interface IConsoleCommandWithData : IConsoleCommand
{
bool Execute(IEnumerable<string> args, IEventsData data);
}
public interface IConsoleCommand
{
string Id { get; }
bool Execute(IEnumerable<string> args);
bool IsValidCommandArgs(IEnumerable<string> args);
}
public interface IDebugLogger : ILoggerWithConsole, ILogger
{
void LogDebugInfo(object obj);
void LogDebugWarning(object obj);
void LogDebugError(object obj);
}
public interface ILoggerWithConsole : ILogger
{
void LogInfoConsoleOnly(object obj);
void LogWarningConsoleOnly(object obj);
void LogErrorConsoleOnly(object obj);
void LogInfoFileOnly(object obj);
void LogWarningFileOnly(object obj);
void LogErrorFileOnly(object obj);
}
public interface ICommandNotify
{
string ProcessMsg(string msg);
}
public interface ICommand
{
string Id { get; }
}
public interface IDictionaryItem<T>
{
string Key { get; }
T Value { get; }
}
public interface IJsonUtil
{
T FromFile<T>(string path) where T : class;
T FromString<T>(string s) where T : class;
}
public interface IDictManager
{
Dictionary<string, string> ParseDict(string data);
}
public interface ICommandManager
{
string GetCommandData(string eventKey, bool isLogError = false);
string[] GetCommands();
void InitFromString(string data);
void InitFromFile(string path);
}
public interface IEventManager<CustomEvent>
{
CustomEvent GetEvent(string eventID, bool isLogError = false);
IEnumerable<CustomEvent> GetEventsCollection();
}
public interface IEventWithData : IEvent
{
bool Execute(IEventsData data);
}
public interface IEvent
{
string Id { get; }
bool Execute();
}
public interface ILogger
{
void Log(object obj);
void LogInfo(object obj);
void LogWarning(object obj);
void LogError(object obj);
void LogClear();
}
public interface ITranslation
{
string GetTrans(string key, Languages lang);
string GetTrans(string key, string lang);
void InitFromString(string data);
void InitFromFile(string path);
}
public interface IParseManager
{
bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum));
bool TryParseBool(string arg, out bool result, bool defaultValue = false);
}
}using System;
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.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using EventsIO.Interfaces;
using ModHelper;
using ModHelper.Interfaces;
using ModHelperUnity.Data;
using ModHelperUnity.Interfaces;
using ModHelperUnity.UtilityGUI;
using Mono.Cecil;
using Mono.Cecil.Cil;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ModHelperUnity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyProduct("ModHelperUnity")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4afa0e1e-341b-4554-97c1-0c38ad74f246")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace ModHelperUnity
{
public abstract class TypedNotifyBase : MonoBehaviour, IComponentTypedNotify
{
private bool isDisposed;
private Queue<TypedNotifyMessage> messages;
private bool isInitiated;
private bool isMessageProcessed;
private float delayAfterNotify;
private bool isShowAnimationStageFinished;
private bool isShowMessageStageFinished;
private bool isHideAnimationStageFinished;
protected int logLimit;
protected IDebugLogger logger;
protected Dictionary<string, Texture2D> messageTextures = new Dictionary<string, Texture2D>();
public TypedNotifySettings Settings { get; protected set; }
protected TypedNotifyMessage CurrentMessage { get; private set; }
protected TypedNotifyParameters CurrentNotifyParameters { get; private set; }
protected virtual void Log(object obj)
{
IDebugLogger obj2 = logger;
if (obj2 != null)
{
((ILogger)obj2).LogInfo((object)$"TypedNotifyBase: {obj}");
}
}
protected virtual void LimitedLogError(object obj)
{
if (logLimit > 0 && logger != null)
{
((ILogger)logger).LogError((object)$"TypedNotifyBase: {obj}");
logLimit--;
}
}
protected virtual Texture2D GetMessageTexture(string type)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
if (messageTextures.ContainsKey(type))
{
return messageTextures[type];
}
return new Texture2D(2, 2);
}
protected void LoadFadeSettings(string settingsFilePath, Func<string, byte[]> customFileReader = null)
{
try
{
if (customFileReader == null)
{
Settings = UtilityJson.Generate(logger).FromFile<TypedNotifySettings>(settingsFilePath);
}
else
{
byte[] bytes = customFileReader(settingsFilePath);
string @string = Encoding.UTF8.GetString(bytes);
Settings = UtilityJson.Generate(logger).FromString<TypedNotifySettings>(@string);
}
}
catch (Exception arg)
{
Log($"LoadFadeSettings error: {arg}");
}
if (Settings == null)
{
Settings = new TypedNotifySettings();
}
}
protected Texture2D LoadImage(string imageFilePath, Func<string, byte[]> customFileReader = null)
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Expected O, but got Unknown
try
{
Texture2D val = UtilityUI.LoadImage(imageFilePath, customFileReader);
Log($"LoadImage {imageFilePath}: width {((Texture)val).width}, height {((Texture)val).height}");
return val;
}
catch (Exception arg)
{
Log($"LoadImage {imageFilePath} error: {arg}");
return new Texture2D(2, 2, (TextureFormat)4, false);
}
}
protected void LoadResources(string folderPath, Func<string, byte[]> customFileReader = null)
{
Log("LoadResources");
string text = "notify_settings.data";
string settingsFilePath = ((folderPath == null) ? text : Path.Combine(folderPath, text));
LoadFadeSettings(settingsFilePath, customFileReader);
ClearMessageTextures();
if (Settings.notifyParameters != null)
{
TypedNotifyParameters[] notifyParameters = Settings.notifyParameters;
foreach (TypedNotifyParameters typedNotifyParameters in notifyParameters)
{
Log(typedNotifyParameters.ToString());
string imageFilePath = ((folderPath == null) ? typedNotifyParameters.imageFileName : Path.Combine(folderPath, typedNotifyParameters.imageFileName));
Texture2D val = LoadImage(imageFilePath, customFileReader);
messageTextures[typedNotifyParameters.type] = val;
((Texture)val).filterMode = (FilterMode)2;
((Texture)val).anisoLevel = 16;
}
}
}
public virtual void PostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null)
{
if (!isInitiated)
{
ForcePostInit(folderPath, logger, customFileReader);
}
Log("post init completed");
}
public virtual void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null)
{
this.logger = logger;
try
{
messages = new Queue<TypedNotifyMessage>();
CurrentMessage = null;
CurrentNotifyParameters = new TypedNotifyParameters();
logLimit = 10;
isInitiated = true;
LoadResources(folderPath, customFileReader);
}
catch (Exception arg)
{
Log($"ForcePostInit error: {arg}");
}
Log("force init");
}
protected virtual string ProcessCustomTemplates(string message, IEventsData eventData, ITranslation translation)
{
try
{
return Regex.Replace(message, "%template_.+?%", (Match s) => translation.GetTrans(s.Value, eventData.Lang));
}
catch (Exception arg)
{
Log($"ProcessCustomTemplates error: {arg}");
return message;
}
}
protected virtual string GenerateMessage(IEventsData eventData, ITranslation translation)
{
//IL_002d: 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)
TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData);
string trans = translation.GetTrans(eventData.EventID, eventData.Lang);
string message = typedNotifyParameters.messageTemplate.Replace("%name%", UtilityUI.GetColoredText(eventData.Username, typedNotifyParameters.nicknameTextColor)).Replace("%message%", UtilityUI.GetColoredText(trans, typedNotifyParameters.messageTextColor));
return ProcessCustomTemplates(message, eventData, translation);
}
public virtual TypedNotifyParameters GetTypedNotifyParameters(string type)
{
TypedNotifyParameters[] notifyParameters = Settings.notifyParameters;
if (notifyParameters == null || notifyParameters.Length == 0)
{
Log("warning, notify types empty (use default)");
return new TypedNotifyParameters();
}
TypedNotifyParameters[] array = notifyParameters;
foreach (TypedNotifyParameters typedNotifyParameters in array)
{
if (typedNotifyParameters.type == type)
{
return typedNotifyParameters;
}
}
return notifyParameters[0];
}
public virtual TypedNotifyParameters GetTypedNotifyParameters(IEventsData eventData)
{
TypedNotifyParameters[] notifyParameters = Settings.notifyParameters;
if (notifyParameters == null || notifyParameters.Length == 0)
{
Log("warning, notify types empty (use default)");
return new TypedNotifyParameters();
}
TypedNotifyParameters[] array = notifyParameters;
foreach (TypedNotifyParameters typedNotifyParameters in array)
{
string[] events = typedNotifyParameters.events;
if (events != null && events.Contains(eventData.EventID))
{
return typedNotifyParameters;
}
}
return notifyParameters[0];
}
public virtual void AddNotifyToQueue(IEventsData eventData, ITranslation translation, Func<string, string> converter = null)
{
if (eventData == null)
{
Log("warning, eventData is null");
}
if (translation == null)
{
Log("warning, translation is null");
}
TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData);
string text = GenerateMessage(eventData, translation);
if (converter != null)
{
text = converter(text);
}
AddNotifyToQueue(new TypedNotifyMessage(text.ToUpperInvariant(), typedNotifyParameters.type, typedNotifyParameters.showMessageDuration, typedNotifyParameters.showFadeAnimationDuration, typedNotifyParameters.hideFadeAnimationDuration));
}
public virtual void AddNotifyToQueue(string message, string type)
{
TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(type);
AddNotifyToQueue(new TypedNotifyMessage(message, type, typedNotifyParameters.showMessageDuration, typedNotifyParameters.showFadeAnimationDuration, typedNotifyParameters.hideFadeAnimationDuration));
}
public virtual void AddNotifyToQueue(TypedNotifyMessage notifyMessage)
{
if (!isInitiated)
{
Log("error, attempt to use the manager before init completed");
return;
}
if (notifyMessage == null)
{
Log("error, message is null");
return;
}
messages.Enqueue(notifyMessage);
Log("add new notify message: " + notifyMessage.message);
}
public virtual void ClearNotifyQueue()
{
if (isInitiated)
{
messages.Clear();
}
}
public virtual void StopCurrentNotify()
{
CurrentMessage = null;
isShowAnimationStageFinished = true;
isShowMessageStageFinished = true;
isHideAnimationStageFinished = true;
isMessageProcessed = false;
}
protected virtual void Update()
{
try
{
if (!isInitiated)
{
return;
}
if (CurrentMessage == null)
{
if (delayAfterNotify > 0f)
{
delayAfterNotify -= Time.deltaTime;
}
else if (messages.Count > 0)
{
CurrentMessage = messages.Peek();
CurrentNotifyParameters = GetTypedNotifyParameters(CurrentMessage.messageType);
delayAfterNotify = CurrentNotifyParameters.delayAfterNotify;
StartShowAnimation();
}
return;
}
if (!isShowAnimationStageFinished)
{
UpdateProcessShowAnimation();
}
else if (!isShowMessageStageFinished)
{
UpdateProcessNoAnimationStage();
}
else if (!isHideAnimationStageFinished)
{
UpdateProcessHideAnimation();
}
if (isMessageProcessed)
{
messages.Dequeue();
CurrentMessage = null;
isMessageProcessed = false;
}
}
catch (Exception obj)
{
LimitedLogError(obj);
}
}
protected virtual void UpdateProcessShowAnimation()
{
if (CurrentMessage.showFadeAnimationDuration > 0f)
{
CurrentMessage.showFadeAnimationDuration -= Time.deltaTime;
}
else
{
FinishShowAnimation();
}
}
protected virtual void UpdateProcessNoAnimationStage()
{
if (CurrentMessage.showMessageDuration > 0f)
{
CurrentMessage.showMessageDuration -= Time.deltaTime;
}
else
{
StartHideAnimation();
}
}
protected virtual void UpdateProcessHideAnimation()
{
if (CurrentMessage.hideFadeAnimationDuration > 0f)
{
CurrentMessage.hideFadeAnimationDuration -= Time.deltaTime;
}
else
{
FinishHideAnimation();
}
}
protected virtual void Start()
{
}
protected virtual void Awake()
{
}
protected virtual void OnGUI()
{
}
protected virtual void StartShowAnimation()
{
isShowAnimationStageFinished = false;
Log("start show animation");
}
protected virtual void FinishShowAnimation()
{
isShowAnimationStageFinished = true;
isShowMessageStageFinished = false;
Log("finish show animation");
}
protected virtual void StartHideAnimation()
{
isHideAnimationStageFinished = false;
isShowMessageStageFinished = true;
Log("start hide animation");
}
protected virtual void FinishHideAnimation()
{
isHideAnimationStageFinished = true;
isMessageProcessed = true;
Log("finish hide animation");
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void ClearMessageTextures()
{
if (messageTextures == null)
{
return;
}
foreach (Texture2D value in messageTextures.Values)
{
((Object)value).hideFlags = (HideFlags)61;
Object.Destroy((Object)(object)value);
}
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
ClearMessageTextures();
messageTextures = null;
isDisposed = true;
}
}
~TypedNotifyBase()
{
try
{
Dispose(disposing: false);
}
finally
{
((object)this).Finalize();
}
}
}
public static class UtilityUI
{
public static int StandardScreenWidth => 2560;
public static int StandardScreenHeight => 1440;
public static string GetColoredText(string text, Color32 color)
{
//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)
string text2 = ColorUtility.ToHtmlStringRGBA(Color32.op_Implicit(color));
return "<color=#" + text2 + ">" + text + "</color>";
}
public static Texture2D LoadImage(string imageFilePath, Func<string, byte[]> customFileReader = null)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
//IL_0025: Expected O, but got Unknown
byte[] array = ((customFileReader == null) ? File.ReadAllBytes(imageFilePath) : customFileReader(imageFilePath));
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
ImageConversion.LoadImage(val, array);
return val;
}
public static float CalcScreenFactor(int baseScreenSize, int currentScreenSize)
{
if (baseScreenSize != currentScreenSize)
{
return (float)currentScreenSize / (float)baseScreenSize;
}
return 1f;
}
}
public class MathUtility
{
public static bool RandomBool()
{
return Random.value > 0.5f;
}
public static int GetRandomSign()
{
if (!RandomBool())
{
return 1;
}
return -1;
}
public static Vector3 GetRandomPointOnCircle(float radius = 1f)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//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)
Vector2 insideUnitCircle = Random.insideUnitCircle;
return Vector2.op_Implicit(((Vector2)(ref insideUnitCircle)).normalized * radius);
}
public static Vector3 GetRandomPointOnCircleInForward(Vector3 forward, float radiusMin, float radiusMax, float minAngleInDeg = -90f, float maxAngleInDeg = 90f)
{
//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_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: 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_0072: 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)
Vector3 val = forward;
val.y = 0f;
val = ((Vector3)(ref val)).normalized;
if (minAngleInDeg > maxAngleInDeg)
{
float num = minAngleInDeg;
minAngleInDeg = maxAngleInDeg;
maxAngleInDeg = num;
}
float num2 = Random.Range(minAngleInDeg, maxAngleInDeg);
if (radiusMin < 0f)
{
radiusMin = 0f;
}
if (radiusMax < 0f)
{
radiusMax = 1f;
}
if (radiusMin > radiusMax)
{
float num3 = radiusMin;
radiusMin = radiusMax;
radiusMax = num3;
}
float num4 = Random.Range(radiusMin, radiusMax);
Vector3 result = default(Vector3);
float num5 = (float)Math.PI / 180f * num2;
float num6 = Mathf.Atan2(val.z, val.x);
num5 += num6;
result.x = num4 * Mathf.Cos(num5);
result.z = num4 * Mathf.Sin(num5);
return result;
}
public static Vector3 FindRandomSpawnPointNearPosition(Vector3 pos, float minDistance, float maxDistance)
{
//IL_0024: 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_005f: 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_0085: Unknown result type (might be due to invalid IL or missing references)
if (maxDistance < 0f)
{
maxDistance = 10f;
}
if (minDistance < 0f || minDistance > maxDistance)
{
minDistance = 0f;
}
Vector3 result = default(Vector3);
float num = Random.Range(-(float)Math.PI, (float)Math.PI);
float num2 = Random.Range(minDistance, maxDistance);
result.x = Mathf.Floor(pos.x + num2 * Mathf.Cos(num));
result.z = Mathf.Floor(pos.z + num2 * Mathf.Sin(num));
result.y = pos.y;
return result;
}
public static Vector3 FindRandomSpawnPointNearPositionFixY(Vector3 pos, float minDistance, float maxDistance, float yFixOffset, LayerMask mask)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: 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_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_001e: 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_004c: 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)
Vector3 result = FindRandomSpawnPointNearPosition(pos, minDistance, maxDistance);
RaycastHit val = default(RaycastHit);
if (Physics.Raycast(pos + Vector3.up * 10f, Vector3.down, ref val, 10f, LayerMask.op_Implicit(mask)))
{
result = ((RaycastHit)(ref val)).point;
result.y += yFixOffset;
}
return result;
}
public static Vector3 GetRandomVector(Vector3 randomRangeMin, Vector3 randomRangeMax)
{
//IL_0000: 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)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: 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_0037: Unknown result type (might be due to invalid IL or missing references)
float num = Random.Range(randomRangeMin.x, randomRangeMax.x);
float num2 = Random.Range(randomRangeMin.y, randomRangeMax.y);
float num3 = Random.Range(randomRangeMin.z, randomRangeMax.z);
return new Vector3(num, num2, num3);
}
public static void LookAt(Transform obj, Transform target)
{
//IL_0001: 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_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: 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_0014: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = target.position - obj.position;
obj.rotation = Quaternion.LookRotation(val);
}
}
public static class Loader
{
private static GameObject hookObj;
private static readonly string AssemblyName;
private static readonly string ClassMod;
public static ILogger Logger { get; }
public static GameObject HookObj { get; set; }
static Loader()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
AssemblyName = "InteractiveMod";
ClassMod = AssemblyName;
Logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "loader_log.txt");
Logger.LogClear();
}
public static void LoadAssembly()
{
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
Logger.LogInfo((object)"Load mod assembly");
Assembly assembly = AppDomain.CurrentDomain.Load(AssemblyName);
if (string.Equals(assembly.GetName().Name, AssemblyName, StringComparison.OrdinalIgnoreCase))
{
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
bool num = string.Equals(type.Name, ClassMod, StringComparison.OrdinalIgnoreCase);
Type typeFromHandle = typeof(MonoBehaviour);
bool flag = type.IsAssignableFrom(typeFromHandle) || type.IsSubclassOf(typeFromHandle);
if (num && flag)
{
hookObj = new GameObject();
Component obj = hookObj.AddComponent(type);
Component obj2 = ((obj is MonoBehaviour) ? obj : null);
hookObj.SetActive(true);
((Behaviour)obj2).enabled = true;
Logger.LogInfo((object)"Loader init success");
return;
}
}
}
else
{
Logger.LogWarning((object)"Wrong assembly mod name");
}
Logger.LogError((object)"Init failed");
}
public static void Init()
{
Logger.LogClear();
Logger.LogInfo((object)"Loader triggered");
try
{
LoadAssembly();
}
catch (Exception arg)
{
Logger.LogError((object)$"ModHelperUnity.Init: {arg}");
}
}
}
public class Patcher
{
private readonly string nameModDll = "ModHelperUnity.dll";
private readonly string nameMod = "ModHelperUnity";
private readonly ILogger logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "patcher_log.txt");
public void ExecutePatch()
{
try
{
logger.LogClear();
logger.LogInfo((object)$"Patcher v{Assembly.GetExecutingAssembly().GetName().Version}");
bool flag = false;
string[] files = Directory.GetFiles(Directory.GetCurrentDirectory());
for (int i = 0; i < files.Length; i++)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(files[i]);
string path = Path.Combine(Environment.CurrentDirectory, fileNameWithoutExtension + "_Data");
path = Path.Combine(path, "Managed");
string text = "UnityEngine.CoreModule.dll";
string text2 = "UnityEngine.dll";
string fullPath = Path.GetFullPath(Path.Combine(path, text));
string fullPath2 = Path.GetFullPath(Path.Combine(path, text2));
if (!Directory.Exists(path) || (!File.Exists(fullPath2) && !File.Exists(fullPath)))
{
continue;
}
flag = true;
logger.LogInfo((object)("found game " + fileNameWithoutExtension));
logger.LogInfo((object)("target managed " + path));
logger.LogInfo((object)("try to patching " + text));
if (!PatchUnityEngine(path, fullPath, text))
{
logger.LogInfo((object)("try to patching " + text2));
if (!PatchUnityEngine(path, fullPath2, text2))
{
logger.LogWarning((object)"patching failed");
}
}
}
if (!flag)
{
logger.LogError((object)"didn't find any games to patch");
}
}
catch (Exception arg)
{
logger.LogError((object)$"Patcher unexpected error: {arg}");
}
}
private bool PatchUnityEngine(string managedDir, string unityOutputDll, string targetDllName)
{
try
{
string fullPath = Path.GetFullPath(Path.Combine(managedDir, targetDllName + ".bak"));
using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(unityOutputDll));
AssemblyDefinition val = AssemblyDefinition.ReadAssembly((Stream)memoryStream);
try
{
if (val == null)
{
logger.LogInfo((object)(unityOutputDll + " not found"));
return false;
}
if (IsNeedPatching(val))
{
AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(Path.Combine(Preloader.GetAssemblyModFolderFullPath(), nameModDll));
try
{
if (val2 == null)
{
return false;
}
logger.LogInfo((object)("found mod dll: " + val2.FullName));
logger.LogInfo((object)("try to backup into " + fullPath));
File.Copy(unityOutputDll, fullPath, overwrite: true);
InjectAssembly(val, val2);
val.Write(unityOutputDll);
}
finally
{
((IDisposable)val2)?.Dispose();
}
}
}
finally
{
((IDisposable)val)?.Dispose();
}
}
catch (Exception arg)
{
logger.LogError((object)$"Patcher: {arg}");
return false;
}
logger.LogInfo((object)"Patching successful finished");
return true;
}
private void InjectAssembly(AssemblyDefinition unity, AssemblyDefinition injected)
{
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Expected O, but got Unknown
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
logger.LogInfo((object)"InjectAssembly started");
MethodDefinition val = ((IEnumerable<MethodDefinition>)((IEnumerable<TypeDefinition>)injected.MainModule.Types).First((TypeDefinition x) => ((MemberReference)x).Name == "Loader").Methods).First((MethodDefinition x) => ((MemberReference)x).Name == "Init");
MethodReference val2 = unity.MainModule.ImportReference((MethodReference)(object)val);
logger.LogInfo((object)"try to find Application in unity");
TypeDefinition obj = ((IEnumerable<TypeDefinition>)unity.MainModule.Types).First((TypeDefinition x) => ((MemberReference)x).Name == "Application");
TypeReference val3 = unity.MainModule.ImportReference(typeof(void));
MethodDefinition val4 = new MethodDefinition(".cctor", (MethodAttributes)6289, val3);
ILProcessor iLProcessor = val4.Body.GetILProcessor();
iLProcessor.Append(iLProcessor.Create(OpCodes.Call, val2));
iLProcessor.Append(iLProcessor.Create(OpCodes.Ret));
obj.Methods.Add(val4);
logger.LogInfo((object)"injecting assembly finished");
}
private bool IsNeedPatching(AssemblyDefinition unity)
{
if (((IEnumerable<AssemblyNameReference>)unity.MainModule.AssemblyReferences).Any((AssemblyNameReference x) => x.Name.Contains(nameMod)))
{
logger.LogInfo((object)"this assembly has already been patched");
return false;
}
return true;
}
}
public class Preloader
{
private static string baseFolderFullPath;
private static readonly ILogger logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "preloader_log.txt");
public static string GetAssemblyModFolderFullPath()
{
return baseFolderFullPath;
}
public static void Main()
{
logger.LogClear();
logger.LogInfo((object)"Preloader main");
baseFolderFullPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
AppDomain.CurrentDomain.AssemblyResolve += ModAssemblyResolve;
new Patcher().ExecutePatch();
}
private static Assembly ModAssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
string text = Path.Combine(GetAssemblyModFolderFullPath(), new AssemblyName(args.Name).Name + ".dll");
logger.LogInfo((object)text);
if (File.Exists(text))
{
return Assembly.LoadFrom(text);
}
}
catch (Exception arg)
{
logger.LogError((object)$"error: {arg}");
}
return null;
}
}
}
namespace ModHelperUnity.UtilityGUI
{
public class TypedNotifyOnGUI : TypedNotifyBase
{
private float currentAlpha;
private float targetAlpha;
protected Dictionary<string, Font> fonts;
public override void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null)
{
base.ForcePostInit(folderPath, logger, customFileReader);
try
{
fonts = new Dictionary<string, Font>();
TypedNotifyParameters[] notifyParameters = base.Settings.notifyParameters;
foreach (TypedNotifyParameters typedNotifyParameters in notifyParameters)
{
try
{
string fontPath = typedNotifyParameters.fontPath;
if (!fonts.ContainsKey(fontPath))
{
Font val = Resources.Load<Font>(fontPath);
if ((Object)(object)val != (Object)null)
{
fonts.Add(fontPath, val);
}
}
}
catch (Exception arg)
{
if (logger != null)
{
((ILogger)logger).LogError((object)$"TypedNotifyOnGUI loading font: {arg}");
}
}
}
}
catch (Exception arg2)
{
if (logger != null)
{
((ILogger)logger).LogError((object)$"TypedNotifyOnGUI PostInit: {arg2}");
}
}
}
protected Font GetFont(string path, int size)
{
try
{
if (fonts.ContainsKey(path))
{
return fonts[path];
}
string key = $"{path}_{size}";
if (fonts.ContainsKey(key))
{
return fonts[key];
}
Font val = Font.CreateDynamicFontFromOSFont(path, size);
if ((Object)(object)val != (Object)null)
{
fonts.Add(key, val);
}
return val;
}
catch (Exception arg)
{
IDebugLogger obj = logger;
if (obj != null)
{
((ILogger)obj).LogError((object)$"finding font: {arg}");
}
}
return null;
}
protected virtual void SetupAlpha(float baseDuration)
{
if (!Mathf.Approximately(currentAlpha, targetAlpha))
{
currentAlpha = Mathf.MoveTowards(currentAlpha, targetAlpha, Time.deltaTime / baseDuration);
}
}
protected override void UpdateProcessShowAnimation()
{
SetupAlpha(base.CurrentNotifyParameters.showFadeAnimationDuration);
base.UpdateProcessShowAnimation();
}
protected override void UpdateProcessNoAnimationStage()
{
SetupAlpha(base.CurrentNotifyParameters.showMessageDuration);
base.UpdateProcessNoAnimationStage();
}
protected override void UpdateProcessHideAnimation()
{
SetupAlpha(base.CurrentNotifyParameters.hideFadeAnimationDuration);
base.UpdateProcessHideAnimation();
}
protected override void StartShowAnimation()
{
base.StartShowAnimation();
targetAlpha = 1f;
}
protected override void StartHideAnimation()
{
base.StartHideAnimation();
targetAlpha = 0f;
}
protected string GetFadedText(string text)
{
string text2 = ((int)(255f * currentAlpha)).ToString("X2");
return text.Replace("FF>", text2 + ">");
}
protected override void OnGUI()
{
//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_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Expected O, but got Unknown
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
base.OnGUI();
TypedNotifyParameters currentNotifyParameters = base.CurrentNotifyParameters;
if (!base.Settings.isDisableNotify && base.CurrentMessage != null && currentNotifyParameters != null && !currentNotifyParameters.isDisable)
{
Matrix4x4 matrix = GUI.matrix;
Color color = GUI.color;
color.a = currentAlpha;
GUI.color = color;
Texture2D messageTexture = GetMessageTexture(base.CurrentMessage.messageType);
float num = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenWidth, Screen.width);
float num2 = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenHeight, Screen.height);
float num3 = (float)((Texture)messageTexture).width * num;
float num4 = (float)((Texture)messageTexture).height * num2;
Rect val = default(Rect);
((Rect)(ref val)).x = ((float)Screen.width - num3) * (0.5f + currentNotifyParameters.notifyHorizontalOffset);
((Rect)(ref val)).y = ((float)Screen.height - num4) * (0.5f + currentNotifyParameters.notifyVerticalOffset);
((Rect)(ref val)).width = num3;
((Rect)(ref val)).height = num4;
Rect val2 = val;
float num5 = Math.Min(num, num2);
float num6 = Math.Max(num, num2);
int num7 = (int)((float)currentNotifyParameters.fontSize * num5);
GUIStyle val3 = new GUIStyle(GUI.skin.label)
{
fontSize = num7,
alignment = (TextAnchor)4,
richText = true,
fixedWidth = num3,
fixedHeight = num4
};
Font font = GetFont(currentNotifyParameters.fontPath, num7);
if ((Object)(object)font != (Object)null)
{
val3.font = font;
}
val3.padding.top = (int)((float)currentNotifyParameters.textPadding.top * num6);
val3.padding.bottom = (int)((float)currentNotifyParameters.textPadding.bottom * num6);
val3.padding.left = (int)((float)currentNotifyParameters.textPadding.left * num6);
val3.padding.right = (int)((float)currentNotifyParameters.textPadding.right * num6);
val3.normal.textColor = color;
GUI.DrawTexture(val2, (Texture)(object)messageTexture);
GUI.Label(val2, GetFadedText(base.CurrentMessage.message), val3);
GUI.matrix = matrix;
}
}
}
public class TypedNotifySettings
{
public bool isDisableNotify;
public TypedNotifyParameters[] notifyParameters = new TypedNotifyParameters[0];
public override string ToString()
{
if (notifyParameters == null)
{
return "TypedNotifySettings: not found notifyParameters";
}
string text = $"isDisableNotify={isDisableNotify}";
TypedNotifyParameters[] array = notifyParameters;
for (int i = 0; i < array.Length; i++)
{
_ = array[i];
text = string.Join(Environment.NewLine, text, "notifyParameters:", notifyParameters.ToString());
}
return text;
}
}
}
namespace ModHelperUnity.Interfaces
{
public interface IComponentTypedNotify
{
void AddNotifyToQueue(string message, string type);
void AddNotifyToQueue(IEventsData eventData, ITranslation translation, Func<string, string> converter = null);
void ClearNotifyQueue();
void StopCurrentNotify();
void PostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null);
void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null);
}
public interface ISoundManager
{
void PlaySound(string path, int volume = 50);
void StopSound();
}
public interface IDictionaryItemJson<T>
{
string Key { get; }
T Value { get; }
}
}
namespace ModHelperUnity.Data
{
public class TypedNotifyParameters
{
public bool isDisable;
public string imageFileName = string.Empty;
public string type = "default";
public string messageTemplate = "%name% %message%";
public string fontPath = "";
public float showMessageDuration = 5f;
public float showFadeAnimationDuration = 1f;
public float hideFadeAnimationDuration = 1f;
public float delayAfterNotify = 1f;
public float notifyHorizontalOffset;
public float notifyVerticalOffset = -0.45f;
public int fontSize = 19;
public Padding textPadding = new Padding
{
bottom = 20,
top = 20,
left = 24,
right = 24
};
public Color32 nicknameTextColor = new Color32((byte)65, (byte)160, (byte)94, byte.MaxValue);
public Color32 messageTextColor = new Color32((byte)65, (byte)160, (byte)94, byte.MaxValue);
public string[] events = new string[0];
public override string ToString()
{
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
return string.Join(Environment.NewLine, "imageFileName: " + imageFileName, "type: " + type, $"showMessageDuration: {showMessageDuration}", $"showFadeAnimationDuration: {showFadeAnimationDuration}", $"hideFadeAnimationDuration: {hideFadeAnimationDuration}", $"delayAfterNotify: {delayAfterNotify}", $"notifyHorizontalOffset: {notifyHorizontalOffset}", $"notifyVerticalOffset: {notifyVerticalOffset}", $"textPadding: {textPadding}", $"fontSize: {fontSize}", $"isDisable: {isDisable}", $"nicknameTextColor: {nicknameTextColor}", $"messageTextColor: {messageTextColor}", "events: " + string.Join(Environment.NewLine, events), "fontPath: " + fontPath);
}
}
public class Padding
{
public int left;
public int right;
public int top;
public int bottom;
public Padding()
{
}
public Padding(int left, int right, int top, int bottom)
{
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
}
public RectOffset GetRect()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
return new RectOffset(left, right, top, bottom);
}
public override string ToString()
{
return $"left: {left}, right: {right}, top: {top}, bottom: {bottom}";
}
}
public class TypedNotifyMessage
{
public readonly string message;
public readonly string messageType;
public float showMessageDuration;
public float showFadeAnimationDuration;
public float hideFadeAnimationDuration;
public TypedNotifyMessage(string message, string messageType, float showMessageDuration, float showFadeAnimationDuration, float hideFadeAnimationDuration)
{
this.message = (string.IsNullOrEmpty(message?.Trim()) ? string.Empty : message);
this.messageType = messageType;
this.showMessageDuration = showMessageDuration;
this.showFadeAnimationDuration = showFadeAnimationDuration;
this.hideFadeAnimationDuration = hideFadeAnimationDuration;
}
}
public class NotifyMessage
{
private readonly string msg;
private float duration;
public NotifyMessage(string msg, float duration)
{
this.msg = (string.IsNullOrEmpty(msg?.Trim()) ? string.Empty : msg);
this.duration = duration;
}
public string GetMessage()
{
return msg;
}
public bool IsFinished()
{
return duration <= 0f;
}
public void OnFrame(float dt)
{
if (!IsFinished())
{
duration -= dt;
}
}
}
}using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Timers;
using WebSocketSharp.Net;
using WebSocketSharp.Net.WebSockets;
using WebSocketSharp.Server;
[assembly: AssemblyProduct("websocket-sharp.dll")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCopyright("sta.blockhead")]
[assembly: AssemblyTrademark("")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyTitle("websocket-sharp")]
[assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyVersion("1.0.2.59611")]
namespace WebSocketSharp
{
public static class Ext
{
private const string _tspecials = "()<>@,;:\\\"/[]?={} \t";
private static readonly byte[] _last;
private static readonly int _retry;
private static byte[] compress(this byte[] data)
{
if (data.LongLength == 0)
{
return data;
}
using MemoryStream stream = new MemoryStream(data);
return stream.compressToArray();
}
private static MemoryStream compress(this Stream stream)
{
MemoryStream memoryStream = new MemoryStream();
if (stream.Length == 0)
{
return memoryStream;
}
stream.Position = 0L;
using DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress, leaveOpen: true);
CopyTo(stream, deflateStream, 1024);
deflateStream.Close();
memoryStream.Write(_last, 0, 1);
memoryStream.Position = 0L;
return memoryStream;
}
private static byte[] compressToArray(this Stream stream)
{
using MemoryStream memoryStream = stream.compress();
memoryStream.Close();
return memoryStream.ToArray();
}
private static byte[] decompress(this byte[] data)
{
if (data.LongLength == 0)
{
return data;
}
using MemoryStream stream = new MemoryStream(data);
return stream.decompressToArray();
}
private static MemoryStream decompress(this Stream stream)
{
MemoryStream memoryStream = new MemoryStream();
if (stream.Length == 0)
{
return memoryStream;
}
stream.Position = 0L;
using DeflateStream source = new DeflateStream(stream, CompressionMode.Decompress, leaveOpen: true);
CopyTo(source, memoryStream, 1024);
memoryStream.Position = 0L;
return memoryStream;
}
private static byte[] decompressToArray(this Stream stream)
{
using MemoryStream memoryStream = stream.decompress();
memoryStream.Close();
return memoryStream.ToArray();
}
private static void times(this ulong n, Action action)
{
for (ulong num = 0uL; num < n; num++)
{
action();
}
}
internal static byte[] Append(this ushort code, string reason)
{
byte[] array = code.InternalToByteArray(ByteOrder.Big);
if (reason != null && reason.Length > 0)
{
List<byte> list = new List<byte>(array);
list.AddRange(Encoding.UTF8.GetBytes(reason));
array = list.ToArray();
}
return array;
}
internal static string CheckIfAvailable(this ServerState state, bool ready, bool start, bool shutting)
{
return ((!ready && (state == ServerState.Ready || state == ServerState.Stop)) || (!start && state == ServerState.Start) || (!shutting && state == ServerState.ShuttingDown)) ? ("This operation isn't available in: " + state.ToString().ToLower()) : null;
}
internal static string CheckIfAvailable(this WebSocketState state, bool connecting, bool open, bool closing, bool closed)
{
return ((!connecting && state == WebSocketState.Connecting) || (!open && state == WebSocketState.Open) || (!closing && state == WebSocketState.Closing) || (!closed && state == WebSocketState.Closed)) ? ("This operation isn't available in: " + state.ToString().ToLower()) : null;
}
internal static string CheckIfValidProtocols(this string[] protocols)
{
return protocols.Contains((string protocol) => protocol == null || protocol.Length == 0 || !protocol.IsToken()) ? "Contains an invalid value." : (protocols.ContainsTwice() ? "Contains a value twice." : null);
}
internal static string CheckIfValidServicePath(this string path)
{
return (path == null || path.Length == 0) ? "'path' is null or empty." : ((path[0] != '/') ? "'path' isn't an absolute path." : ((path.IndexOfAny(new char[2] { '?', '#' }) > -1) ? "'path' includes either or both query and fragment components." : null));
}
internal static string CheckIfValidSessionID(this string id)
{
return (id == null || id.Length == 0) ? "'id' is null or empty." : null;
}
internal static string CheckIfValidWaitTime(this TimeSpan time)
{
return (time <= TimeSpan.Zero) ? "A wait time is zero or less." : null;
}
internal static bool CheckWaitTime(this TimeSpan time, out string message)
{
message = null;
if (time <= TimeSpan.Zero)
{
message = "A wait time is zero or less.";
return false;
}
return true;
}
internal static void Close(this WebSocketSharp.Net.HttpListenerResponse response, WebSocketSharp.Net.HttpStatusCode code)
{
response.StatusCode = (int)code;
response.OutputStream.Close();
}
internal static void CloseWithAuthChallenge(this WebSocketSharp.Net.HttpListenerResponse response, string challenge)
{
response.Headers.InternalSet("WWW-Authenticate", challenge, response: true);
response.Close(WebSocketSharp.Net.HttpStatusCode.Unauthorized);
}
internal static byte[] Compress(this byte[] data, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? data.compress() : data;
}
internal static Stream Compress(this Stream stream, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? stream.compress() : stream;
}
internal static byte[] CompressToArray(this Stream stream, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? stream.compressToArray() : stream.ToByteArray();
}
internal static bool Contains<T>(this IEnumerable<T> source, Func<T, bool> condition)
{
foreach (T item in source)
{
if (condition(item))
{
return true;
}
}
return false;
}
internal static bool ContainsTwice(this string[] values)
{
int len = values.Length;
Func<int, bool> contains = null;
contains = delegate(int idx)
{
if (idx < len - 1)
{
for (int i = idx + 1; i < len; i++)
{
if (values[i] == values[idx])
{
return true;
}
}
return contains(++idx);
}
return false;
};
return contains(0);
}
internal static T[] Copy<T>(this T[] source, long length)
{
T[] array = new T[length];
Array.Copy(source, 0L, array, 0L, length);
return array;
}
internal static void CopyTo(this Stream source, Stream destination, int bufferLength)
{
byte[] buffer = new byte[bufferLength];
int num = 0;
while ((num = source.Read(buffer, 0, bufferLength)) > 0)
{
destination.Write(buffer, 0, num);
}
}
internal static void CopyToAsync(this Stream source, Stream destination, int bufferLength, Action completed, Action<Exception> error)
{
byte[] buff = new byte[bufferLength];
AsyncCallback callback = null;
callback = delegate(IAsyncResult ar)
{
try
{
int num = source.EndRead(ar);
if (num <= 0)
{
if (completed != null)
{
completed();
}
}
else
{
destination.Write(buff, 0, num);
source.BeginRead(buff, 0, bufferLength, callback, null);
}
}
catch (Exception obj2)
{
if (error != null)
{
error(obj2);
}
}
};
try
{
source.BeginRead(buff, 0, bufferLength, callback, null);
}
catch (Exception obj)
{
if (error != null)
{
error(obj);
}
}
}
internal static byte[] Decompress(this byte[] data, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? data.decompress() : data;
}
internal static Stream Decompress(this Stream stream, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? stream.decompress() : stream;
}
internal static byte[] DecompressToArray(this Stream stream, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? stream.decompressToArray() : stream.ToByteArray();
}
internal static bool EqualsWith(this int value, char c, Action<int> action)
{
action(value);
return value == c;
}
internal static string GetAbsolutePath(this Uri uri)
{
if (uri.IsAbsoluteUri)
{
return uri.AbsolutePath;
}
string originalString = uri.OriginalString;
if (originalString[0] != '/')
{
return null;
}
int num = originalString.IndexOfAny(new char[2] { '?', '#' });
return (num > 0) ? originalString.Substring(0, num) : originalString;
}
internal static string GetMessage(this CloseStatusCode code)
{
return code switch
{
CloseStatusCode.TlsHandshakeFailure => "An error has occurred during a TLS handshake.",
CloseStatusCode.ServerError => "WebSocket server got an internal error.",
CloseStatusCode.MandatoryExtension => "WebSocket client didn't receive expected extension(s).",
CloseStatusCode.TooBig => "A too big message has been received.",
CloseStatusCode.PolicyViolation => "A policy violation has occurred.",
CloseStatusCode.InvalidData => "Invalid data has been received.",
CloseStatusCode.Abnormal => "An exception has occurred.",
CloseStatusCode.UnsupportedData => "Unsupported data has been received.",
CloseStatusCode.ProtocolError => "A WebSocket protocol error has occurred.",
_ => string.Empty,
};
}
internal static string GetName(this string nameAndValue, char separator)
{
int num = nameAndValue.IndexOf(separator);
return (num > 0) ? nameAndValue.Substring(0, num).Trim() : null;
}
internal static string GetValue(this string nameAndValue, char separator)
{
int num = nameAndValue.IndexOf(separator);
return (num > -1 && num < nameAndValue.Length - 1) ? nameAndValue.Substring(num + 1).Trim() : null;
}
internal static string GetValue(this string nameAndValue, char separator, bool unquote)
{
int num = nameAndValue.IndexOf(separator);
if (num < 0 || num == nameAndValue.Length - 1)
{
return null;
}
string text = nameAndValue.Substring(num + 1).Trim();
return unquote ? text.Unquote() : text;
}
internal static TcpListenerWebSocketContext GetWebSocketContext(this TcpClient tcpClient, string protocol, bool secure, ServerSslConfiguration sslConfig, Logger logger)
{
return new TcpListenerWebSocketContext(tcpClient, protocol, secure, sslConfig, logger);
}
internal static byte[] InternalToByteArray(this ushort value, ByteOrder order)
{
byte[] bytes = BitConverter.GetBytes(value);
if (!order.IsHostOrder())
{
Array.Reverse((Array)bytes);
}
return bytes;
}
internal static byte[] InternalToByteArray(this ulong value, ByteOrder order)
{
byte[] bytes = BitConverter.GetBytes(value);
if (!order.IsHostOrder())
{
Array.Reverse((Array)bytes);
}
return bytes;
}
internal static bool IsCompressionExtension(this string value, CompressionMethod method)
{
return value.StartsWith(method.ToExtensionString());
}
internal static bool IsControl(this byte opcode)
{
return opcode > 7 && opcode < 16;
}
internal static bool IsControl(this Opcode opcode)
{
return (int)opcode >= 8;
}
internal static bool IsData(this byte opcode)
{
return opcode == 1 || opcode == 2;
}
internal static bool IsData(this Opcode opcode)
{
return opcode == Opcode.Text || opcode == Opcode.Binary;
}
internal static bool IsPortNumber(this int value)
{
return value > 0 && value < 65536;
}
internal static bool IsReserved(this ushort code)
{
return code == 1004 || code == 1005 || code == 1006 || code == 1015;
}
internal static bool IsReserved(this CloseStatusCode code)
{
return code == CloseStatusCode.Undefined || code == CloseStatusCode.NoStatus || code == CloseStatusCode.Abnormal || code == CloseStatusCode.TlsHandshakeFailure;
}
internal static bool IsSupported(this byte opcode)
{
return Enum.IsDefined(typeof(Opcode), opcode);
}
internal static bool IsText(this string value)
{
int length = value.Length;
for (int i = 0; i < length; i++)
{
char c = value[i];
if (c < ' ' && !Contains("\r\n\t", c))
{
return false;
}
switch (c)
{
case '\u007f':
return false;
case '\n':
if (++i < length)
{
c = value[i];
if (!Contains(" \t", c))
{
return false;
}
}
break;
}
}
return true;
}
internal static bool IsToken(this string value)
{
foreach (char c in value)
{
if (c < ' ' || c >= '\u007f' || Contains("()<>@,;:\\\"/[]?={} \t", c))
{
return false;
}
}
return true;
}
internal static string Quote(this string value)
{
return string.Format("\"{0}\"", value.Replace("\"", "\\\""));
}
internal static byte[] ReadBytes(this Stream stream, int length)
{
byte[] array = new byte[length];
int num = 0;
try
{
int num2 = 0;
while (length > 0)
{
num2 = stream.Read(array, num, length);
if (num2 == 0)
{
break;
}
num += num2;
length -= num2;
}
}
catch
{
}
return array.SubArray(0, num);
}
internal static byte[] ReadBytes(this Stream stream, long length, int bufferLength)
{
using MemoryStream memoryStream = new MemoryStream();
try
{
byte[] buffer = new byte[bufferLength];
int num = 0;
while (length > 0)
{
if (length < bufferLength)
{
bufferLength = (int)length;
}
num = stream.Read(buffer, 0, bufferLength);
if (num == 0)
{
break;
}
memoryStream.Write(buffer, 0, num);
length -= num;
}
}
catch
{
}
memoryStream.Close();
return memoryStream.ToArray();
}
internal static void ReadBytesAsync(this Stream stream, int length, Action<byte[]> completed, Action<Exception> error)
{
byte[] buff = new byte[length];
int offset = 0;
int retry = 0;
AsyncCallback callback = null;
callback = delegate(IAsyncResult ar)
{
try
{
int num = stream.EndRead(ar);
if (num == 0 && retry < _retry)
{
retry++;
stream.BeginRead(buff, offset, length, callback, null);
}
else if (num == 0 || num == length)
{
if (completed != null)
{
completed(buff.SubArray(0, offset + num));
}
}
else
{
retry = 0;
offset += num;
length -= num;
stream.BeginRead(buff, offset, length, callback, null);
}
}
catch (Exception obj2)
{
if (error != null)
{
error(obj2);
}
}
};
try
{
stream.BeginRead(buff, offset, length, callback, null);
}
catch (Exception obj)
{
if (error != null)
{
error(obj);
}
}
}
internal static void ReadBytesAsync(this Stream stream, long length, int bufferLength, Action<byte[]> completed, Action<Exception> error)
{
MemoryStream dest = new MemoryStream();
byte[] buff = new byte[bufferLength];
int retry = 0;
Action<long> read = null;
read = delegate(long len)
{
if (len < bufferLength)
{
bufferLength = (int)len;
}
stream.BeginRead(buff, 0, bufferLength, delegate(IAsyncResult ar)
{
try
{
int num = stream.EndRead(ar);
if (num > 0)
{
dest.Write(buff, 0, num);
}
if (num == 0 && retry < _retry)
{
retry++;
read(len);
}
else if (num == 0 || num == len)
{
if (completed != null)
{
dest.Close();
completed(dest.ToArray());
}
dest.Dispose();
}
else
{
retry = 0;
read(len - num);
}
}
catch (Exception obj2)
{
dest.Dispose();
if (error != null)
{
error(obj2);
}
}
}, null);
};
try
{
read(length);
}
catch (Exception obj)
{
dest.Dispose();
if (error != null)
{
error(obj);
}
}
}
internal static string RemovePrefix(this string value, params string[] prefixes)
{
int num = 0;
foreach (string text in prefixes)
{
if (value.StartsWith(text))
{
num = text.Length;
break;
}
}
return (num > 0) ? value.Substring(num) : value;
}
internal static T[] Reverse<T>(this T[] array)
{
int num = array.Length;
T[] array2 = new T[num];
int num2 = num - 1;
for (int i = 0; i <= num2; i++)
{
array2[i] = array[num2 - i];
}
return array2;
}
internal static IEnumerable<string> SplitHeaderValue(this string value, params char[] separators)
{
int len = value.Length;
string seps = new string(separators);
StringBuilder buff = new StringBuilder(32);
bool escaped = false;
bool quoted = false;
for (int i = 0; i < len; i++)
{
char c = value[i];
switch (c)
{
case '"':
if (escaped)
{
escaped = !escaped;
}
else
{
quoted = !quoted;
}
break;
case '\\':
if (i < len - 1 && value[i + 1] == '"')
{
escaped = true;
}
break;
default:
if (Contains(seps, c) && !quoted)
{
yield return buff.ToString();
buff.Length = 0;
continue;
}
break;
}
buff.Append(c);
}
if (buff.Length > 0)
{
yield return buff.ToString();
}
}
internal static byte[] ToByteArray(this Stream stream)
{
using MemoryStream memoryStream = new MemoryStream();
stream.Position = 0L;
CopyTo(stream, memoryStream, 1024);
memoryStream.Close();
return memoryStream.ToArray();
}
internal static CompressionMethod ToCompressionMethod(this string value)
{
foreach (CompressionMethod value2 in Enum.GetValues(typeof(CompressionMethod)))
{
if (value2.ToExtensionString() == value)
{
return value2;
}
}
return CompressionMethod.None;
}
internal static string ToExtensionString(this CompressionMethod method, params string[] parameters)
{
if (method == CompressionMethod.None)
{
return string.Empty;
}
string text = $"permessage-{method.ToString().ToLower()}";
if (parameters == null || parameters.Length == 0)
{
return text;
}
return string.Format("{0}; {1}", text, parameters.ToString("; "));
}
internal static IPAddress ToIPAddress(this string hostnameOrAddress)
{
if (IPAddress.TryParse(hostnameOrAddress, out IPAddress address))
{
return address;
}
try
{
return Dns.GetHostAddresses(hostnameOrAddress)[0];
}
catch
{
return null;
}
}
internal static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
return new List<TSource>(source);
}
internal static ushort ToUInt16(this byte[] source, ByteOrder sourceOrder)
{
return BitConverter.ToUInt16(source.ToHostOrder(sourceOrder), 0);
}
internal static ulong ToUInt64(this byte[] source, ByteOrder sourceOrder)
{
return BitConverter.ToUInt64(source.ToHostOrder(sourceOrder), 0);
}
internal static string TrimEndSlash(this string value)
{
value = value.TrimEnd(new char[1] { '/' });
return (value.Length > 0) ? value : "/";
}
internal static bool TryCreateWebSocketUri(this string uriString, out Uri result, out string message)
{
result = null;
Uri uri = uriString.ToUri();
if (uri == null)
{
message = "An invalid URI string: " + uriString;
return false;
}
if (!uri.IsAbsoluteUri)
{
message = "Not an absolute URI: " + uriString;
return false;
}
string scheme = uri.Scheme;
if (!(scheme == "ws") && !(scheme == "wss"))
{
message = "The scheme part isn't 'ws' or 'wss': " + uriString;
return false;
}
if (uri.Fragment.Length > 0)
{
message = "Includes the fragment component: " + uriString;
return false;
}
int port = uri.Port;
if (port == 0)
{
message = "The port part is zero: " + uriString;
return false;
}
result = ((port != -1) ? uri : new Uri(string.Format("{0}://{1}:{2}{3}", scheme, uri.Host, (scheme == "ws") ? 80 : 443, uri.PathAndQuery)));
message = string.Empty;
return true;
}
internal static string Unquote(this string value)
{
int num = value.IndexOf('"');
if (num < 0)
{
return value;
}
int num2 = value.LastIndexOf('"');
int num3 = num2 - num - 1;
return (num3 < 0) ? value : ((num3 == 0) ? string.Empty : value.Substring(num + 1, num3).Replace("\\\"", "\""));
}
internal static string UTF8Decode(this byte[] bytes)
{
try
{
return Encoding.UTF8.GetString(bytes);
}
catch
{
return null;
}
}
internal static byte[] UTF8Encode(this string s)
{
return Encoding.UTF8.GetBytes(s);
}
internal static void WriteBytes(this Stream stream, byte[] bytes, int bufferLength)
{
using MemoryStream source = new MemoryStream(bytes);
CopyTo(source, stream, bufferLength);
}
internal static void WriteBytesAsync(this Stream stream, byte[] bytes, int bufferLength, Action completed, Action<Exception> error)
{
MemoryStream input = new MemoryStream(bytes);
input.CopyToAsync(stream, bufferLength, delegate
{
if (completed != null)
{
completed();
}
input.Dispose();
}, delegate(Exception ex)
{
input.Dispose();
if (error != null)
{
error(ex);
}
});
}
public static bool Contains(this string value, params char[] chars)
{
return chars == null || chars.Length == 0 || (value != null && value.Length != 0 && value.IndexOfAny(chars) > -1);
}
public static bool Contains(this NameValueCollection collection, string name)
{
return collection != null && collection.Count > 0 && collection[name] != null;
}
public static bool Contains(this NameValueCollection collection, string name, string value)
{
if (collection == null || collection.Count == 0)
{
return false;
}
string text = collection[name];
if (text == null)
{
return false;
}
string[] array = text.Split(new char[1] { ',' });
foreach (string text2 in array)
{
if (text2.Trim().Equals(value, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
public static void Emit(this EventHandler eventHandler, object sender, EventArgs e)
{
eventHandler?.Invoke(sender, e);
}
public static void Emit<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e) where TEventArgs : EventArgs
{
eventHandler?.Invoke(sender, e);
}
public static WebSocketSharp.Net.CookieCollection GetCookies(this NameValueCollection headers, bool response)
{
string name = (response ? "Set-Cookie" : "Cookie");
return (headers != null && headers.Contains(name)) ? WebSocketSharp.Net.CookieCollection.Parse(headers[name], response) : new WebSocketSharp.Net.CookieCollection();
}
public static string GetDescription(this WebSocketSharp.Net.HttpStatusCode code)
{
return ((int)code).GetStatusDescription();
}
public static string GetStatusDescription(this int code)
{
return code switch
{
100 => "Continue",
101 => "Switching Protocols",
102 => "Processing",
200 => "OK",
201 => "Created",
202 => "Accepted",
203 => "Non-Authoritative Information",
204 => "No Content",
205 => "Reset Content",
206 => "Partial Content",
207 => "Multi-Status",
300 => "Multiple Choices",
301 => "Moved Permanently",
302 => "Found",
303 => "See Other",
304 => "Not Modified",
305 => "Use Proxy",
307 => "Temporary Redirect",
400 => "Bad Request",
401 => "Unauthorized",
402 => "Payment Required",
403 => "Forbidden",
404 => "Not Found",
405 => "Method Not Allowed",
406 => "Not Acceptable",
407 => "Proxy Authentication Required",
408 => "Request Timeout",
409 => "Conflict",
410 => "Gone",
411 => "Length Required",
412 => "Precondition Failed",
413 => "Request Entity Too Large",
414 => "Request-Uri Too Long",
415 => "Unsupported Media Type",
416 => "Requested Range Not Satisfiable",
417 => "Expectation Failed",
422 => "Unprocessable Entity",
423 => "Locked",
424 => "Failed Dependency",
500 => "Internal Server Error",
501 => "Not Implemented",
502 => "Bad Gateway",
503 => "Service Unavailable",
504 => "Gateway Timeout",
505 => "Http Version Not Supported",
507 => "Insufficient Storage",
_ => string.Empty,
};
}
public static bool IsCloseStatusCode(this ushort value)
{
return value > 999 && value < 5000;
}
public static bool IsEnclosedIn(this string value, char c)
{
return value != null && value.Length > 1 && value[0] == c && value[value.Length - 1] == c;
}
public static bool IsHostOrder(this ByteOrder order)
{
return !(BitConverter.IsLittleEndian ^ (order == ByteOrder.Little));
}
public static bool IsLocal(this IPAddress address)
{
if (address == null)
{
return false;
}
if (address.Equals(IPAddress.Any))
{
return true;
}
if (address.Equals(IPAddress.Loopback))
{
return true;
}
if (Socket.OSSupportsIPv6)
{
if (address.Equals(IPAddress.IPv6Any))
{
return true;
}
if (address.Equals(IPAddress.IPv6Loopback))
{
return true;
}
}
string hostName = Dns.GetHostName();
IPAddress[] hostAddresses = Dns.GetHostAddresses(hostName);
IPAddress[] array = hostAddresses;
foreach (IPAddress obj in array)
{
if (address.Equals(obj))
{
return true;
}
}
return false;
}
public static bool IsNullOrEmpty(this string value)
{
return value == null || value.Length == 0;
}
public static bool IsPredefinedScheme(this string value)
{
if (value == null || value.Length < 2)
{
return false;
}
char c = value[0];
if (c == 'h')
{
return value == "http" || value == "https";
}
if (c == 'w')
{
return value == "ws" || value == "wss";
}
if (c == 'f')
{
return value == "file" || value == "ftp";
}
if (c == 'n')
{
c = value[1];
return (c != 'e') ? (value == "nntp") : (value == "news" || value == "net.pipe" || value == "net.tcp");
}
return (c == 'g' && value == "gopher") || (c == 'm' && value == "mailto");
}
public static bool IsUpgradeTo(this WebSocketSharp.Net.HttpListenerRequest request, string protocol)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
if (protocol == null)
{
throw new ArgumentNullException("protocol");
}
if (protocol.Length == 0)
{
throw new ArgumentException("An empty string.", "protocol");
}
return request.Headers.Contains("Upgrade", protocol) && request.Headers.Contains("Connection", "Upgrade");
}
public static bool MaybeUri(this string value)
{
if (value == null || value.Length == 0)
{
return false;
}
int num = value.IndexOf(':');
if (num == -1)
{
return false;
}
if (num >= 10)
{
return false;
}
return value.Substring(0, num).IsPredefinedScheme();
}
public static T[] SubArray<T>(this T[] array, int startIndex, int length)
{
int num;
if (array == null || (num = array.Length) == 0)
{
return new T[0];
}
if (startIndex < 0 || length <= 0 || startIndex + length > num)
{
return new T[0];
}
if (startIndex == 0 && length == num)
{
return array;
}
T[] array2 = new T[length];
Array.Copy(array, startIndex, array2, 0, length);
return array2;
}
public static T[] SubArray<T>(this T[] array, long startIndex, long length)
{
long longLength;
if (array == null || (longLength = array.LongLength) == 0)
{
return new T[0];
}
if (startIndex < 0 || length <= 0 || startIndex + length > longLength)
{
return new T[0];
}
if (startIndex == 0 && length == longLength)
{
return array;
}
T[] array2 = new T[length];
Array.Copy(array, startIndex, array2, 0L, length);
return array2;
}
public static void Times(this int n, Action action)
{
if (n > 0 && action != null)
{
((ulong)n).times(action);
}
}
public static void Times(this long n, Action action)
{
if (n > 0 && action != null)
{
((ulong)n).times(action);
}
}
public static void Times(this uint n, Action action)
{
if (n != 0 && action != null)
{
times(n, action);
}
}
public static void Times(this ulong n, Action action)
{
if (n != 0 && action != null)
{
n.times(action);
}
}
public static void Times(this int n, Action<int> action)
{
if (n > 0 && action != null)
{
for (int i = 0; i < n; i++)
{
action(i);
}
}
}
public static void Times(this long n, Action<long> action)
{
if (n > 0 && action != null)
{
for (long num = 0L; num < n; num++)
{
action(num);
}
}
}
public static void Times(this uint n, Action<uint> action)
{
if (n != 0 && action != null)
{
for (uint num = 0u; num < n; num++)
{
action(num);
}
}
}
public static void Times(this ulong n, Action<ulong> action)
{
if (n != 0 && action != null)
{
for (ulong num = 0uL; num < n; num++)
{
action(num);
}
}
}
public static T To<T>(this byte[] source, ByteOrder sourceOrder) where T : struct
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (source.Length == 0)
{
return default(T);
}
Type typeFromHandle = typeof(T);
byte[] value = source.ToHostOrder(sourceOrder);
return ((object)typeFromHandle == typeof(bool)) ? ((T)(object)BitConverter.ToBoolean(value, 0)) : (((object)typeFromHandle == typeof(char)) ? ((T)(object)BitConverter.ToChar(value, 0)) : (((object)typeFromHandle == typeof(double)) ? ((T)(object)BitConverter.ToDouble(value, 0)) : (((object)typeFromHandle == typeof(short)) ? ((T)(object)BitConverter.ToInt16(value, 0)) : (((object)typeFromHandle == typeof(int)) ? ((T)(object)BitConverter.ToInt32(value, 0)) : (((object)typeFromHandle == typeof(long)) ? ((T)(object)BitConverter.ToInt64(value, 0)) : (((object)typeFromHandle == typeof(float)) ? ((T)(object)BitConverter.ToSingle(value, 0)) : (((object)typeFromHandle == typeof(ushort)) ? ((T)(object)BitConverter.ToUInt16(value, 0)) : (((object)typeFromHandle == typeof(uint)) ? ((T)(object)BitConverter.ToUInt32(value, 0)) : (((object)typeFromHandle == typeof(ulong)) ? ((T)(object)BitConverter.ToUInt64(value, 0)) : default(T))))))))));
}
public static byte[] ToByteArray<T>(this T value, ByteOrder order) where T : struct
{
Type typeFromHandle = typeof(T);
byte[] array = (((object)typeFromHandle == typeof(bool)) ? BitConverter.GetBytes((bool)(object)value) : (((object)typeFromHandle == typeof(byte)) ? new byte[1] { (byte)(object)value } : (((object)typeFromHandle == typeof(char)) ? BitConverter.GetBytes((char)(object)value) : (((object)typeFromHandle == typeof(double)) ? BitConverter.GetBytes((double)(object)value) : (((object)typeFromHandle == typeof(short)) ? BitConverter.GetBytes((short)(object)value) : (((object)typeFromHandle == typeof(int)) ? BitConverter.GetBytes((int)(object)value) : (((object)typeFromHandle == typeof(long)) ? BitConverter.GetBytes((long)(object)value) : (((object)typeFromHandle == typeof(float)) ? BitConverter.GetBytes((float)(object)value) : (((object)typeFromHandle == typeof(ushort)) ? BitConverter.GetBytes((ushort)(object)value) : (((object)typeFromHandle == typeof(uint)) ? BitConverter.GetBytes((uint)(object)value) : (((object)typeFromHandle == typeof(ulong)) ? BitConverter.GetBytes((ulong)(object)value) : WebSocket.EmptyBytes)))))))))));
if (array.Length > 1 && !order.IsHostOrder())
{
Array.Reverse((Array)array);
}
return array;
}
public static byte[] ToHostOrder(this byte[] source, ByteOrder sourceOrder)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
return (source.Length > 1 && !sourceOrder.IsHostOrder()) ? source.Reverse() : source;
}
public static string ToString<T>(this T[] array, string separator)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
int num = array.Length;
if (num == 0)
{
return string.Empty;
}
if (separator == null)
{
separator = string.Empty;
}
StringBuilder buff = new StringBuilder(64);
(num - 1).Times(delegate(int i)
{
buff.AppendFormat("{0}{1}", array[i].ToString(), separator);
});
buff.Append(array[num - 1].ToString());
return buff.ToString();
}
public static Uri ToUri(this string uriString)
{
Uri.TryCreate(uriString, uriString.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out Uri result);
return result;
}
public static string UrlDecode(this string value)
{
return (value != null && value.Length > 0) ? HttpUtility.UrlDecode(value) : value;
}
public static string UrlEncode(this string value)
{
return (value != null && value.Length > 0) ? HttpUtility.UrlEncode(value) : value;
}
public static void WriteContent(this WebSocketSharp.Net.HttpListenerResponse response, byte[] content)
{
if (response == null)
{
throw new ArgumentNullException("response");
}
if (content == null)
{
throw new ArgumentNullException("content");
}
long longLength = content.LongLength;
if (longLength == 0)
{
response.Close();
return;
}
response.ContentLength64 = longLength;
Stream outputStream = response.OutputStream;
if (longLength <= int.MaxValue)
{
outputStream.Write(content, 0, (int)longLength);
}
else
{
outputStream.WriteBytes(content, 1024);
}
outputStream.Close();
}
static Ext()
{
byte[] last = new byte[1];
_last = last;
_retry = 5;
}
}
public class MessageEventArgs : EventArgs
{
private string _data;
private bool _dataSet;
private Opcode _opcode;
private byte[] _rawData;
public string Data
{
get
{
if (!_dataSet)
{
_data = ((_opcode != Opcode.Binary) ? _rawData.UTF8Decode() : BitConverter.ToString(_rawData));
_dataSet = true;
}
return _data;
}
}
public bool IsBinary => _opcode == Opcode.Binary;
public bool IsPing => _opcode == Opcode.Ping;
public bool IsText => _opcode == Opcode.Text;
public byte[] RawData => _rawData;
[Obsolete("This property will be removed. Use any of the Is properties instead.")]
public Opcode Type => _opcode;
internal MessageEventArgs(WebSocketFrame frame)
{
_opcode = frame.Opcode;
_rawData = frame.PayloadData.ApplicationData;
}
internal MessageEventArgs(Opcode opcode, byte[] rawData)
{
if ((ulong)rawData.LongLength > PayloadData.MaxLength)
{
throw new WebSocketException(CloseStatusCode.TooBig);
}
_opcode = opcode;
_rawData = rawData;
}
}
public class CloseEventArgs : EventArgs
{
private bool _clean;
private ushort _code;
private PayloadData _payloadData;
private string _reason;
internal PayloadData PayloadData => _payloadData ?? (_payloadData = new PayloadData(_code.Append(_reason)));
public ushort Code => _code;
public string Reason => _reason ?? string.Empty;
public bool WasClean
{
get
{
return _clean;
}
internal set
{
_clean = value;
}
}
internal CloseEventArgs()
{
_code = 1005;
_payloadData = PayloadData.Empty;
}
internal CloseEventArgs(ushort code)
{
_code = code;
}
internal CloseEventArgs(CloseStatusCode code)
: this((ushort)code)
{
}
internal CloseEventArgs(PayloadData payloadData)
{
_payloadData = payloadData;
byte[] applicationData = payloadData.ApplicationData;
int num = applicationData.Length;
_code = (ushort)((num > 1) ? applicationData.SubArray(0, 2).ToUInt16(ByteOrder.Big) : 1005);
_reason = ((num > 2) ? applicationData.SubArray(2, num - 2).UTF8Decode() : string.Empty);
}
internal CloseEventArgs(ushort code, string reason)
{
_code = code;
_reason = reason;
}
internal CloseEventArgs(CloseStatusCode code, string reason)
: this((ushort)code, reason)
{
}
}
public enum ByteOrder
{
Little,
Big
}
public class ErrorEventArgs : EventArgs
{
private Exception _exception;
private string _message;
public Exception Exception => _exception;
public string Message => _message;
internal ErrorEventArgs(string message)
: this(message, null)
{
}
internal ErrorEventArgs(string message, Exception exception)
{
_message = message;
_exception = exception;
}
}
public class WebSocket : IDisposable
{
private const string _guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private const string _version = "13";
private AuthenticationChallenge _authChallenge;
private string _base64Key;
private bool _client;
private Action _closeContext;
private CompressionMethod _compression;
private WebSocketContext _context;
private WebSocketSharp.Net.CookieCollection _cookies;
private WebSocketSharp.Net.NetworkCredential _credentials;
private bool _emitOnPing;
private bool _enableRedirection;
private AutoResetEvent _exitReceiving;
private string _extensions;
private bool _extensionsRequested;
private object _forConn;
private object _forMessageEventQueue;
private object _forSend;
private MemoryStream _fragmentsBuffer;
private bool _fragmentsCompressed;
private Opcode _fragmentsOpcode;
private Func<WebSocketContext, string> _handshakeRequestChecker;
private bool _ignoreExtensions;
private bool _inContinuation;
private volatile bool _inMessage;
private volatile Logger _logger;
private Action<MessageEventArgs> _message;
private Queue<MessageEventArgs> _messageEventQueue;
private uint _nonceCount;
private string _origin;
private bool _preAuth;
private string _protocol;
private string[] _protocols;
private bool _protocolsRequested;
private WebSocketSharp.Net.NetworkCredential _proxyCredentials;
private Uri _proxyUri;
private volatile WebSocketState _readyState;
private AutoResetEvent _receivePong;
private bool _secure;
private ClientSslConfiguration _sslConfig;
private Stream _stream;
private TcpClient _tcpClient;
private Uri _uri;
private TimeSpan _waitTime;
internal static readonly byte[] EmptyBytes;
internal static readonly int FragmentLength;
internal static readonly RandomNumberGenerator RandomNumber;
internal WebSocketSharp.Net.CookieCollection CookieCollection => _cookies;
internal Func<WebSocketContext, string> CustomHandshakeRequestChecker
{
get
{
return _handshakeRequestChecker;
}
set
{
_handshakeRequestChecker = value;
}
}
internal bool HasMessage
{
get
{
lock (_forMessageEventQueue)
{
return _messageEventQueue.Count > 0;
}
}
}
internal bool IgnoreExtensions
{
get
{
return _ignoreExtensions;
}
set
{
_ignoreExtensions = value;
}
}
internal bool IsConnected => _readyState == WebSocketState.Open || _readyState == WebSocketState.Closing;
public CompressionMethod Compression
{
get
{
return _compression;
}
set
{
lock (_forConn)
{
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in setting the compression.", null);
}
else
{
_compression = value;
}
}
}
}
public IEnumerable<WebSocketSharp.Net.Cookie> Cookies
{
get
{
object syncRoot;
object obj = (syncRoot = _cookies.SyncRoot);
Monitor.Enter(syncRoot);
try
{
foreach (WebSocketSharp.Net.Cookie cookie in _cookies)
{
yield return cookie;
}
}
finally
{
Monitor.Exit(obj);
}
}
}
public WebSocketSharp.Net.NetworkCredential Credentials => _credentials;
public bool EmitOnPing
{
get
{
return _emitOnPing;
}
set
{
_emitOnPing = value;
}
}
public bool EnableRedirection
{
get
{
return _enableRedirection;
}
set
{
lock (_forConn)
{
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in setting the enable redirection.", null);
}
else
{
_enableRedirection = value;
}
}
}
}
public string Extensions => _extensions ?? string.Empty;
public bool IsAlive => Ping();
public bool IsSecure => _secure;
public Logger Log
{
get
{
return _logger;
}
internal set
{
_logger = value;
}
}
public string Origin
{
get
{
return _origin;
}
set
{
lock (_forConn)
{
Uri result;
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in setting the origin.", null);
}
else if (value.IsNullOrEmpty())
{
_origin = value;
}
else if (!Uri.TryCreate(value, UriKind.Absolute, out result) || result.Segments.Length > 1)
{
_logger.Error("The syntax of an origin must be '<scheme>://<host>[:<port>]'.");
error("An error has occurred in setting the origin.", null);
}
else
{
_origin = value.TrimEnd(new char[1] { '/' });
}
}
}
}
public string Protocol
{
get
{
return _protocol ?? string.Empty;
}
internal set
{
_protocol = value;
}
}
public WebSocketState ReadyState => _readyState;
public ClientSslConfiguration SslConfiguration
{
get
{
return _client ? (_sslConfig ?? (_sslConfig = new ClientSslConfiguration(_uri.DnsSafeHost))) : null;
}
set
{
lock (_forConn)
{
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in setting the ssl configuration.", null);
}
else
{
_sslConfig = value;
}
}
}
}
public Uri Url => _client ? _uri : _context.RequestUri;
public TimeSpan WaitTime
{
get
{
return _waitTime;
}
set
{
lock (_forConn)
{
if (!checkIfAvailable(client: true, server: true, connecting: true, open: false, closing: false, closed: true, out var text) || !value.CheckWaitTime(out text))
{
_logger.Error(text);
error("An error has occurred in setting the wait time.", null);
}
else
{
_waitTime = value;
}
}
}
}
public event EventHandler<CloseEventArgs> OnClose;
public event EventHandler<ErrorEventArgs> OnError;
public event EventHandler<MessageEventArgs> OnMessage;
public event EventHandler OnOpen;
static WebSocket()
{
EmptyBytes = new byte[0];
FragmentLength = 1016;
RandomNumber = new RNGCryptoServiceProvider();
}
internal WebSocket(HttpListenerWebSocketContext context, string protocol)
{
_context = context;
_protocol = protocol;
_closeContext = context.Close;
_logger = context.Log;
_message = messages;
_secure = context.IsSecureConnection;
_stream = context.Stream;
_waitTime = TimeSpan.FromSeconds(1.0);
init();
}
internal WebSocket(TcpListenerWebSocketContext context, string protocol)
{
_context = context;
_protocol = protocol;
_closeContext = context.Close;
_logger = context.Log;
_message = messages;
_secure = context.IsSecureConnection;
_stream = context.Stream;
_waitTime = TimeSpan.FromSeconds(1.0);
init();
}
public WebSocket(string url, params string[] protocols)
{
if (url == null)
{
throw new ArgumentNullException("url");
}
if (url.Length == 0)
{
throw new ArgumentException("An empty string.", "url");
}
if (!url.TryCreateWebSocketUri(out _uri, out var text))
{
throw new ArgumentException(text, "url");
}
if (protocols != null && protocols.Length > 0)
{
text = protocols.CheckIfValidProtocols();
if (text != null)
{
throw new ArgumentException(text, "protocols");
}
_protocols = protocols;
}
_base64Key = CreateBase64Key();
_client = true;
_logger = new Logger();
_message = messagec;
_secure = _uri.Scheme == "wss";
_waitTime = TimeSpan.FromSeconds(5.0);
init();
}
private bool accept()
{
lock (_forConn)
{
if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: false, out var text))
{
_logger.Error(text);
error("An error has occurred in accepting.", null);
return false;
}
try
{
if (!acceptHandshake())
{
return false;
}
_readyState = WebSocketState.Open;
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
fatal("An exception has occurred while accepting.", ex);
return false;
}
return true;
}
}
private bool acceptHandshake()
{
_logger.Debug($"A request from {_context.UserEndPoint}:\n{_context}");
if (!checkHandshakeRequest(_context, out var text))
{
sendHttpResponse(createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest));
_logger.Fatal(text);
fatal("An error has occurred while accepting.", CloseStatusCode.ProtocolError);
return false;
}
if (!customCheckHandshakeRequest(_context, out text))
{
sendHttpResponse(createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest));
_logger.Fatal(text);
fatal("An error has occurred while accepting.", CloseStatusCode.PolicyViolation);
return false;
}
_base64Key = _context.Headers["Sec-WebSocket-Key"];
if (_protocol != null)
{
processSecWebSocketProtocolHeader(_context.SecWebSocketProtocols);
}
if (!_ignoreExtensions)
{
processSecWebSocketExtensionsClientHeader(_context.Headers["Sec-WebSocket-Extensions"]);
}
return sendHttpResponse(createHandshakeResponse());
}
private bool checkHandshakeRequest(WebSocketContext context, out string message)
{
message = null;
if (context.RequestUri == null)
{
message = "Specifies an invalid Request-URI.";
return false;
}
if (!context.IsWebSocketRequest)
{
message = "Not a WebSocket handshake request.";
return false;
}
NameValueCollection headers = context.Headers;
if (!validateSecWebSocketKeyHeader(headers["Sec-WebSocket-Key"]))
{
message = "Includes no Sec-WebSocket-Key header, or it has an invalid value.";
return false;
}
if (!validateSecWebSocketVersionClientHeader(headers["Sec-WebSocket-Version"]))
{
message = "Includes no Sec-WebSocket-Version header, or it has an invalid value.";
return false;
}
if (!validateSecWebSocketProtocolClientHeader(headers["Sec-WebSocket-Protocol"]))
{
message = "Includes an invalid Sec-WebSocket-Protocol header.";
return false;
}
if (!_ignoreExtensions && !validateSecWebSocketExtensionsClientHeader(headers["Sec-WebSocket-Extensions"]))
{
message = "Includes an invalid Sec-WebSocket-Extensions header.";
return false;
}
return true;
}
private bool checkHandshakeResponse(HttpResponse response, out string message)
{
message = null;
if (response.IsRedirect)
{
message = "Indicates the redirection.";
return false;
}
if (response.IsUnauthorized)
{
message = "Requires the authentication.";
return false;
}
if (!response.IsWebSocketResponse)
{
message = "Not a WebSocket handshake response.";
return false;
}
NameValueCollection headers = response.Headers;
if (!validateSecWebSocketAcceptHeader(headers["Sec-WebSocket-Accept"]))
{
message = "Includes no Sec-WebSocket-Accept header, or it has an invalid value.";
return false;
}
if (!validateSecWebSocketProtocolServerHeader(headers["Sec-WebSocket-Protocol"]))
{
message = "Includes no Sec-WebSocket-Protocol header, or it has an invalid value.";
return false;
}
if (!validateSecWebSocketExtensionsServerHeader(headers["Sec-WebSocket-Extensions"]))
{
message = "Includes an invalid Sec-WebSocket-Extensions header.";
return false;
}
if (!validateSecWebSocketVersionServerHeader(headers["Sec-WebSocket-Version"]))
{
message = "Includes an invalid Sec-WebSocket-Version header.";
return false;
}
return true;
}
private bool checkIfAvailable(bool connecting, bool open, bool closing, bool closed, out string message)
{
message = null;
if (!connecting && _readyState == WebSocketState.Connecting)
{
message = "This operation isn't available in: connecting";
return false;
}
if (!open && _readyState == WebSocketState.Open)
{
message = "This operation isn't available in: open";
return false;
}
if (!closing && _readyState == WebSocketState.Closing)
{
message = "This operation isn't available in: closing";
return false;
}
if (!closed && _readyState == WebSocketState.Closed)
{
message = "This operation isn't available in: closed";
return false;
}
return true;
}
private bool checkIfAvailable(bool client, bool server, bool connecting, bool open, bool closing, bool closed, out string message)
{
message = null;
if (!client && _client)
{
message = "This operation isn't available in: client";
return false;
}
if (!server && !_client)
{
message = "This operation isn't available in: server";
return false;
}
return checkIfAvailable(connecting, open, closing, closed, out message);
}
private bool checkReceivedFrame(WebSocketFrame frame, out string message)
{
message = null;
bool isMasked = frame.IsMasked;
if (_client && isMasked)
{
message = "A frame from the server is masked.";
return false;
}
if (!_client && !isMasked)
{
message = "A frame from a client isn't masked.";
return false;
}
if (_inContinuation && frame.IsData)
{
message = "A data frame has been received while receiving continuation frames.";
return false;
}
if (frame.IsCompressed && _compression == CompressionMethod.None)
{
message = "A compressed frame has been received without any agreement for it.";
return false;
}
if (frame.Rsv2 == Rsv.On)
{
message = "The RSV2 of a frame is non-zero without any negotiation for it.";
return false;
}
if (frame.Rsv3 == Rsv.On)
{
message = "The RSV3 of a frame is non-zero without any negotiation for it.";
return false;
}
return true;
}
private void close(CloseEventArgs e, bool send, bool receive, bool received)
{
lock (_forConn)
{
if (_readyState == WebSocketState.Closing)
{
_logger.Info("The closing is already in progress.");
return;
}
if (_readyState == WebSocketState.Closed)
{
_logger.Info("The connection has been closed.");
return;
}
send = send && _readyState == WebSocketState.Open;
receive = receive && send;
_readyState = WebSocketState.Closing;
}
_logger.Trace("Begin closing the connection.");
byte[] frameAsBytes = (send ? WebSocketFrame.CreateCloseFrame(e.PayloadData, _client).ToArray() : null);
e.WasClean = closeHandshake(frameAsBytes, receive, received);
releaseResources();
_logger.Trace("End closing the connection.");
_readyState = WebSocketState.Closed;
try
{
this.OnClose.Emit(this, e);
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
error("An exception has occurred during the OnClose event.", ex);
}
}
private void closeAsync(CloseEventArgs e, bool send, bool receive, bool received)
{
Action<CloseEventArgs, bool, bool, bool> closer = close;
closer.BeginInvoke(e, send, receive, received, delegate(IAsyncResult ar)
{
closer.EndInvoke(ar);
}, null);
}
private bool closeHandshake(byte[] frameAsBytes, bool receive, bool received)
{
bool flag = frameAsBytes != null && sendBytes(frameAsBytes);
received = received || (receive && flag && _exitReceiving != null && _exitReceiving.WaitOne(_waitTime));
bool flag2 = flag && received;
_logger.Debug($"Was clean?: {flag2}\n sent: {flag}\n received: {received}");
return flag2;
}
private bool connect()
{
lock (_forConn)
{
if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in connecting.", null);
return false;
}
try
{
_readyState = WebSocketState.Connecting;
if (!doHandshake())
{
return false;
}
_readyState = WebSocketState.Open;
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
fatal("An exception has occurred while connecting.", ex);
return false;
}
return true;
}
}
private string createExtensions()
{
StringBuilder stringBuilder = new StringBuilder(80);
if (_compression != 0)
{
string arg = _compression.ToExtensionString("server_no_context_takeover", "client_no_context_takeover");
stringBuilder.AppendFormat("{0}, ", arg);
}
int length = stringBuilder.Length;
if (length > 2)
{
stringBuilder.Length = length - 2;
return stringBuilder.ToString();
}
return null;
}
private HttpResponse createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode code)
{
HttpResponse httpResponse = HttpResponse.CreateCloseResponse(code);
httpResponse.Headers["Sec-WebSocket-Version"] = "13";
return httpResponse;
}
private HttpRequest createHandshakeRequest()
{
HttpRequest httpRequest = HttpRequest.CreateWebSocketRequest(_uri);
NameValueCollection headers = httpRequest.Headers;
if (!_origin.IsNullOrEmpty())
{
headers["Origin"] = _origin;
}
headers["Sec-WebSocket-Key"] = _base64Key;
_protocolsRequested = _protocols != null;
if (_protocolsRequested)
{
headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", ");
}
_extensionsRequested = _compression != CompressionMethod.None;
if (_extensionsRequested)
{
headers["Sec-WebSocket-Extensions"] = createExtensions();
}
headers["Sec-WebSocket-Version"] = "13";
AuthenticationResponse authenticationResponse = null;
if (_authChallenge != null && _credentials != null)
{
authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount);
_nonceCount = authenticationResponse.NonceCount;
}
else if (_preAuth)
{
authenticationResponse = new AuthenticationResponse(_credentials);
}
if (authenticationResponse != null)
{
headers["Authorization"] = authenticationResponse.ToString();
}
if (_cookies.Count > 0)
{
httpRequest.SetCookies(_cookies);
}
return httpRequest;
}
private HttpResponse createHandshakeResponse()
{
HttpResponse httpResponse = HttpResponse.CreateWebSocketResponse();
NameValueCollection headers = httpResponse.Headers;
headers["Sec-WebSocket-Accept"] = CreateResponseKey(_base64Key);
if (_protocol != null)
{
headers["Sec-WebSocket-Protocol"] = _protocol;
}
if (_extensions != null)
{
headers["Sec-WebSocket-Extensions"] = _extensions;
}
if (_cookies.Count > 0)
{
httpResponse.SetCookies(_cookies);
}
return httpResponse;
}
private bool customCheckHandshakeRequest(WebSocketContext context, out string message)
{
message = null;
return _handshakeRequestChecker == null || (message = _handshakeRequestChecker(context)) == null;
}
private MessageEventArgs dequeueFromMessageEventQueue()
{
lock (_forMessageEventQueue)
{
return (_messageEventQueue.Count > 0) ? _messageEventQueue.Dequeue() : null;
}
}
private bool doHandshake()
{
setClientStream();
HttpResponse httpResponse = sendHandshakeRequest();
if (!checkHandshakeResponse(httpResponse, out var text))
{
_logger.Fatal(text);
fatal("An error has occurred while connecting.", CloseStatusCode.ProtocolError);
return false;
}
if (_protocolsRequested)
{
_protocol = httpResponse.Headers["Sec-WebSocket-Protocol"];
}
if (_extensionsRequested)
{
processSecWebSocketExtensionsServerHeader(httpResponse.Headers["Sec-WebSocket-Extensions"]);
}
processCookies(httpResponse.Cookies);
return true;
}
private void enqueueToMessageEventQueue(MessageEventArgs e)
{
lock (_forMessageEventQueue)
{
_messageEventQueue.Enqueue(e);
}
}
private void error(string message, Exception exception)
{
try
{
this.OnError.Emit(this, new ErrorEventArgs(message, exception));
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
}
}
private void fatal(string message, Exception exception)
{
CloseStatusCode code = ((exception is WebSocketException) ? ((WebSocketException)exception).Code : CloseStatusCode.Abnormal);
fatal(message, code);
}
private void fatal(string message, CloseStatusCode code)
{
close(new CloseEventArgs(code, message), !code.IsReserved(), receive: false, received: false);
}
private void init()
{
_compression = CompressionMethod.None;
_cookies = new WebSocketSharp.Net.CookieCollection();
_forConn = new object();
_forSend = new object();
_messageEventQueue = new Queue<MessageEventArgs>();
_forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot;
_readyState = WebSocketState.Connecting;
}
private void message()
{
MessageEventArgs obj = null;
lock (_forMessageEventQueue)
{
if (_inMessage || _messageEventQueue.Count == 0 || _readyState != WebSocketState.Open)
{
return;
}
_inMessage = true;
obj = _messageEventQueue.Dequeue();
}
_message(obj);
}
private void messagec(MessageEventArgs e)
{
while (true)
{
try
{
this.OnMessage.Emit(this, e);
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
error("An exception has occurred during an OnMessage event.", ex);
}
lock (_forMessageEventQueue)
{
if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open)
{
_inMessage = false;
break;
}
e = _messageEventQueue.Dequeue();
}
bool flag = true;
}
}
private void messages(MessageEventArgs e)
{
try
{
this.OnMessage.Emit(this, e);
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
error("An exception has occurred during an OnMessage event.", ex);
}
lock (_forMessageEventQueue)
{
if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open)
{
_inMessage = false;
return;
}
e = _messageEventQueue.Dequeue();
}
ThreadPool.QueueUserWorkItem(delegate
{
messages(e);
});
}
private void open()
{
_inMessage = true;
startReceiving();
try
{
this.OnOpen.Emit(this, EventArgs.Empty);
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
error("An exception has occurred during the OnOpen event.", ex);
}
MessageEventArgs obj = null;
lock (_forMessageEventQueue)
{
if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open)
{
_inMessage = false;
return;
}
obj = _messageEventQueue.Dequeue();
}
_message.BeginInvoke(obj, delegate(IAsyncResult ar)
{
_message.EndInvoke(ar);
}, null);
}
private bool processCloseFrame(WebSocketFrame frame)
{
PayloadData payloadData = frame.PayloadData;
close(new CloseEventArgs(payloadData), !payloadData.IncludesReservedCloseStatusCode, receive: false, received: true);
return false;
}
private void processCookies(WebSocketSharp.Net.CookieCollection cookies)
{
if (cookies.Count != 0)
{
_cookies.SetOrRemove(cookies);
}
}
private bool processDataFrame(WebSocketFrame frame)
{
enqueueToMessageEventQueue(frame.IsCompressed ? new MessageEventArgs(frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression)) : new MessageEventArgs(frame));
return true;
}
private bool processFragmentFrame(WebSocketFrame frame)
{
if (!_inContinuation)
{
if (frame.IsContinuation)
{
return true;
}
_fragmentsOpcode = frame.Opcode;
_fragmentsCompressed = frame.IsCompressed;
_fragmentsBuffer = new MemoryStream();
_inContinuation = true;
}
_fragmentsBuffer.WriteBytes(frame.PayloadData.ApplicationData, 1024);
if (frame.IsFinal)
{
using (_fragmentsBuffer)
{
byte[] rawData = (_fragmentsCompressed ? _fragmentsBuffer.DecompressToArray(_compression) : _fragmentsBuffer.ToArray());
enqueueToMessageEventQueue(new MessageEventArgs(_fragmentsOpcode, rawData));
}
_fragmentsBuffer = null;
_inContinuation = false;
}
return true;
}
private bool processPingFrame(WebSocketFrame frame)
{
if (send(new WebSocketFrame(Opcode.Pong, frame.PayloadData, _client).ToArray()))
{
_logger.Trace("Returned a pong.");
}
if (_emitOnPing)
{
enqueueToMessageEventQueue(new MessageEventArgs(frame));
}
return true;
}
private bool processPongFrame(WebSocketFrame frame)
{
_receivePong.Set();
_logger.Trace("Received a pong.");
return true;
}
private bool processReceivedFrame(WebSocketFrame frame)
{
if (!checkReceivedFrame(frame, out var text))
{
throw new WebSocketException(CloseStatusCode.ProtocolError, text);
}
frame.Unmask();
return frame.IsFragment ? processFragmentFrame(frame) : (frame.IsData ? processDataFrame(frame) : (frame.IsPing ? processPingFrame(frame) : (frame.IsPong ? processPongFrame(frame) : (frame.IsClose ? processCloseFrame(frame) : processUnsupportedFrame(frame)))));
}
private void processSecWebSocketExtensionsClientHeader(string value)
{
if (value == null)
{
return;
}
StringBuilder stringBuilder = new StringBuilder(80);
bool flag = false;
foreach (string item in value.SplitHeaderValue(','))
{
string value2 = item.Trim();
if (!flag && value2.IsCompressionExtension(CompressionMethod.Deflate))
{
_compression = CompressionMethod.Deflate;
stringBuilder.AppendFormat("{0}, ", _compression.ToExtensionString("client_no_context_takeover", "server_no_context_takeover"));
flag = true;
}
}
int length = stringBuilder.Length;
if (length > 2)
{
stringBuilder.Length = length - 2;
_extensions = stringBuilder.ToString();
}
}
private void processSecWebSocketExtensionsServerHeader(string value)
{
if (value == null)
{
_compression = CompressionMethod.None;
}
else
{
_extensions = value;
}
}
private void processSecWebSocketProtocolHeader(IEnumerable<string> values)
{
if (!values.Contains((string p) => p == _protocol))
{
_protocol = null;
}
}
private bool processUnsupportedFrame(WebSocketFrame frame)
{
_logger.Fatal("An unsupported frame:" + frame.PrintToString(dumped: false));
fatal("There is no way to handle it.", CloseStatusCode.PolicyViolation);
return false;
}
private void releaseClientResources()
{
if (_stream != null)
{
_stream.Dispose();
_stream = null;
}
if (_tcpClient != null)
{
_tcpClient.Close();
_tcpClient = null;
}
}
private void releaseCommonResources()
{
if (_fragmentsBuffer != null)
{
_fragmentsBuffer.Dispose();
_fragmentsBuffer = null;
_inContinuation = false;
}
if (_receivePong != null)
{
_receivePong.Close();
_receivePong = null;
}
if (_exitReceiving != null)
{
_exitReceiving.Close();
_exitReceiving = null;
}
}
private void releaseResources()
{
if (_client)
{
releaseClientResources();
}
else
{
releaseServerResources();
}
releaseCommonResources();
}
private void releaseServerResources()
{
if (_closeContext != null)
{
_closeContext();
_closeContext = null;
_stream = null;
_context = null;
}
}
private bool send(byte[] frameAsBytes)
{
lock (_forConn)
{
if (_readyState != WebSocketState.Open)
{
_logger.Error("The sending has been interrupted.");
return false;
}
return sendBytes(frameAsBytes);
}
}
private bool send(Opcode opcode, Stream stream)
{
lock (_forSend)
{
Stream stream2 = stream;
bool flag = false;
bool flag2 = false;
try
{
if (_compression != 0)
{
stream = stream.Compress(_compression);
flag = true;
}
flag2 = send(opcode, stream, flag);
if (!flag2)
{
error("The sending has been interrupted.", null);
}
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
error("An exception has occurred while sending data.", ex);
}
finally
{
if (flag)
{
stream.Dispose();
}
stream2.Dispose();
}
return flag2;
}
}
private bool send(Opcode opcode, Stream stream, bool compressed)
{
long length = stream.Length;
if (length == 0)
{
return send(Fin.Final, opcode, EmptyBytes, compressed);
}
long num = length / FragmentLength;
int num2 = (int)(length % FragmentLength);
byte[] array = null;
if (num == 0)
{
array = new byte[num2];
return stream.Read(array, 0, num2) == num2 && send(Fin.Final, opcode, array, compressed);
}
array = new byte[FragmentLength];
if (num == 1 && num2 == 0)
{
return stream.Read(array, 0, FragmentLength) == FragmentLength && send(Fin.Final, opcode, array, compressed);
}
if (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, opcode, array, compressed))
{
return false;
}
long num3 = ((num2 == 0) ? (num - 2) : (num - 1));
for (long num4 = 0L; num4 < num3; num4++)
{
if (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, Opcode.Cont, array, compressed))
{
return false;
}
}
if (num2 == 0)
{
num2 = FragmentLength;
}
else
{
array = new byte[num2];
}
return stream.Read(array, 0, num2) == num2 && send(Fin.Final, Opcode.Cont, array, compressed);
}
private bool send(Fin fin, Opcode opcode, byte[] data, bool compressed)
{
lock (_forConn)
{
if (_readyState != WebSocketState.Open)
{
_logger.Error("The sending has been interrupted.");
return false;
}
return sendBytes(new WebSocketFrame(fin, opcode, data, compressed, _client).ToArray());
}
}
private void sendAsync(Opcode opcode, Stream stream, Action<bool> completed)
{
Func<Opcode, Stream, bool> sender = send;
sender.BeginInvoke(opcode, stream, delegate(IAsyncResult ar)
{
try
{
bool obj = sender.EndInvoke(ar);
if (completed != null)
{
completed(obj);
}
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
error("An exception has occurred during a send callback.", ex);
}
}, null);
}
private bool sendBytes(byte[] bytes)
{
try
{
_stream.Write(bytes, 0, bytes.Length);
return true;
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
return false;
}
}
private HttpResponse sendHandshakeRequest()
{
HttpRequest httpRequest = createHandshakeRequest();
HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000);
if (httpResponse.IsUnauthorized)
{
string text = httpResponse.Headers["WWW-Authenticate"];
_logger.Warn($"Received an authentication requirement for '{text}'.");
if (text.IsNullOrEmpty())
{
_logger.Error("No authentication challenge is specified.");
return httpResponse;
}
_authChallenge = AuthenticationChallenge.Parse(text);
if (_authChallenge == null)
{
_logger.Error("An invalid authentication challenge is specified.");
return httpResponse;
}
if (_credentials != null && (!_preAuth || _authChallenge.Scheme == WebSocketSharp.Net.AuthenticationSchemes.Digest))
{
if (httpResponse.HasConnectionClose)
{
releaseClientResources();
setClientStream();
}
AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount);
_nonceCount = authenticationResponse.NonceCount;
httpRequest.Headers["Authorization"] = authenticationResponse.ToString();
httpResponse = sendHttpRequest(httpRequest, 15000);
}
}
if (httpResponse.IsRedirect)
{
string text2 = httpResponse.Headers["Location"];
_logger.Warn($"Received a redirection to '{text2}'.");
if (_enableRedirection)
{
if (text2.IsNullOrEmpty())
{
_logger.Error("No url to redirect is located.");
return httpResponse;
}
if (!text2.TryCreateWebSocketUri(out var result, out var text3))
{
_logger.Error("An invalid url to redirect is located: " + text3);
return httpResponse;
}
releaseClientResources();
_uri = result;
_secure = result.Scheme == "wss";
setClientStream();
return sendHandshakeRequest();
}
}
return httpResponse;
}
private HttpResponse sendHttpRequest(HttpRequest request, int millisecondsTimeout)
{
_logger.Debug("A request to the server:\n" + request.ToString());
HttpResponse response = request.GetResponse(_stream, millisecondsTimeout);
_logger.Debug("A response to this request:\n" + response.ToString());
return response;
}
private bool sendHttpResponse(HttpResponse response)
{
_logger.Debug("A response to this request:\n" + response.ToString());
return sendBytes(response.ToByteArray());
}
private void sendProxyConnectRequest()
{
HttpRequest httpRequest = HttpRequest.CreateConnectRequest(_uri);
HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000);
if (httpResponse.IsProxyAuthenticationRequired)
{
string text = httpResponse.Headers["Proxy-Authenticate"];
_logger.Warn($"Received a proxy authentication requirement for '{text}'.");
if (text.IsNullOrEmpty())
{
throw new WebSocketException("No proxy authentication challenge is specified.");
}
AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(text);
if (authenticationChallenge == null)
{
throw new WebSocketException("An invalid proxy authentication challenge is specified.");
}
if (_proxyCredentials != null)
{
if (httpResponse.HasConnectionClose)
{
releaseClientResources();
_tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port);
_stream = _tcpClient.GetStream();
}
AuthenticationResponse authenticationResponse = new AuthenticationResponse(authenticationChallenge, _proxyCredentials, 0u);
httpRequest.Headers["Proxy-Authorization"] = authenticationResponse.ToString();
httpResponse = sendHttpRequest(httpRequest, 15000);
}
if (httpResponse.IsProxyAuthenticationRequired)
{
throw new WebSocketException("A proxy authentication is required.");
}
}
if (httpResponse.StatusCode[0] != '2')
{
throw new WebSocketException("The proxy has failed a connection to the requested host and port.");
}
}
private void setClientStream()
{
if (_proxyUri != null)
{
_tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port);
_stream = _tcpClient.GetStream();
sendProxyConnectRequest();
}
else
{
_tcpClient = new TcpClient(_uri.DnsSafeHost, _uri.Port);
_stream = _tcpClient.GetStream();
}
if (_secure)
{
ClientSslConfiguration sslConfiguration = SslConfiguration;
string targetHost = sslConfiguration.TargetHost;
if (targetHost != _uri.DnsSafeHost)
{
throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, "An invalid host name is specified.");
}
try
{
SslStream sslStream = new SslStream(_stream, leaveInnerStreamOpen: false, sslConfiguration.ServerCertificateValidationCallback, sslConfiguration.ClientCertificateSelectionCallback);
sslStream.AuthenticateAsClient(targetHost, sslConfiguration.ClientCertificates, sslConfiguration.EnabledSslProtocols, sslConfiguration.CheckCertificateRevocation);
_stream = sslStream;
}
catch (Exception innerException)
{
throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, innerException);
}
}
}
private void startReceiving()
{
if (_messageEventQueue.Count > 0)
{
_messageEventQueue.Clear();
}
_exitReceiving = new AutoResetEvent(initialState: false);
_receivePong = new AutoResetEvent(initialState: false);
Action receive = null;
receive = delegate
{
WebSocketFrame.ReadFrameAsync(_stream, unmask: false, delegate(WebSocketFrame frame)
{
if (!processReceivedFrame(frame) || _readyState == WebSocketState.Closed)
{
_exitReceiving?.Set();
}
else
{
receive();
if (!_inMessage && HasMessage && _readyState == WebSocketState.Open)
{
message();
}
}
}, delegate(Exception ex)
{
_logger.Fatal(ex.ToString());
fatal("An exception has occurred while receiving.", ex);
});
};
receive();
}
private bool validateSecWebSocketAcceptHeader(string value)
{
return value != null && value == CreateResponseKey(_base64Key);
}
private bool validateSecWebSocketExtensionsClientHeader(string value)
{
return value == null || value.Length > 0;
}
private bool validateSecWebSocketExtensionsServerHeader(string value)
{
if (value == null)
{
return true;
}
if (value.Length == 0)
{
return false;
}
if (!_extensionsRequested)
{
return false;
}
bool flag = _compression != CompressionMethod.None;
foreach (string item in value.SplitHeaderValue(','))
{
string text = item.Trim();
if (flag && text.IsCompressionExtension(_compression))
{
if (!text.Contains("server_no_context_takeover"))
{
_logger.Error("The server hasn't sent back 'server_no_context_takeover'.");
return false;
}
if (!text.Contains("client_no_context_takeover"))
{
_logger.Warn("The server hasn't sent back 'client_no_context_takeover'.");
}
string method = _compression.ToExtensionString();
if (text.SplitHeaderValue(';').Contains(delegate(string t)
{
t = t.Trim();
return t != method && t != "server_no_context_takeover" && t != "client_no_context_takeover";
}))
{
return false;
}
continue;
}
return false;
}
return true;
}
private bool validateSecWebSocketKeyHeader(string value)
{
return value != null && value.Length > 0;
}
private bool validateSecWebSocketProtocolClientHeader(string value)
{
return value == null || value.Length > 0;
}
private bool validateSecWebSocketProtocolServerHeader(string value)
{
if (value == null)
{
return !_protocolsRequested;
}
if (value.Length == 0)
{
return false;
}
return _protocolsRequested && _protocols.Contains((string p) => p == value);
}
private bool validateSecWebSocketVersionClientHeader(string value)
{
return value != null && value == "13";
}
private bool validateSecWebSocketVersionServerHeader(string value)
{
return value == null || value == "13";
}
internal static string CheckCloseParameters(ushort code, string reason, bool client)
{
return (!code.IsCloseStatusCode()) ? "An invalid close status code." : ((code != 1005) ? ((code == 1010 && !client) ? "MandatoryExtension cannot be used by a server." : ((code == 1011 && client) ? "ServerError cannot be used by a client." : ((!reason.IsNullOrEmpty() && reason.UTF8Encode().Length > 123) ? "A reason has greater than the allowable max size." : null))) : ((!reason.IsNullOrEmpty()) ? "NoStatus cannot have a reason." : null));
}
internal static string CheckCloseParameters(CloseStatusCode code, string reason, bool client)
{
return (code != CloseStatusCode.NoStatus) ? ((code == CloseStatusCode.MandatoryExtension && !client) ? "MandatoryExtension cannot be used by a server." : ((code == CloseStatusCode.ServerError && client) ? "ServerError cannot be used by a client." : ((!reason.IsNullOrEmpty() && reason.UTF8Encode().Length > 123) ? "A reason has greater than the allowable max size." : null))) : ((!reason.IsNullOrEmpty()) ? "NoStatus cannot have a reason." : null);
}
internal static string CheckPingParameter(string message, out byte[] bytes)
{
bytes = message.UTF8Encode();
return (bytes.Length > 125) ? "A message has greater than the allowable max size." : null;
}
internal static string CheckSendParameter(byte[] data)
{
return (data == null) ? "'data' is null." : null;
}
internal static string CheckSendParameter(FileInfo file)
{
return (file == null) ? "'file' is null." : null;
}
internal static string CheckSendParameter(string data)
{
return (data == null) ? "'data' is null." : null;
}
internal static string CheckSendParameters(Stream stream, int length)
{
return (stream == null) ? "'stream' is null." : ((!stream.CanRead) ? "'stream' cannot be read." : ((length < 1) ? "'length' is less than 1." : null));
}
internal void Close(HttpResponse response)
{
_readyState = WebSocketState.Closing;
sendHttpResponse(response);
releaseServerResources();
_readyState = WebSocketState.Closed;
}
internal void Close(WebSocketSharp.Net.HttpStatusCode code)
{
Close(createHandshakeFailureResponse(code));
}
internal void Close(CloseEventArgs e, byte[] frameAsBytes, bool receive)
{
lock (_forConn)
{
if (_readyState == WebSocketState.Closing)
{
_logger.Info("The closing is already in progress.");
return;
}
if (_readyState == WebSocketState.Closed)
{
_logger.Info("The connection has been closed.");
return;
}
_readyState = WebSocketState.Closing;
}
e.WasClean = closeHandshake(frameAsBytes, receive, received: false);
releaseServerResources();
releaseCommonResources();
_readyState = WebSocketState.Closed;
try
{
this.OnClose.Emit(this, e);
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
}
}
internal static string CreateBase64Key()
{
byte[] array = new byte[16];
RandomNumber.GetBytes(array);
return Convert.ToBase64String(array);
}
internal static string CreateResponseKey(string base64Key)
{
StringBuilder stringBuilder = new StringBuilder(base64Key, 64);
stringBuilder.Append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
SHA1 sHA = new SHA1CryptoServiceProvider();
byte[] inArray = sHA.ComputeHash(stringBuilder.ToString().UTF8Encode());
return Convert.ToBase64String(inArray);
}
internal void InternalAccept()
{
try
{
if (!acceptHandshake())
{
return;
}
_readyState = WebSocketState.Open;
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
fatal("An exception has occurred while accepting.", ex);
return;
}
open();
}
internal bool Ping(byte[] frameAsBytes, TimeSpan timeout)
{
if (_readyState != WebSocketState.Open)
{
return false;
}
if (!send(frameAsBytes))
{
return false;
}
return _receivePong?.WaitOne(timeout) ?? false;
}
internal void Send(Opcode opcode, byte[] data, Dictionary<CompressionMethod, byte[]> cache)
{
lock (_forSend)
{
lock (_forConn)
{
if (_readyState != WebSocketState.Open)
{
_logger.Error("The sending has been interrupted.");
return;
}
try
{
if (!cache.TryGetValue(_compression, out var value))
{
value = new WebSocketFrame(Fin.Final, opcode, data.Compress(_compression), _compression != CompressionMethod.None, mask: false).ToArray();
cache.Add(_compression, value);
}
sendBytes(value);
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
}
}
}
}
internal void Send(Opcode opcode, Stream stream, Dictionary<CompressionMethod, Stream> cache)
{
lock (_forSend)
{
try
{
if (!cache.TryGetValue(_compression, out var value))
{
value = stream.Compress(_compression);
cache.Add(_compression, value);
}
else
{
value.Position = 0L;
}
send(opcode, value, _compression != CompressionMethod.None);
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
}
}
}
public void Accept()
{
if (!checkIfAvailable(client: false, server: true, connecting: true, open: false, closing: false, closed: false, out var text))
{
_logger.Error(text);
error("An error has occurred in accepting.", null);
}
else if (accept())
{
open();
}
}
public void AcceptAsync()
{
if (!checkIfAvailable(client: false, server: true, connecting: true, open: false, closing: false, closed: false, out var text))
{
_logger.Error(text);
error("An error has occurred in accepting.", null);
return;
}
Func<bool> acceptor = accept;
acceptor.BeginInvoke(delegate(IAsyncResult ar)
{
if (acceptor.EndInvoke(ar))
{
open();
}
}, null);
}
public void Close()
{
if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text))
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else
{
close(new CloseEventArgs(), send: true, receive: true, received: false);
}
}
public void Close(ushort code)
{
string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, null, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == 1005)
{
close(new CloseEventArgs(), send: true, receive: true, received: false);
}
else
{
bool receive = !code.IsReserved();
close(new CloseEventArgs(code), receive, receive, received: false);
}
}
public void Close(CloseStatusCode code)
{
string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, null, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == CloseStatusCode.NoStatus)
{
close(new CloseEventArgs(), send: true, receive: true, received: false);
}
else
{
bool receive = !code.IsReserved();
close(new CloseEventArgs(code), receive, receive, received: false);
}
}
public void Close(ushort code, string reason)
{
string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, reason, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == 1005)
{
close(new CloseEventArgs(), send: true, receive: true, received: false);
}
else
{
bool receive = !code.IsReserved();
close(new CloseEventArgs(code, reason), receive, receive, received: false);
}
}
public void Close(CloseStatusCode code, string reason)
{
string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, reason, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == CloseStatusCode.NoStatus)
{
close(new CloseEventArgs(), send: true, receive: true, received: false);
}
else
{
bool receive = !code.IsReserved();
close(new CloseEventArgs(code, reason), receive, receive, received: false);
}
}
public void CloseAsync()
{
if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text))
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else
{
closeAsync(new CloseEventArgs(), send: true, receive: true, received: false);
}
}
public void CloseAsync(ushort code)
{
string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, null, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == 1005)
{
closeAsync(new CloseEventArgs(), send: true, receive: true, received: false);
}
else
{
bool receive = !code.IsReserved();
closeAsync(new CloseEventArgs(code), receive, receive, received: false);
}
}
public void CloseAsync(CloseStatusCode code)
{
string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, null, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == CloseStatusCode.NoStatus)
{
closeAsync(new CloseEventArgs(), send: true, receive: true, received: false);
}
else
{
bool receive = !code.IsReserved();
closeAsync(new CloseEventArgs(code), receive, receive, received: false);
}
}
public void CloseAsync(ushort code, string reason)
{
string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, reason, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == 1005)
{
closeAsync(new CloseEventArgs(), send: true, receive: true, received: false);
}
else
{
bool receive = !code.IsReserved();
closeAsync(new CloseEventArgs(code, reason), receive, receive, received: false);
}
}
public void CloseAsync(CloseStatusCode code, string reason)
{
string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, reason, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == CloseStatusCode.NoStatus)
{
closeAsync(new CloseEventArgs(), send: true, receive: true, received: false);
}
else
{
bool receive = !code.IsReserved();
closeAsync(new CloseEventArgs(code, reason), receive, receive, received: false);
}
}
public void Connect()
{
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in connecting.", null);
}
else if (connect())
{
open();
}
}
public void ConnectAsync()
{
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in connecting.", null);
return;
}
Func<bool> connector = connect;
connector.BeginInvoke(delegate(IAsyncResult ar)
{
if (connector.EndInvoke(ar))
{
open();
}
}, null);
}
public bool Ping()
{
byte[] frameAsBytes = (_client ? WebSocketFrame.CreatePingFrame(mask: true).ToArray() : WebSocketFrame.EmptyPingBytes);
return Ping(frameAsBytes, _waitTime);
}
public bool Ping(string message)
{
if (message == null || message.Length == 0)
{
return Ping();
}
byte[] bytes;
string text = CheckPingParameter(message, out bytes);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending a ping.", null);
return false;
}
return Ping(WebSocketFrame.CreatePingFrame(bytes, _client).ToArray(), _waitTime);
}
public void Send(byte[] data)
{
string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending data.", null);
}
else
{
send(Opcode.Binary, new MemoryStream(data));
}
}
public void Send(FileInfo file)
{
string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(file);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending data.", null);
}
else
{
send(Opcode.Binary, file.OpenRead());
}
}
public void Send(string data)
{
string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending data.", null);
}
else
{
send(Opcode.Text, new MemoryStream(data.UTF8Encode()));
}
}
public void SendAsync(byte[] data, Action<bool> completed)
{
string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending data.", null);
}
else
{
sendAsync(Opcode.Binary, new MemoryStream(data), completed);
}
}
public void SendAsync(FileInfo file, Action<bool> completed)
{
string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(file);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending data.", null);
}
else
{
sendAsync(Opcode.Binary, file.OpenRead(), completed);
}
}
public void SendAsync(string data, Action<bool> completed)
{
string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending data.", null);
}
else
{
sendAsync(Opcode.Text, new MemoryStream(data.UTF8Encode()), completed);
}
}
public void SendAsync(Stream stream, int length, Action<bool> completed)
{
string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameters(stream, length);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending data.", null);
return;
}
stream.ReadBytesAsync(length, delegate(byte[] data)
{
int num = data.Length;
if (num == 0)
{
_logger.Error("The data cannot be read from 'stream'.");
error("An error has occurred in sending data.", null);
}
else
{
if (num < length)
{
_logger.Warn($"The length of the data is less than 'length':\n expected: {length}\n actual: {num}");
}
bool obj = send(Opcode.Binary, new MemoryStream(data));
if (completed != null)
{
completed(obj);
}
}
}, delegate(Exception ex)
{
_logger.Error(ex.ToString());
error("An exception has occurred while sending data.", ex);
});
}
public void SetCookie(WebSocketSharp.Net.Cookie cookie)
{
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in setting a cookie.", null);
return;
}
lock (_forConn)
{
if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text))
{
_logger.Error(text);
error("An error has occurred in setting a cookie.", null);
return;
}
if (cookie == null)
{
_logger.Error("'cookie' is null.");
error("An error has occurred in setting a cookie.", null);
return;
}
lock (_cookies.SyncRoot)
{
_cookies.SetOrRemove(cookie);
}
}
}
public void SetCredentials(string username, string password, bool preAuth)
{
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in setting the credentials.", null);
return;
}
lock (_forConn)
{
if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text))
{
_logger.Error(text);
error("An error has occurred in setting the credentials.", null);
}
else if (username.IsNullOrEmpty())
{
_logger.Warn("The credentials are set back to the default.");
_credentials = null;
_preAuth = false;
}
else if (Ext.Contains(username, ':') || !username.IsText())
{
_logger.Error("'username' contains an invalid character.");
error("An error has occurred in setting the credentials.", null);
}
else if (!password.IsNullOrEmpty() && !password.IsText())
{
_logger.Error("'password' contains an invalid character.");
error("An error has occurred in setting the credentials.", null);
}
else
{
_credentials = new WebSocketSharp.Net.NetworkCredential(username, password, _uri.PathAndQuery);
_preAuth = preAuth;
}
}
}
public void SetProxy(string url, string username, string password)
{
if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text))
{
_logger.Error(text);
error("An error has occurred in setting the proxy.", null);
return;
}
lock (_forConn)
{
Uri result;
if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text))
{
_logger.Error(text);
error("An error has occurred in setting the proxy.", null);
}
else if (url.IsNullOrEmpty())
{
_logger.Warn("The proxy url and credentials are set back to the default.");
_proxyUri = null;
_proxyCredentials = null;
}
else if (!Uri.TryCreate(url, UriKind.Absolute, out result) || result.Scheme != "http" || result.Segments.Length > 1)
{
_logger.Error("The syntax of a proxy url must be 'http://<host>[:<port>]'.");
error("An error has occurred in setting the proxy.", null);
}
else if (username.IsNullOrEmpty())
{
_logger.Warn("The proxy credentials are set back to the default.");
_proxyUri = result;
_proxyCredentials = null;
}
else if (Ext.Contains(username, ':') || !username.IsText())
{
_logger.Error("'username' contains an invalid character.");
error("An error has occurred in setting the proxy.", null);
}
else if (!password.IsNullOrEmpty() && !password.IsText())
{
_logger.Error("'password' contains an invalid character.");
error("An error has occurred in setting the proxy.", null);
}
else
{
_proxyUri = result;
_proxyCredentials = new WebSocketSharp.Net.NetworkCredential(username, password, $"{_uri.DnsSafeHost}:{_uri.Port}");
}
}
}
void IDisposable.Dispose()
{
close(new CloseEventArgs(CloseStatusCode.Away), send: true, receive: true, received: false);
}
}
}
namespace WebSocketSharp.Server
{
public class WebSocketServer
{
private IPAddress _address;
private WebSocketSharp.Net.AuthenticationSchemes _authSchemes;
private static readonly string _defaultRealm;
private bool _dnsStyle;
private string _hostname;
private TcpListener _listener;
private Logger _logger;
private int _port;
private string _realm;
private Thread _receiveThread;
private bool _reuseAddress;
private bool _secure;
private WebSocketServiceManager _services;
private ServerSslConfiguration _sslConfig;
private volatile ServerState _state;
private object _sync;
private Func<IIdentity, WebSocketSharp.Net.NetworkCredential> _userCredFinder;
public IPAddress Address => _address;
public WebSocketSharp.Net.AuthenticationSchemes AuthenticationSchemes
{
get
{
return _authSchemes;
}
set
{
string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false);
if (text != null)
{
_logger.Error(text);
}
else
{
_authSchemes = value;
}
}
}
public bool IsListening => _state == ServerState.Start;
public bool IsSecure => _secure;
public bool KeepClean
{
get
{
return _services.KeepClean;
}
set
{
string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false);
if (text != null)
{
_logger.Error(text);
}
else
{
_services.KeepClean = value;
}
}
}
public Logger Log => _logger;
public int Port => _port;
public string Realm
{
get
{
return _realm;
}
set
{
string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false);
if (text != null)
{
_logger.Error(text);
}
else
{
_realm = value;
}
}
}
public bool ReuseAddress
{
get
{
return _reuseAddress;
}
set
{
string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false);
if (text != null)
{
_logger.Error(text);
}
else
{
_reuseAddress = value;
}
}
}
public ServerSslConfiguration SslConfiguration
{
get
{
return _sslConfig ?? (_sslConfig = new ServerSslConfiguration(null));
}
set
{
string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false);
if (text != null)
{
_logger.Error(text);
}
else
{
_sslConfig = value;
}
}
}
public Func<IIdentity, WebSocketSharp.Net.NetworkCredential> UserCredentialsFinder
{
get
{
return _userCredFinder;
}
set
{
string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false);
if (text != null)
{
_logger.Error(text);
}
else
{
_userCredFinder = value;
}
}
}
public TimeSpan WaitTime
{
get
{
return _services.WaitTime;
}
set
{
string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false) ?? value.CheckIfValidWaitTime();
if (text != null)
{
_logger.Error(text);
}
else
{
_services.WaitTime = value;
}
}
}
public WebSocketServiceManager WebSocketServices => _services;
static WebSocketServer()
{
_defaultRealm = "SECRET AREA";
}
public WebSocketServer()
{
init(null, IPAddress.Any, 80, secure: false);
}
public WebSocketServer(int port)
: this(port, port == 443)
{
}
public WebSocketServer(string url)
{
if (url == null)
{
throw new ArgumentNullException("url");
}
if (url.Length == 0)
{
throw new ArgumentException("An empty string.", "url");
}
if (!tryCreateUri(url, out var result, out var message))
{
throw new ArgumentException(message, "url");
}
string dnsSafeHost = result.DnsSafeHost;
IPAddress address = dnsSafeHost.ToIPAddress();
if (!address.IsLocal())
{
throw new ArgumentException("The host part isn't a local host name: " + url, "url");
}
init(dnsSafeHost, address, result.Port, result.Scheme == "wss");
}
public WebSocketServer(int port, bool secure)
{
if (!port.IsPortNumber())
{
throw new ArgumentOutOfRangeException("port", "Not between 1 and 65535 inclusive: " + port);
}
init(null, IPAddress.Any, port, secure);
}
public WebSocketServer(IPAddress address, int port)
: this(address, port, port == 443)
{
}
public WebSocketServer(IPAddress address, int port, bool secure)
{
if (address == null)
{
throw new ArgumentNullException("address");
}
if (!address.IsLocal())
{
throw new ArgumentException("Not a local IP address: " + address, "address");
}
if (!port.IsPortNumber())
{
throw new ArgumentOutOfRangeException("port", "Not between 1 and 65535 inclusive: " + port);
}
init(null, address, port, secure);
}
private void abort()
{
lock (_sync)
{
if (!IsListening)
{
return;
}
_state = ServerState.ShuttingDown;
}
_listener.Stop();
_services.Stop(new CloseEventArgs(CloseStatusCode.ServerError), send: true, receive: false);
_state = ServerState.Stop;
}
private string checkIfCertificateExists()
{
return (_secure && (_sslConfig == null || _sslConfig.ServerCertificate == null)) ? "The secure connection requires a server certificate." : null;
}
private string getRealm()
{
string realm = _realm;
return (realm != null && realm.Length > 0) ? realm : _defaultRealm;
}
private void init(string hostname, IPAddress address, int port, bool secure)
{
_hostname = hostname ?? address.ToString();
_address = address;
_port = port;
_secure = seusing System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using EventsIO;
using EventsIO.Interfaces;
using ModHelper;
using ModHelper.Interfaces;
using WebSocketIO.Data;
using WebSocketSharp;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WebSocketIO")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyProduct("WebSocketIO")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("27b98c5b-ac6a-4518-ae12-3c9957b291e4")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace WebSocketIO
{
public class ChaosWebSocketHandler
{
public const string TypeEventMessage = "event";
public const string TypeConfigMessage = "config";
public bool isEnableDebugLog = true;
public bool isEnableDebugLogOnClose;
public bool isEnableDebugLogOnOpen;
public bool isEnableDebugLogOnCloseValidConnect = true;
protected bool isNeedLogOnCloseValidConnect;
protected ILogger logger;
public Action<string, string> OnCustomMessage { get; set; }
public Action<string> OnEventMessage { get; set; }
public Action<string> OnConfigMessage { get; set; }
public Action OnWebSocketOpen { get; set; }
public Action<CloseEventArgs> OnWebSocketClose { get; set; }
public Action<ErrorEventArgs> OnWebSocketError { get; set; }
public ChaosWebSocketHandler(ILogger logger = null)
{
this.logger = logger;
}
protected void DebugWebSocketLog(string s)
{
if (isEnableDebugLog && logger != null)
{
logger.LogInfo((object)("[DEBUG] ChaosTricks WebSocketHandler: " + s));
}
}
protected void DebugWebSocketLogError(string s)
{
if (isEnableDebugLog && logger != null)
{
logger.LogError((object)("[DEBUG] ChaosTricks WebSocketHandler: " + s));
}
}
public void OnOpen()
{
if (isEnableDebugLogOnOpen)
{
DebugWebSocketLog("OnOpen");
}
try
{
if (isEnableDebugLogOnCloseValidConnect)
{
isNeedLogOnCloseValidConnect = true;
}
OnWebSocketOpen?.Invoke();
}
catch (Exception arg)
{
if (isEnableDebugLogOnOpen)
{
DebugWebSocketLogError($"OnOpen {arg}");
}
}
}
public void OnClose(CloseEventArgs e)
{
if (isEnableDebugLogOnClose)
{
DebugWebSocketLog("OnClose " + e.Reason);
}
try
{
OnWebSocketClose?.Invoke(e);
}
catch (Exception arg)
{
if (isEnableDebugLogOnClose)
{
DebugWebSocketLogError($"OnClose {arg}");
}
else if (isEnableDebugLogOnCloseValidConnect && isNeedLogOnCloseValidConnect)
{
isNeedLogOnCloseValidConnect = false;
DebugWebSocketLogError($"OnClose {arg}");
}
}
}
public void OnError(ErrorEventArgs e)
{
DebugWebSocketLogError("Error " + e.Message);
try
{
OnWebSocketError?.Invoke(e);
}
catch (Exception arg)
{
DebugWebSocketLogError($"OnError inner error {arg}");
}
}
public WebSocketMessage ParseWebSocketMessage(string data)
{
try
{
return UtilityJson.Generate((IDebugLogger)null).FromString<WebSocketMessage>(data) ?? new WebSocketMessage();
}
catch (Exception arg)
{
DebugWebSocketLogError($"ParseWebSocketMessage {arg}");
return new WebSocketMessage();
}
}
public void OnMessage(MessageEventArgs e)
{
if (!e.IsText)
{
return;
}
try
{
WebSocketMessage webSocketMessage = ParseWebSocketMessage(e.Data);
string type = webSocketMessage.type;
string data = webSocketMessage.data;
if (!(type == "config"))
{
if (type == "event")
{
DebugWebSocketLog("OnMessage - event");
OnEventMessage?.Invoke(data);
}
else
{
DebugWebSocketLog("OnMessage - custom msg");
OnCustomMessage?.Invoke(type, data);
}
}
else
{
DebugWebSocketLog("OnMessage - config");
OnConfigMessage?.Invoke(data);
}
}
catch (Exception arg)
{
DebugWebSocketLogError($"OnMessage {arg}");
}
}
}
public class WebSocketEventsReader<T> : EventsReaderOnFrame, IDisposable where T : class
{
protected object locker = new object();
protected List<string> eventListFromSocket = new List<string>();
protected bool isDisposed;
protected bool isSocketMessageProcessing;
public bool isAutoRequestSettingsOnOpen = true;
public bool isAutoConnectOnRead = true;
public const int DEFAULT_PORT = 13715;
public float autoConnectOnReadPeriod = 8f;
protected float autoConnectOnReadPeriodTicks;
protected bool isNeedLogOnClose;
public virtual ChaosWebSocketHandler SocketHandler { get; set; }
public virtual WebSocket Socket { get; set; }
public virtual T Settings { get; protected set; }
public Action<MessageEventArgs> OnMessage { get; set; }
public Action OnOpen { get; set; }
public Action<CloseEventArgs> OnCloseOnlyAfterConnect { get; set; }
public Action<ErrorEventArgs> OnErrorOnlyAfterConnect { get; set; }
public Action<CloseEventArgs> OnClose { get; set; }
public Action<ErrorEventArgs> OnError { get; set; }
public WebSocketEventsReader(Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> errorLog = null, float checkPeriod = 2f, float delay = 1f, float initDelay = 0.5f)
: base("", processEvent, parser, log, errorLog, checkPeriod, delay, initDelay)
{
}
public virtual int GetPortFromSettingsOrDefault(string settingsDir)
{
try
{
string path = Path.Combine(settingsDir, "ChaosWebSocketConfig.txt");
if (File.Exists(path))
{
return int.Parse(File.ReadAllLines(path)[0]);
}
}
catch (Exception arg)
{
((EventsReader)this).ReaderLogError($"GetPortFromSettingsOrDefault error: {arg}. (will be used {13715})");
}
return 13715;
}
public virtual T ParseSettings(string data)
{
try
{
T result = UtilityJson.Generate((IDebugLogger)null).FromString<T>(data);
((EventsReader)this).ReaderLog("settings parsing completed: " + data);
return result;
}
catch (Exception arg)
{
((EventsReader)this).ReaderLogError($"error: {arg}.\nCan't parse settings. Using standard.");
}
T result2 = null;
try
{
result2 = Activator.CreateInstance<T>();
return result2;
}
catch (Exception arg2)
{
((EventsReader)this).ReaderLogError($"error: {arg2}.\nCan't create default data class.");
return result2;
}
}
public virtual void OpenSocket(bool isLogOnError = true)
{
try
{
WebSocket socket = Socket;
if (socket != null && !socket.IsAlive)
{
((EventsReader)this).ReaderLog("try to open socket connection");
socket.ConnectAsync();
}
}
catch (Exception arg)
{
if (isLogOnError)
{
((EventsReader)this).ReaderLogError($"OpenSocket error: {arg}");
}
}
}
public virtual void CloseSocket()
{
try
{
WebSocket socket = Socket;
if (socket != null)
{
socket.Close();
}
}
catch (Exception arg)
{
((EventsReader)this).ReaderLogError($"CloseSocket error: {arg}");
}
}
public virtual void RequestSettings()
{
try
{
WebSocket socket = Socket;
if (socket != null)
{
socket.Send(new WebSocketMessage("config", "").ToString());
}
}
catch (Exception arg)
{
((EventsReader)this).ReaderLogError($"RequestSettings error: {arg}");
}
}
public virtual void InitDefaultSocket(string settingsDir, string room, int port, string ip = "127.0.0.1")
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
WebSocket val = new WebSocket($"ws://{ip}:{port}/{room}", new string[0]);
ChaosWebSocketHandler socketHandler = new ChaosWebSocketHandler
{
OnEventMessage = delegate(string data)
{
isSocketMessageProcessing = true;
lock (locker)
{
eventListFromSocket.Add(data);
}
isSocketMessageProcessing = false;
},
OnConfigMessage = delegate(string data)
{
Settings = ParseSettings(data);
},
OnWebSocketOpen = delegate
{
isNeedLogOnClose = true;
((EventsReader)this).ReaderLog("ChaosTricks connected");
if (isAutoRequestSettingsOnOpen)
{
RequestSettings();
}
try
{
OnOpen?.Invoke();
}
catch (Exception arg6)
{
((EventsReader)this).ReaderLogError($"ChaosTricks custom OnOpen error: {arg6}");
}
},
OnWebSocketClose = delegate(CloseEventArgs e)
{
if (isNeedLogOnClose)
{
isNeedLogOnClose = false;
((EventsReader)this).ReaderLog($"ChaosTricks disconnected {e.Reason} {e.Code}");
try
{
OnCloseOnlyAfterConnect?.Invoke(e);
}
catch (Exception arg4)
{
((EventsReader)this).ReaderLogError($"ChaosTricks custom OnClose after success connection error: {arg4}");
}
}
try
{
OnClose?.Invoke(e);
}
catch (Exception arg5)
{
((EventsReader)this).ReaderLogError($"ChaosTricks custom OnClose error: {arg5}");
}
},
OnWebSocketError = delegate(ErrorEventArgs e)
{
if (isNeedLogOnClose)
{
((EventsReader)this).ReaderLog($"ChaosTricks ws error {e.Message} {e.Exception}");
try
{
OnErrorOnlyAfterConnect?.Invoke(e);
}
catch (Exception arg2)
{
((EventsReader)this).ReaderLogError($"ChaosTricks custom OnError after success connection error: {arg2}");
}
}
try
{
OnError?.Invoke(e);
}
catch (Exception arg3)
{
((EventsReader)this).ReaderLogError($"ChaosTricks custom OnError error: {arg3}");
}
}
};
val.OnMessage += delegate(object sender, MessageEventArgs e)
{
socketHandler.OnMessage(e);
try
{
OnMessage?.Invoke(e);
}
catch (Exception arg)
{
((EventsReader)this).ReaderLogError($"ChaosTricks custom OnMessage error: {arg}");
}
};
val.OnOpen += delegate
{
socketHandler.OnOpen();
};
val.OnClose += delegate(object sender, CloseEventArgs e)
{
socketHandler.OnClose(e);
};
val.OnError += delegate(object sender, ErrorEventArgs e)
{
socketHandler.OnError(e);
};
if (!File.Exists(Path.Combine(settingsDir ?? "", ".debug_websocket")))
{
val.Log.Level = (LogLevel)10;
}
SocketHandler = socketHandler;
Socket = val;
}
public override string[] ReadAll(string path, bool isClearFile = true)
{
string[] result = null;
if (!isSocketMessageProcessing)
{
lock (locker)
{
if (eventListFromSocket.Count > 0)
{
result = eventListFromSocket.ToArray();
eventListFromSocket.Clear();
}
}
}
return result;
}
public override void ReadAndProcessAllWithDelayOnFrame(float dt)
{
if (isAutoConnectOnRead)
{
autoConnectOnReadPeriodTicks += dt;
if (autoConnectOnReadPeriodTicks > autoConnectOnReadPeriod)
{
autoConnectOnReadPeriodTicks = 0f;
OpenSocket(isLogOnError: false);
}
}
((EventsReaderOnFrame)this).ReadAndProcessAllWithDelayOnFrame(dt);
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
isDisposed = true;
if (disposing)
{
((IDisposable)Socket)?.Dispose();
}
}
}
~WebSocketEventsReader()
{
try
{
Dispose(disposing: false);
}
finally
{
((object)this).Finalize();
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
namespace WebSocketIO.Interfaces
{
public interface IChaosWebSocket
{
void Start();
void Stop();
}
}
namespace WebSocketIO.Data
{
public class WebSocketMessage
{
public string type = "";
public string data = "";
public WebSocketMessage()
{
}
public WebSocketMessage(string type, string data)
{
this.type = type;
this.data = data;
}
public override string ToString()
{
string text = data.Replace("\"", "\\\"");
return "{\"type\":\"" + type + "\", \"data\":\"" + text + "\"}";
}
}
}