Upload from upload_mods.ps1
This commit is contained in:
215
Scripts/StaticManagers/CustomEffectEnumManager.cs
Normal file
215
Scripts/StaticManagers/CustomEffectEnumManager.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniLinq;
|
||||
|
||||
namespace KFCommonUtilityLib.Scripts.StaticManagers
|
||||
{
|
||||
public static class CustomEffectEnumManager
|
||||
{
|
||||
private static event Action OnInitDefault;
|
||||
private static event Action OnInitFinal;
|
||||
private static event Action OnPrintResult;
|
||||
|
||||
//call this in InitMod
|
||||
public static void RegisterEnumType<T>(bool requestMin = false, int requestedMin = 0, bool requestMax = false, int requestedMax = int.MaxValue) where T : struct, Enum
|
||||
{
|
||||
if (EnumHolder<T>.Registered)
|
||||
return;
|
||||
EnumHolder<T>.Registered = true;
|
||||
EnumHolder<T>.RequestMinMax(requestMin, requestedMin, requestMax, requestedMax);
|
||||
OnInitDefault += EnumHolder<T>.InitDefault;
|
||||
OnInitFinal += EnumHolder<T>.InitFinal;
|
||||
OnPrintResult += EnumHolder<T>.PrintResult;
|
||||
}
|
||||
|
||||
//hooked to GameAwake
|
||||
public static void InitDefault()
|
||||
{
|
||||
OnInitDefault?.Invoke();
|
||||
}
|
||||
|
||||
//patched to GameManager.StartGame prefix
|
||||
public static void InitFinal()
|
||||
{
|
||||
OnInitFinal?.Invoke();
|
||||
}
|
||||
|
||||
public static void PrintResults()
|
||||
{
|
||||
OnPrintResult?.Invoke();
|
||||
}
|
||||
|
||||
//only call these from callbacks hooked to ModEvents.GameStartDone and cache the results for future usage
|
||||
//patched to PassiveEffect.ParsePassiveEffect and MinEventActionBase.ParseXmlAttribute
|
||||
public static T RegisterOrGetEnum<T>(string name, bool ignoreCase = false) where T : struct, Enum
|
||||
{
|
||||
if (!EnumHolder<T>.Registered)
|
||||
{
|
||||
throw new Exception($"Enum not registered: {typeof(T).Name}");
|
||||
}
|
||||
return EnumHolder<T>.RegisterOrGetEnum(name, ignoreCase);
|
||||
}
|
||||
|
||||
//public static PassiveEffects RegisterOrGetPassive(string passive)
|
||||
//{
|
||||
// if (!dict_final_passive.TryGetValue(passive, out var value))
|
||||
// {
|
||||
// if (dict_final_passive.Count >= byte.MaxValue)
|
||||
// throw new OverflowException("Passive effect count exceeds limit 255!");
|
||||
// value = (PassiveEffects)(byte)dict_final_passive.Count;
|
||||
// dict_final_passive.Add(passive, value);
|
||||
// }
|
||||
// return value;
|
||||
//}
|
||||
|
||||
////patched to MinEventActionBase.ParseXmlAttribute
|
||||
//public static MinEventTypes RegisterOrGetTrigger(string trigger)
|
||||
//{
|
||||
// if (!dict_final_trigger.TryGetValue(trigger, out var value))
|
||||
// {
|
||||
// value = (MinEventTypes)dict_final_trigger.Count;
|
||||
// dict_final_trigger.Add(trigger, value);
|
||||
// }
|
||||
// return value;
|
||||
//}
|
||||
|
||||
private static class EnumHolder<T> where T : struct, Enum
|
||||
{
|
||||
private static int max, min;
|
||||
private static readonly TypeCode typecode;
|
||||
private static readonly Dictionary<string, T> dict_default_enums = new Dictionary<string, T>();
|
||||
private static readonly Dictionary<string, T> dict_default_enums_lower = new Dictionary<string, T>();
|
||||
private static readonly LinkedList<(int start, int end)> link_default_holes = new LinkedList<(int start, int end)>();
|
||||
private static Dictionary<string, T> dict_final_enums = new Dictionary<string, T>();
|
||||
private static Dictionary<string, T> dict_final_enums_lower = new Dictionary<string, T>();
|
||||
private static LinkedList<(int start, int end)> link_final_holes = new LinkedList<(int start, int end)>();
|
||||
public static bool Registered { get; set; } = false;
|
||||
private static bool DefaultInited { get; set; } = false;
|
||||
static EnumHolder()
|
||||
{
|
||||
Type underlying = Enum.GetUnderlyingType(typeof(T));
|
||||
typecode = Type.GetTypeCode(underlying);
|
||||
switch (typecode)
|
||||
{
|
||||
case TypeCode.Byte:
|
||||
min = 0;
|
||||
max = byte.MaxValue;
|
||||
break;
|
||||
case TypeCode.SByte:
|
||||
min = sbyte.MinValue;
|
||||
max = sbyte.MaxValue;
|
||||
break;
|
||||
case TypeCode.Int16:
|
||||
min = short.MinValue;
|
||||
max = short.MaxValue;
|
||||
break;
|
||||
case TypeCode.UInt16:
|
||||
min = 0;
|
||||
max = ushort.MaxValue;
|
||||
break;
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
min = int.MinValue;
|
||||
max = int.MaxValue;
|
||||
break;
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
min = 0;
|
||||
max = int.MaxValue;
|
||||
break;
|
||||
default:
|
||||
throw new Exception($"Invalid underlying type for enum {typeof(T).Name}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void RequestMinMax(bool requestMin, int requestedMin, bool requestMax, int requestedMax)
|
||||
{
|
||||
if (requestMin && requestedMin >= min)
|
||||
{
|
||||
min = requestedMin;
|
||||
}
|
||||
if (requestMax && requestedMax <= max)
|
||||
{
|
||||
max = requestedMax;
|
||||
}
|
||||
}
|
||||
|
||||
public static void InitDefault()
|
||||
{
|
||||
if (DefaultInited)
|
||||
return;
|
||||
dict_default_enums.Clear();
|
||||
dict_default_enums_lower.Clear();
|
||||
link_default_holes.Clear();
|
||||
var total = Enum.GetNames(typeof(T)).Length;
|
||||
var enums = Enum.GetValues(typeof(T)).Cast<T>().ToArray();
|
||||
for (int i = 0; i < total; i++)
|
||||
{
|
||||
string name = enums[i].ToString();
|
||||
dict_default_enums.Add(name, enums[i]);
|
||||
dict_default_enums_lower.Add(name.ToLower(), enums[i]);
|
||||
}
|
||||
var values = enums.Select(e => Convert.ToInt32(e)).OrderBy(i => i).ToArray();
|
||||
int nextHole = min;
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (nextHole < value)
|
||||
{
|
||||
link_default_holes.AddLast((nextHole, Math.Min(value - 1, max)));
|
||||
if (value >= max)
|
||||
{
|
||||
nextHole = max;
|
||||
break;
|
||||
}
|
||||
nextHole = value + 1;
|
||||
}
|
||||
else if (nextHole == value)
|
||||
{
|
||||
if (value >= max)
|
||||
{
|
||||
break;
|
||||
}
|
||||
nextHole++;
|
||||
}
|
||||
}
|
||||
if (nextHole <= max && values[values.Length - 1] < max)
|
||||
{
|
||||
link_default_holes.AddLast((nextHole, max));
|
||||
}
|
||||
DefaultInited = true;
|
||||
}
|
||||
|
||||
public static void InitFinal()
|
||||
{
|
||||
dict_final_enums = new Dictionary<string, T>(dict_default_enums);
|
||||
dict_final_enums_lower = new Dictionary<string, T>(dict_default_enums_lower);
|
||||
link_final_holes = new LinkedList<(int start, int end)>(link_default_holes);
|
||||
}
|
||||
|
||||
public static void PrintResult()
|
||||
{
|
||||
//Log.Out($"{typeof(T).Name}:\n" + string.Join("\n", dict_final_enums.Select(p => $"name: {p.Key} value: {p.Value}")));
|
||||
}
|
||||
|
||||
public static T RegisterOrGetEnum(string passive, bool ignoreCase = false)
|
||||
{
|
||||
if (!(ignoreCase ? dict_final_enums_lower : dict_final_enums).TryGetValue(ignoreCase ? passive.ToLower() : passive, out var value))
|
||||
{
|
||||
if (link_final_holes.Count == 0)
|
||||
throw new OverflowException($"Enum count exceeds limit {max}!");
|
||||
(int start, int end) = link_final_holes.First.Value;
|
||||
link_final_holes.RemoveFirst();
|
||||
value = (T)Enum.ToObject(typeof(T), Convert.ChangeType(start, typecode));
|
||||
dict_final_enums.Add(passive, value);
|
||||
dict_final_enums_lower.Add(passive.ToLower(), value);
|
||||
if (start < end)
|
||||
{
|
||||
start++;
|
||||
link_final_holes.AddFirst((start, end));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user