170 lines
5.0 KiB
C#
170 lines
5.0 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using EntityStates;
|
||
|
using HG;
|
||
|
using JetBrains.Annotations;
|
||
|
using RoR2.ContentManagement;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace RoR2;
|
||
|
|
||
|
public static class EntityStateCatalog
|
||
|
{
|
||
|
private static readonly Dictionary<Type, EntityStateIndex> stateTypeToIndex = new Dictionary<Type, EntityStateIndex>(1000);
|
||
|
|
||
|
private static Type[] stateIndexToType = Array.Empty<Type>();
|
||
|
|
||
|
private static readonly Dictionary<Type, Action<object>> instanceFieldInitializers = new Dictionary<Type, Action<object>>();
|
||
|
|
||
|
private static string[] stateIndexToTypeName = Array.Empty<string>();
|
||
|
|
||
|
[Obsolete("This is only for use in legacy editors only until they're fully phased out.")]
|
||
|
public static string[] baseGameStateTypeNames = new string[0];
|
||
|
|
||
|
private static void SetStateInstanceInitializer([NotNull] Type stateType, [NotNull] Action<object> initializer)
|
||
|
{
|
||
|
if (typeof(EntityState).IsAssignableFrom(stateType))
|
||
|
{
|
||
|
instanceFieldInitializers[stateType] = initializer;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void InitializeStateFields([NotNull] EntityState entityState)
|
||
|
{
|
||
|
if (instanceFieldInitializers.TryGetValue(entityState.GetType(), out var value))
|
||
|
{
|
||
|
value(entityState);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerator SetElements(Type[] newEntityStateTypes, EntityStateConfiguration[] newEntityStateConfigurations)
|
||
|
{
|
||
|
ArrayUtils.CloneTo(newEntityStateTypes, ref stateIndexToType);
|
||
|
int _length = stateIndexToType.Length;
|
||
|
string[] typeNames = new string[_length];
|
||
|
for (int i = 0; i < _length; i++)
|
||
|
{
|
||
|
typeNames[i] = stateIndexToType[i].AssemblyQualifiedName;
|
||
|
}
|
||
|
yield return null;
|
||
|
Array.Sort(typeNames, stateIndexToType, StringComparer.Ordinal);
|
||
|
yield return null;
|
||
|
stateTypeToIndex.Clear();
|
||
|
for (int j = 0; j < _length; j++)
|
||
|
{
|
||
|
Type key = stateIndexToType[j];
|
||
|
stateTypeToIndex[key] = (EntityStateIndex)j;
|
||
|
}
|
||
|
yield return null;
|
||
|
Array.Resize(ref stateIndexToTypeName, stateIndexToType.Length);
|
||
|
for (int k = 0; k < stateIndexToType.Length; k++)
|
||
|
{
|
||
|
stateIndexToTypeName[k] = stateIndexToType[k].Name;
|
||
|
}
|
||
|
yield return null;
|
||
|
instanceFieldInitializers.Clear();
|
||
|
int limitForLoop = 10;
|
||
|
int loopIndex = 0;
|
||
|
for (_length = 0; _length < newEntityStateConfigurations.Length; _length++)
|
||
|
{
|
||
|
ApplyEntityStateConfiguration(newEntityStateConfigurations[_length]);
|
||
|
if (loopIndex++ >= limitForLoop)
|
||
|
{
|
||
|
loopIndex = 0;
|
||
|
yield return null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void ApplyEntityStateConfiguration(EntityStateConfiguration entityStateConfiguration)
|
||
|
{
|
||
|
Type type = (Type)entityStateConfiguration.targetType;
|
||
|
if (type == null)
|
||
|
{
|
||
|
Debug.LogFormat("ApplyEntityStateConfiguration({0}) failed: state type is null.", entityStateConfiguration);
|
||
|
return;
|
||
|
}
|
||
|
if (!stateTypeToIndex.ContainsKey(type))
|
||
|
{
|
||
|
Debug.LogFormat("ApplyEntityStateConfiguration({0}) failed: state type {1} is not registered.", entityStateConfiguration, type.FullName);
|
||
|
return;
|
||
|
}
|
||
|
entityStateConfiguration.ApplyStatic();
|
||
|
Action<object> action = entityStateConfiguration.BuildInstanceInitializer();
|
||
|
if (action == null)
|
||
|
{
|
||
|
instanceFieldInitializers.Remove(type);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
instanceFieldInitializers[type] = action;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void OnStateConfigurationUpdatedByEditor(EntityStateConfiguration entityStateConfiguration)
|
||
|
{
|
||
|
ApplyEntityStateConfiguration(entityStateConfiguration);
|
||
|
}
|
||
|
|
||
|
public static IEnumerator Init()
|
||
|
{
|
||
|
EntityStateConfiguration.onEditorUpdatedConfigurationGlobal += OnStateConfigurationUpdatedByEditor;
|
||
|
yield return SetElements(ContentManager.entityStateTypes, ContentManager.entityStateConfigurations);
|
||
|
}
|
||
|
|
||
|
public static EntityStateIndex GetStateIndex(Type entityStateType)
|
||
|
{
|
||
|
if (stateTypeToIndex.TryGetValue(entityStateType, out var value))
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
return EntityStateIndex.Invalid;
|
||
|
}
|
||
|
|
||
|
public static Type GetStateType(EntityStateIndex entityStateIndex)
|
||
|
{
|
||
|
Type[] array = stateIndexToType;
|
||
|
Type defaultValue = null;
|
||
|
return ArrayUtils.GetSafe(array, (int)entityStateIndex, in defaultValue);
|
||
|
}
|
||
|
|
||
|
[CanBeNull]
|
||
|
public static string GetStateTypeName(Type entityStateType)
|
||
|
{
|
||
|
return GetStateTypeName(GetStateIndex(entityStateType));
|
||
|
}
|
||
|
|
||
|
[CanBeNull]
|
||
|
public static string GetStateTypeName(EntityStateIndex entityStateIndex)
|
||
|
{
|
||
|
return ArrayUtils.GetSafe(stateIndexToTypeName, (int)entityStateIndex);
|
||
|
}
|
||
|
|
||
|
public static EntityState InstantiateState(EntityStateIndex entityStateIndex)
|
||
|
{
|
||
|
Type stateType = GetStateType(entityStateIndex);
|
||
|
if (stateType != null)
|
||
|
{
|
||
|
return Activator.CreateInstance(stateType) as EntityState;
|
||
|
}
|
||
|
Debug.LogFormat("Bad stateTypeIndex {0}", entityStateIndex);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static EntityState InstantiateState(Type stateType)
|
||
|
{
|
||
|
if (stateType != null && stateType.IsSubclassOf(typeof(EntityState)))
|
||
|
{
|
||
|
return Activator.CreateInstance(stateType) as EntityState;
|
||
|
}
|
||
|
Debug.LogFormat("Bad stateType {0}", (stateType == null) ? "null" : stateType.FullName);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static EntityState InstantiateState(ref SerializableEntityStateType serializableStateType)
|
||
|
{
|
||
|
return InstantiateState(serializableStateType.stateType);
|
||
|
}
|
||
|
}
|