public static bool HandlesMatch(object item, string handle) { if (item == null) { return(false); } if (handle.NullOrEmpty()) { return(false); } handle = TranslationHandleUtility.NormalizedHandle(handle); if (handle.NullOrEmpty()) { return(false); } Type type = item as Type; if (type != null) { return(TranslationHandleUtility.NormalizedHandle(type.Name) == handle || TranslationHandleUtility.NormalizedHandle(type.FullName) == handle || TranslationHandleUtility.NormalizedHandle(type.ToString()) == handle); } string text; try { text = item.ToString(); } catch (Exception arg) { throw new InvalidOperationException("Could not get element by handle because one of the elements threw an exception in its ToString(): " + arg); } return(!text.NullOrEmpty() && TranslationHandleUtility.NormalizedHandle(text) == handle); }
private static void ForEachPossibleDefInjectionInDefRecursive(object obj, string curNormalizedPath, string curSuggestedPath, HashSet <object> visited, bool translationAllowed, Def def, PossibleDefInjectionTraverser action) { if (obj == null || (!obj.GetType().IsValueType&& visited.Contains(obj))) { return; } visited.Add(obj); foreach (FieldInfo item in FieldsInDeterministicOrder(obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))) { object value = item.GetValue(obj); bool flag = translationAllowed && !item.HasAttribute <NoTranslateAttribute>() && !item.HasAttribute <UnsavedAttribute>(); if (value is Def) { continue; } if (typeof(string).IsAssignableFrom(item.FieldType)) { string currentValue = (string)value; string text = curNormalizedPath + "." + item.Name; string suggestedPath = curSuggestedPath + "." + item.Name; if (TKeySystem.TrySuggestTKeyPath(text, out var tKeyPath)) { suggestedPath = tKeyPath; } action(suggestedPath, text, isCollection: false, currentValue, null, flag, fullListTranslationAllowed: false, item, def); } else if (value is IEnumerable <string> ) { IEnumerable <string> currentValueCollection = (IEnumerable <string>)value; bool flag2 = item.HasAttribute <TranslationCanChangeCountAttribute>(); string text2 = curNormalizedPath + "." + item.Name; string suggestedPath2 = curSuggestedPath + "." + item.Name; if (TKeySystem.TrySuggestTKeyPath(text2, out var tKeyPath2)) { suggestedPath2 = tKeyPath2; } action(suggestedPath2, text2, isCollection: true, null, currentValueCollection, flag, flag && flag2, item, def); } else if (value is IEnumerable) { IEnumerable enumerable = (IEnumerable)value; int num = 0; foreach (object item2 in enumerable) { if (item2 != null && !(item2 is Def) && GenTypes.IsCustomType(item2.GetType())) { string text3 = TranslationHandleUtility.GetBestHandleWithIndexForListElement(enumerable, item2); if (text3.NullOrEmpty()) { text3 = num.ToString(); } string curNormalizedPath2 = curNormalizedPath + "." + item.Name + "." + num; string curSuggestedPath2 = curSuggestedPath + "." + item.Name + "." + text3; ForEachPossibleDefInjectionInDefRecursive(item2, curNormalizedPath2, curSuggestedPath2, visited, flag, def, action); } num++; } } else if (value != null && GenTypes.IsCustomType(value.GetType())) { string curNormalizedPath3 = curNormalizedPath + "." + item.Name; string curSuggestedPath3 = curSuggestedPath + "." + item.Name; ForEachPossibleDefInjectionInDefRecursive(value, curNormalizedPath3, curSuggestedPath3, visited, flag, def, action); } } }
private bool SetDefFieldAtPath(Type defType, string path, object value, Type ensureFieldType, bool errorOnDefNotFound, string fileSource, bool isPlaceholder, out string normalizedPath, out string suggestedPath, out string replacedString, out IEnumerable <string> replacedStringsList) { replacedString = null; replacedStringsList = null; normalizedPath = path; suggestedPath = path; string text = path.Split(new char[] { '.' })[0]; text = BackCompatibility.BackCompatibleDefName(defType, text, true); if (GenDefDatabase.GetDefSilentFail(defType, text, false) == null) { if (errorOnDefNotFound) { this.loadErrors.Add(string.Concat(new object[] { "Found no ", defType, " named ", text, " to match ", path, " (", fileSource, ")" })); } return(false); } bool flag = false; int num = 0; bool result; try { List <string> list = path.Split(new char[] { '.' }).ToList <string>(); object obj = GenGeneric.InvokeStaticMethodOnGenericType(typeof(DefDatabase <>), defType, "GetNamedSilentFail", new object[] { list[0] }); if (obj == null) { throw new InvalidOperationException("Def named " + list[0] + " not found."); } list.RemoveAt(0); num++; string text2; int num2; DefInjectionPathPartKind defInjectionPathPartKind; FieldInfo field; int num3; int num4; while (true) { text2 = list[0]; num2 = -1; if (int.TryParse(text2, out num2)) { defInjectionPathPartKind = DefInjectionPathPartKind.ListIndex; } else if (this.GetFieldNamed(obj.GetType(), text2) != null) { defInjectionPathPartKind = DefInjectionPathPartKind.Field; } else if (obj.GetType().GetProperty("Count") != null) { if (text2.Contains('-')) { defInjectionPathPartKind = DefInjectionPathPartKind.ListHandleWithIndex; string[] array = text2.Split(new char[] { '-' }); text2 = array[0]; num2 = (int)ParseHelper.FromString(array[1], typeof(int)); } else { defInjectionPathPartKind = DefInjectionPathPartKind.ListHandle; } } else { defInjectionPathPartKind = DefInjectionPathPartKind.Field; } if (list.Count == 1) { break; } if (defInjectionPathPartKind == DefInjectionPathPartKind.Field) { field = obj.GetType().GetField(text2, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { goto Block_41; } if (field.HasAttribute <NoTranslateAttribute>()) { goto Block_42; } if (field.HasAttribute <UnsavedAttribute>()) { goto Block_43; } if (field.HasAttribute <TranslationCanChangeCountAttribute>()) { flag = true; } if (defInjectionPathPartKind == DefInjectionPathPartKind.Field) { obj = field.GetValue(obj); } else { object value2 = field.GetValue(obj); PropertyInfo property = value2.GetType().GetProperty("Item"); if (property == null) { goto Block_46; } num3 = (int)value2.GetType().GetProperty("Count").GetValue(value2, null); if (num2 < 0 || num2 >= num3) { goto IL_ADC; } obj = property.GetValue(value2, new object[] { num2 }); } } else if (defInjectionPathPartKind == DefInjectionPathPartKind.ListIndex || defInjectionPathPartKind == DefInjectionPathPartKind.ListHandle || defInjectionPathPartKind == DefInjectionPathPartKind.ListHandleWithIndex) { object obj2 = obj; PropertyInfo property2 = obj2.GetType().GetProperty("Item"); if (property2 == null) { goto Block_50; } bool flag2; if (defInjectionPathPartKind == DefInjectionPathPartKind.ListHandle || defInjectionPathPartKind == DefInjectionPathPartKind.ListHandleWithIndex) { num2 = TranslationHandleUtility.GetElementIndexByHandle(obj2, text2, num2); defInjectionPathPartKind = DefInjectionPathPartKind.ListIndex; flag2 = true; } else { flag2 = false; } num4 = (int)obj2.GetType().GetProperty("Count").GetValue(obj2, null); if (num2 < 0 || num2 >= num4) { goto IL_BB7; } obj = property2.GetValue(obj2, new object[] { num2 }); if (flag2) { string[] array2 = normalizedPath.Split(new char[] { '.' }); array2[num] = num2.ToString(); normalizedPath = string.Join(".", array2); } else { string bestHandleWithIndexForListElement = TranslationHandleUtility.GetBestHandleWithIndexForListElement(obj2, obj); if (!bestHandleWithIndexForListElement.NullOrEmpty()) { string[] array3 = suggestedPath.Split(new char[] { '.' }); array3[num] = bestHandleWithIndexForListElement; suggestedPath = string.Join(".", array3); } } } else { this.loadErrors.Add(string.Concat(new object[] { "Can't enter node ", text2, " at path ", path, ", element kind is ", defInjectionPathPartKind, ". (", fileSource, ")" })); } list.RemoveAt(0); num++; } bool flag3 = false; foreach (KeyValuePair <string, DefInjectionPackage.DefInjection> current in this.injections) { if (!(current.Key == path)) { if (current.Value.injected && current.Value.normalizedPath == normalizedPath) { string text3 = string.Concat(new string[] { "Duplicate def-injected translation key. Both ", current.Value.path, " and ", path, " refer to the same field (", suggestedPath, ")" }); if (current.Value.path != current.Value.nonBackCompatiblePath) { string text4 = text3; text3 = string.Concat(new string[] { text4, " (", current.Value.nonBackCompatiblePath, " was auto-renamed to ", current.Value.path, ")" }); } text3 = text3 + " (" + current.Value.fileSource + ")"; this.loadErrors.Add(text3); flag3 = true; break; } } } bool flag4 = false; if (!flag3) { if (defInjectionPathPartKind == DefInjectionPathPartKind.Field) { FieldInfo fieldNamed = this.GetFieldNamed(obj.GetType(), text2); if (fieldNamed == null) { throw new InvalidOperationException(string.Concat(new object[] { "Field ", text2, " does not exist in type ", obj.GetType(), "." })); } if (fieldNamed.HasAttribute <NoTranslateAttribute>()) { this.loadErrors.Add(string.Concat(new object[] { "Translated untranslatable field ", fieldNamed.Name, " of type ", fieldNamed.FieldType, " at path ", path, ". Translating this field will break the game. (", fileSource, ")" })); } else if (fieldNamed.HasAttribute <UnsavedAttribute>()) { this.loadErrors.Add(string.Concat(new object[] { "Translated untranslatable field (UnsavedAttribute) ", fieldNamed.Name, " of type ", fieldNamed.FieldType, " at path ", path, ". Translating this field will break the game. (", fileSource, ")" })); } else if (!isPlaceholder && fieldNamed.FieldType != ensureFieldType) { this.loadErrors.Add(string.Concat(new object[] { "Translated non-", ensureFieldType, " field ", fieldNamed.Name, " of type ", fieldNamed.FieldType, " at path ", path, ". Expected ", ensureFieldType, ". (", fileSource, ")" })); } else if (!isPlaceholder && ensureFieldType != typeof(string) && !fieldNamed.HasAttribute <TranslationCanChangeCountAttribute>()) { this.loadErrors.Add(string.Concat(new object[] { "Tried to translate field ", fieldNamed.Name, " of type ", fieldNamed.FieldType, " at path ", path, ", but this field doesn't have [TranslationCanChangeCount] attribute so it doesn't allow this type of translation. (", fileSource, ")" })); } else if (!isPlaceholder) { if (ensureFieldType == typeof(string)) { replacedString = (string)fieldNamed.GetValue(obj); } else { replacedStringsList = (fieldNamed.GetValue(obj) as IEnumerable <string>); } fieldNamed.SetValue(obj, value); flag4 = true; } } else if (defInjectionPathPartKind == DefInjectionPathPartKind.ListIndex || defInjectionPathPartKind == DefInjectionPathPartKind.ListHandle || defInjectionPathPartKind == DefInjectionPathPartKind.ListHandleWithIndex) { object obj3 = obj; if (obj3 == null) { throw new InvalidOperationException("Tried to use index on null list at " + path); } Type type = obj3.GetType(); PropertyInfo property3 = type.GetProperty("Count"); if (property3 == null) { throw new InvalidOperationException("Tried to use index on non-list (missing 'Count' property)."); } if (defInjectionPathPartKind == DefInjectionPathPartKind.ListHandle || defInjectionPathPartKind == DefInjectionPathPartKind.ListHandleWithIndex) { num2 = TranslationHandleUtility.GetElementIndexByHandle(obj3, text2, num2); defInjectionPathPartKind = DefInjectionPathPartKind.ListIndex; } int num5 = (int)property3.GetValue(obj3, null); if (num2 >= num5) { throw new InvalidOperationException(string.Concat(new object[] { "Trying to translate ", defType, ".", path, " at index ", num2, " but the list only has ", num5, " entries (so max index is ", (num5 - 1).ToString(), ")." })); } PropertyInfo property4 = type.GetProperty("Item"); if (property4 == null) { throw new InvalidOperationException("Tried to use index on non-list (missing 'Item' property)."); } Type propertyType = property4.PropertyType; if (!isPlaceholder && propertyType != ensureFieldType) { this.loadErrors.Add(string.Concat(new object[] { "Translated non-", ensureFieldType, " list item of type ", propertyType, " at path ", path, ". Expected ", ensureFieldType, ". (", fileSource, ")" })); } else if (!isPlaceholder && ensureFieldType != typeof(string) && !flag) { this.loadErrors.Add(string.Concat(new object[] { "Tried to translate field of type ", propertyType, " at path ", path, ", but this field doesn't have [TranslationCanChangeCount] attribute so it doesn't allow this type of translation. (", fileSource, ")" })); } else if (num2 < 0 || num2 >= (int)type.GetProperty("Count").GetValue(obj3, null)) { this.loadErrors.Add("Index out of bounds (max index is " + ((int)type.GetProperty("Count").GetValue(obj3, null) - 1) + ")"); } else if (!isPlaceholder) { replacedString = (string)property4.GetValue(obj3, new object[] { num2 }); property4.SetValue(obj3, value, new object[] { num2 }); flag4 = true; } } else { this.loadErrors.Add(string.Concat(new object[] { "Translated ", text2, " at path ", path, " but it's not a field, it's ", defInjectionPathPartKind, ". (", fileSource, ")" })); } } if (path != suggestedPath) { IList <string> list2 = value as IList <string>; string text5; if (list2 != null) { text5 = list2.ToStringSafeEnumerable(); } else { text5 = value.ToString(); } this.loadSyntaxSuggestions.Add(string.Concat(new string[] { "Consider using ", suggestedPath, " instead of ", path, " for translation '", text5, "' (", fileSource, ")" })); } result = flag4; return(result); Block_41: throw new InvalidOperationException("Field " + text2 + " does not exist."); Block_42: throw new InvalidOperationException(string.Concat(new object[] { "Translated untranslatable field ", field.Name, " of type ", field.FieldType, " at path ", path, ". Translating this field will break the game." })); Block_43: throw new InvalidOperationException(string.Concat(new object[] { "Translated untranslatable field ([Unsaved] attribute) ", field.Name, " of type ", field.FieldType, " at path ", path, ". Translating this field will break the game." })); Block_46: throw new InvalidOperationException("Tried to use index on non-list (missing 'Item' property)."); IL_ADC: throw new InvalidOperationException("Index out of bounds (max index is " + (num3 - 1) + ")"); Block_50: throw new InvalidOperationException("Tried to use index on non-list (missing 'Item' property)."); IL_BB7: throw new InvalidOperationException("Index out of bounds (max index is " + (num4 - 1) + ")"); } catch (Exception ex) { string text6 = string.Concat(new object[] { "Couldn't inject ", path, " into ", defType, " (", fileSource, "): ", ex.Message }); if (ex.InnerException != null) { text6 = text6 + " -> " + ex.InnerException.Message; } this.loadErrors.Add(text6); result = false; } return(result); }
public static int GetElementIndexByHandle(object list, string handle, int handleIndex) { if (list == null) { throw new InvalidOperationException("Tried to get element by handle on null object."); } if (handleIndex < 0) { handleIndex = 0; } PropertyInfo property = list.GetType().GetProperty("Count"); if (property == null) { throw new InvalidOperationException("Tried to get element by handle on non-list (missing 'Count' property)."); } PropertyInfo property2 = list.GetType().GetProperty("Item"); if (property2 == null) { throw new InvalidOperationException("Tried to get element by handle on non-list (missing 'Item' property)."); } int num = (int)property.GetValue(list, null); FieldInfo fieldInfo = null; int num2 = 0; for (int i = 0; i < num; i++) { object value = property2.GetValue(list, new object[] { i }); if (value != null) { FieldInfo[] fields = value.GetType().GetFields(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; for (int j = 0; j < array.Length; j++) { FieldInfo fieldInfo2 = array[j]; TranslationHandleAttribute translationHandleAttribute = fieldInfo2.TryGetAttribute <TranslationHandleAttribute>(); if (translationHandleAttribute != null) { object value2 = fieldInfo2.GetValue(value); if (value2 != null) { if (TranslationHandleUtility.HandlesMatch(value2, handle)) { int priority = translationHandleAttribute.Priority; if (fieldInfo == null || priority > num2) { fieldInfo = fieldInfo2; num2 = priority; } } } } } } } if (fieldInfo == null) { throw new InvalidOperationException("None of the list elements have a handle named " + handle + "."); } int num3 = 0; for (int k = 0; k < num; k++) { object value3 = property2.GetValue(list, new object[] { k }); if (value3 != null) { FieldInfo[] fields2 = value3.GetType().GetFields(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array2 = fields2; for (int l = 0; l < array2.Length; l++) { FieldInfo fieldInfo3 = array2[l]; if (TranslationHandleUtility.FieldInfosEqual(fieldInfo3, fieldInfo)) { object value4 = fieldInfo3.GetValue(value3); if (value4 != null) { if (TranslationHandleUtility.HandlesMatch(value4, handle)) { if (num3 == handleIndex) { return(k); } num3++; } } } } } } throw new InvalidOperationException(string.Concat(new object[] { "Tried to access handle ", handle, "[", handleIndex, "], but there are only ", num3, " handles matching this name." })); }
public static string GetBestHandleWithIndexForListElement(object list, object element) { if (list == null || element == null) { return(null); } PropertyInfo property = list.GetType().GetProperty("Count"); if (property == null) { return(null); } PropertyInfo property2 = list.GetType().GetProperty("Item"); if (property2 == null) { return(null); } FieldInfo fieldInfo = null; string handle = null; int num = 0; FieldInfo[] fields = element.GetType().GetFields(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; for (int i = 0; i < array.Length; i++) { FieldInfo fieldInfo2 = array[i]; TranslationHandleAttribute translationHandleAttribute = fieldInfo2.TryGetAttribute <TranslationHandleAttribute>(); if (translationHandleAttribute != null) { object value = fieldInfo2.GetValue(element); if (value != null) { Type type = value as Type; string text; if (type != null) { text = type.Name; } else { try { text = value.ToString(); } catch { return(null); } } if (!text.NullOrEmpty()) { int priority = translationHandleAttribute.Priority; if (fieldInfo == null || priority > num) { fieldInfo = fieldInfo2; handle = text; num = priority; } } } } } if (fieldInfo == null) { return(null); } int num2 = 0; int num3 = -1; int num4 = (int)property.GetValue(list, null); for (int j = 0; j < num4; j++) { object value2 = property2.GetValue(list, new object[] { j }); if (value2 != null) { if (value2 == element) { num3 = num2; num2++; } else { FieldInfo[] fields2 = value2.GetType().GetFields(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array2 = fields2; for (int k = 0; k < array2.Length; k++) { FieldInfo fieldInfo3 = array2[k]; if (TranslationHandleUtility.FieldInfosEqual(fieldInfo3, fieldInfo)) { object value3 = fieldInfo3.GetValue(value2); if (value3 != null) { if (TranslationHandleUtility.HandlesMatch(value3, handle)) { num2++; break; } } } } } } } if (num3 < 0) { return(null); } string text2 = TranslationHandleUtility.NormalizedHandle(handle); if (num2 <= 1) { return(text2); } return(text2 + '-' + num3); }
private static void ForEachPossibleDefInjectionInDefRecursive(object obj, string curNormalizedPath, string curSuggestedPath, HashSet <object> visited, bool translationAllowed, Def def, DefInjectionUtility.PossibleDefInjectionTraverser action) { if (obj == null) { return; } if (visited.Contains(obj)) { return; } visited.Add(obj); foreach (FieldInfo fieldInfo in DefInjectionUtility.FieldsInDeterministicOrder(obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))) { object value = fieldInfo.GetValue(obj); bool flag = translationAllowed && !fieldInfo.HasAttribute <NoTranslateAttribute>() && !fieldInfo.HasAttribute <UnsavedAttribute>(); if (!(value is Def)) { if (typeof(string).IsAssignableFrom(fieldInfo.FieldType)) { string currentValue = (string)value; string normalizedPath = curNormalizedPath + "." + fieldInfo.Name; string suggestedPath = curSuggestedPath + "." + fieldInfo.Name; action(suggestedPath, normalizedPath, false, currentValue, null, flag, false, fieldInfo, def); } else if (value is IEnumerable <string> ) { IEnumerable <string> currentValueCollection = (IEnumerable <string>)value; bool flag2 = fieldInfo.HasAttribute <TranslationCanChangeCountAttribute>(); string normalizedPath2 = curNormalizedPath + "." + fieldInfo.Name; string suggestedPath2 = curSuggestedPath + "." + fieldInfo.Name; action(suggestedPath2, normalizedPath2, true, null, currentValueCollection, flag, flag && flag2, fieldInfo, def); } else if (value is IEnumerable) { IEnumerable enumerable = (IEnumerable)value; int num = 0; IEnumerator enumerator2 = enumerable.GetEnumerator(); try { while (enumerator2.MoveNext()) { object obj2 = enumerator2.Current; if (obj2 != null && !(obj2 is Def) && GenTypes.IsCustomType(obj2.GetType())) { string text = TranslationHandleUtility.GetBestHandleWithIndexForListElement(enumerable, obj2); if (text.NullOrEmpty()) { text = num.ToString(); } string curNormalizedPath2 = string.Concat(new object[] { curNormalizedPath, ".", fieldInfo.Name, ".", num }); string curSuggestedPath2 = string.Concat(new string[] { curSuggestedPath, ".", fieldInfo.Name, ".", text }); DefInjectionUtility.ForEachPossibleDefInjectionInDefRecursive(obj2, curNormalizedPath2, curSuggestedPath2, visited, flag, def, action); } num++; } } finally { IDisposable disposable; if ((disposable = (enumerator2 as IDisposable)) != null) { disposable.Dispose(); } } } else if (value != null && GenTypes.IsCustomType(value.GetType())) { string curNormalizedPath3 = curNormalizedPath + "." + fieldInfo.Name; string curSuggestedPath3 = curSuggestedPath + "." + fieldInfo.Name; DefInjectionUtility.ForEachPossibleDefInjectionInDefRecursive(value, curNormalizedPath3, curSuggestedPath3, visited, flag, def, action); } } } }
private bool SetDefFieldAtPath(Type defType, string path, object value, Type ensureFieldType, bool errorOnDefNotFound, string fileSource, bool isPlaceholder, out string normalizedPath, out string suggestedPath, out string replacedString, out IEnumerable <string> replacedStringsList) { replacedString = null; replacedStringsList = null; string b = path; string text = path; bool flag = TKeySystem.TryGetNormalizedPath(path, out normalizedPath); if (flag) { text = text + " (" + normalizedPath + ")"; suggestedPath = path; path = normalizedPath; } else { normalizedPath = path; suggestedPath = path; } string defName = path.Split('.')[0]; defName = BackCompatibility.BackCompatibleDefName(defType, defName, forDefInjections: true); if (GenDefDatabase.GetDefSilentFail(defType, defName, specialCaseForSoundDefs: false) == null) { if (errorOnDefNotFound) { loadErrors.Add("Found no " + defType + " named " + defName + " to match " + text + " (" + fileSource + ")"); } return(false); } bool flag2 = false; int num = 0; List <object> list = new List <object>(); try { List <string> list2 = path.Split('.').ToList(); object obj = GenGeneric.InvokeStaticMethodOnGenericType(typeof(DefDatabase <>), defType, "GetNamedSilentFail", list2[0]); if (obj == null) { throw new InvalidOperationException("Def named " + list2[0] + " not found."); } num++; string text2; int result; DefInjectionPathPartKind defInjectionPathPartKind; while (true) { text2 = list2[num]; list.Add(obj); result = -1; if (int.TryParse(text2, out result)) { defInjectionPathPartKind = DefInjectionPathPartKind.ListIndex; } else if (GetFieldNamed(obj.GetType(), text2) != null) { defInjectionPathPartKind = DefInjectionPathPartKind.Field; } else if (obj.GetType().GetProperty("Count") != null) { if (text2.Contains('-')) { defInjectionPathPartKind = DefInjectionPathPartKind.ListHandleWithIndex; string[] array = text2.Split('-'); text2 = array[0]; result = ParseHelper.FromString <int>(array[1]); } else { defInjectionPathPartKind = DefInjectionPathPartKind.ListHandle; } } else { defInjectionPathPartKind = DefInjectionPathPartKind.Field; } if (num == list2.Count - 1) { break; } switch (defInjectionPathPartKind) { case DefInjectionPathPartKind.Field: { FieldInfo field = obj.GetType().GetField(text2, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { throw new InvalidOperationException("Field or TKey " + text2 + " does not exist."); } if (field.HasAttribute <NoTranslateAttribute>()) { throw new InvalidOperationException("Translated untranslatable field " + field.Name + " of type " + field.FieldType + " at path " + text + ". Translating this field will break the game."); } if (field.HasAttribute <UnsavedAttribute>()) { throw new InvalidOperationException("Translated untranslatable field ([Unsaved] attribute) " + field.Name + " of type " + field.FieldType + " at path " + text + ". Translating this field will break the game."); } if (field.HasAttribute <TranslationCanChangeCountAttribute>()) { flag2 = true; } if (defInjectionPathPartKind == DefInjectionPathPartKind.Field) { obj = field.GetValue(obj); } else { object value2 = field.GetValue(obj); PropertyInfo property2 = value2.GetType().GetProperty("Item"); if (property2 == null) { throw new InvalidOperationException("Tried to use index on non-list (missing 'Item' property)."); } int num3 = (int)value2.GetType().GetProperty("Count").GetValue(value2, null); if (result < 0 || result >= num3) { throw new InvalidOperationException("Index out of bounds (max index is " + (num3 - 1) + ")"); } obj = property2.GetValue(value2, new object[1] { result }); } break; } case DefInjectionPathPartKind.ListIndex: case DefInjectionPathPartKind.ListHandle: case DefInjectionPathPartKind.ListHandleWithIndex: { object obj2 = obj; PropertyInfo property = obj2.GetType().GetProperty("Item"); if (property == null) { throw new InvalidOperationException("Tried to use index on non-list (missing 'Item' property)."); } bool flag3; if (defInjectionPathPartKind == DefInjectionPathPartKind.ListHandle || defInjectionPathPartKind == DefInjectionPathPartKind.ListHandleWithIndex) { result = TranslationHandleUtility.GetElementIndexByHandle(obj2, text2, result); defInjectionPathPartKind = DefInjectionPathPartKind.ListIndex; flag3 = true; } else { flag3 = false; } int num2 = (int)obj2.GetType().GetProperty("Count").GetValue(obj2, null); if (result < 0 || result >= num2) { throw new InvalidOperationException("Index out of bounds (max index is " + (num2 - 1) + ")"); } obj = property.GetValue(obj2, new object[1] { result }); if (flag3) { string[] array2 = normalizedPath.Split('.'); array2[num] = result.ToString(); normalizedPath = string.Join(".", array2); } else if (!flag) { string bestHandleWithIndexForListElement = TranslationHandleUtility.GetBestHandleWithIndexForListElement(obj2, obj); if (!bestHandleWithIndexForListElement.NullOrEmpty()) { string[] array3 = suggestedPath.Split('.'); array3[num] = bestHandleWithIndexForListElement; suggestedPath = string.Join(".", array3); } } break; } default: loadErrors.Add("Can't enter node " + text2 + " at path " + text + ", element kind is " + defInjectionPathPartKind + ". (" + fileSource + ")"); break; } num++; } bool flag4 = false; foreach (KeyValuePair <string, DefInjection> injection in injections) { if (!(injection.Key == b) && injection.Value.injected && injection.Value.normalizedPath == normalizedPath) { string text3 = "Duplicate def-injected translation key. Both " + injection.Value.path + " and " + text + " refer to the same field (" + suggestedPath + ")"; if (injection.Value.path != injection.Value.nonBackCompatiblePath) { text3 = text3 + " (" + injection.Value.nonBackCompatiblePath + " was auto-renamed to " + injection.Value.path + ")"; } text3 = text3 + " (" + injection.Value.fileSource + ")"; loadErrors.Add(text3); flag4 = true; break; } } bool result2 = false; if (!flag4) { switch (defInjectionPathPartKind) { case DefInjectionPathPartKind.Field: { FieldInfo fieldNamed = GetFieldNamed(obj.GetType(), text2); if (fieldNamed == null) { throw new InvalidOperationException("Field " + text2 + " does not exist in type " + obj.GetType() + "."); } if (fieldNamed.HasAttribute <NoTranslateAttribute>()) { loadErrors.Add("Translated untranslatable field " + fieldNamed.Name + " of type " + fieldNamed.FieldType + " at path " + text + ". Translating this field will break the game. (" + fileSource + ")"); } else if (fieldNamed.HasAttribute <UnsavedAttribute>()) { loadErrors.Add("Translated untranslatable field (UnsavedAttribute) " + fieldNamed.Name + " of type " + fieldNamed.FieldType + " at path " + text + ". Translating this field will break the game. (" + fileSource + ")"); } else if (!isPlaceholder && fieldNamed.FieldType != ensureFieldType) { loadErrors.Add("Translated non-" + ensureFieldType + " field " + fieldNamed.Name + " of type " + fieldNamed.FieldType + " at path " + text + ". Expected " + ensureFieldType + ". (" + fileSource + ")"); } else if (!isPlaceholder && ensureFieldType != typeof(string) && !fieldNamed.HasAttribute <TranslationCanChangeCountAttribute>()) { loadErrors.Add("Tried to translate field " + fieldNamed.Name + " of type " + fieldNamed.FieldType + " at path " + text + ", but this field doesn't have [TranslationCanChangeCount] attribute so it doesn't allow this type of translation. (" + fileSource + ")"); } else if (!isPlaceholder) { if (ensureFieldType == typeof(string)) { replacedString = (string)fieldNamed.GetValue(obj); } else { replacedStringsList = (fieldNamed.GetValue(obj) as IEnumerable <string>); } fieldNamed.SetValue(obj, value); result2 = true; } break; } case DefInjectionPathPartKind.ListIndex: case DefInjectionPathPartKind.ListHandle: case DefInjectionPathPartKind.ListHandleWithIndex: { object obj3 = obj; if (obj3 == null) { throw new InvalidOperationException("Tried to use index on null list at " + text); } Type type = obj3.GetType(); PropertyInfo property3 = type.GetProperty("Count"); if (property3 == null) { throw new InvalidOperationException("Tried to use index on non-list (missing 'Count' property)."); } if (defInjectionPathPartKind == DefInjectionPathPartKind.ListHandle || defInjectionPathPartKind == DefInjectionPathPartKind.ListHandleWithIndex) { result = TranslationHandleUtility.GetElementIndexByHandle(obj3, text2, result); defInjectionPathPartKind = DefInjectionPathPartKind.ListIndex; } int num4 = (int)property3.GetValue(obj3, null); if (result >= num4) { throw new InvalidOperationException("Trying to translate " + defType + "." + text + " at index " + result + " but the list only has " + num4 + " entries (so max index is " + (num4 - 1).ToString() + ")."); } PropertyInfo property4 = type.GetProperty("Item"); if (property4 == null) { throw new InvalidOperationException("Tried to use index on non-list (missing 'Item' property)."); } Type propertyType = property4.PropertyType; if (!isPlaceholder && propertyType != ensureFieldType) { loadErrors.Add("Translated non-" + ensureFieldType + " list item of type " + propertyType + " at path " + text + ". Expected " + ensureFieldType + ". (" + fileSource + ")"); } else if (!isPlaceholder && ensureFieldType != typeof(string) && !flag2) { loadErrors.Add("Tried to translate field of type " + propertyType + " at path " + text + ", but this field doesn't have [TranslationCanChangeCount] attribute so it doesn't allow this type of translation. (" + fileSource + ")"); } else if (result < 0 || result >= (int)type.GetProperty("Count").GetValue(obj3, null)) { loadErrors.Add("Index out of bounds (max index is " + ((int)type.GetProperty("Count").GetValue(obj3, null) - 1) + ")"); } else if (!isPlaceholder) { replacedString = (string)property4.GetValue(obj3, new object[1] { result }); property4.SetValue(obj3, value, new object[1] { result }); result2 = true; } break; } default: loadErrors.Add("Translated " + text2 + " at path " + text + " but it's not a field, it's " + defInjectionPathPartKind + ". (" + fileSource + ")"); break; } } for (int num5 = list.Count - 1; num5 > 0; num5--) { if (list[num5].GetType().IsValueType&& !list[num5].GetType().IsPrimitive) { FieldInfo fieldNamed2 = GetFieldNamed(list[num5 - 1].GetType(), list2[num5]); if (fieldNamed2 != null) { fieldNamed2.SetValue(list[num5 - 1], list[num5]); } } } string tKeyPath; if (flag) { path = suggestedPath; } else if (TKeySystem.TrySuggestTKeyPath(path, out tKeyPath)) { suggestedPath = tKeyPath; } if (path != suggestedPath) { IList <string> list3 = value as IList <string>; string text4 = (list3 == null) ? value.ToString() : list3.ToStringSafeEnumerable(); loadSyntaxSuggestions.Add("Consider using " + suggestedPath + " instead of " + text + " for translation '" + text4 + "' (" + fileSource + ")"); } return(result2); } catch (Exception ex) { string text5 = "Couldn't inject " + text + " into " + defType + " (" + fileSource + "): " + ex.Message; if (ex.InnerException != null) { text5 = text5 + " -> " + ex.InnerException.Message; } loadErrors.Add(text5); return(false); } }