using System.Collections.Generic; using Newlon.Components.Plants; using Newlon.Systems.Effects; using Godot; using Newlon.Resources; namespace Newlon; public static class DescriptionParser { public static string GetParsed(EntityResource resource, Node searchScene) { string descriptionText; if (resource.isDescriptionParsed == false) { var unparsedDescription = TranslationServer.Translate(resource.DescriptionKey); var keys = GetRequestedKeys(unparsedDescription); FillPlaceholders(keys, resource, searchScene); descriptionText = ReplaceTextUsingDict(keys, unparsedDescription); resource.parsedDescription = descriptionText; resource.isDescriptionParsed = true; } else { descriptionText = resource.parsedDescription; } return descriptionText; } private static Dictionary GetRequestedKeys(string text) { var result = new Dictionary(); int start = -1; for (int i = 0; i < text.Length; i++) { if (text[i] == '{') { start = i; } if (text[i] == '}') { if (start == -1) continue; result.Add(text.Substr(start + 1, i - start - 1), 0); start = -1; } } return result; } private static void FillPlaceholders(Dictionary placeholderDictionary, EntityResource resource, Node searchScene) { var searchList = new List() { resource, searchScene }; while (searchList.Count > 0) { var lookedObject = searchList[0]; searchList.RemoveAt(0); if (lookedObject is Node lookedNode) searchList.AddRange(lookedNode.GetChildren()); if (lookedObject is Shooter shooter) { var projectile = shooter._projectile.Instantiate(); searchList.Add(projectile); } foreach (var property in lookedObject.GetPropertyList()) { if ((Variant.Type)property["type"].AsInt32() == Variant.Type.Object) { if (lookedObject.Get(property["name"].AsString()).AsGodotObject() is Effect effect) { searchList.Add(effect); } } } foreach (var key in placeholderDictionary.Keys) { string request = key.Split('|')[0]; var namePropertyPair = request.Split('.'); Variant property; if (namePropertyPair.Length == 2) { if ((namePropertyPair[0] == "?" && lookedObject != searchScene) || (namePropertyPair[0] != "?" && lookedObject is Node node && node.Name != namePropertyPair[0])) { continue; } property = lookedObject.Get(namePropertyPair[1]); } else { property = lookedObject.Get(namePropertyPair[0]); } if (property.VariantType == Variant.Type.Nil) { continue; } float value = property.As(); value = float.Round(value, 3); placeholderDictionary[key] = value; } } // Apply any modifiers foreach (var key in placeholderDictionary.Keys) { if (key.Split('|').Length < 2) continue; string[] modifiers = key.Split('|')[1..]; float value = placeholderDictionary[key]; for (int i = 0; i < modifiers.Length; i++) { if (modifiers[i] != "") { switch (modifiers[i][0]) { case '%': value *= 100; break; case '*': if (placeholderDictionary.ContainsKey(modifiers[i][1..])) { value *= placeholderDictionary[modifiers[i][1..]]; } else if (float.TryParse(modifiers[i][1..], out float mult)) { value *= mult; } break; case '/': if (placeholderDictionary.ContainsKey(modifiers[i][1..])) { value /= placeholderDictionary[modifiers[i][1..]]; } else if (float.TryParse(modifiers[i][1..], out float div)) { value /= div; } break; case '+': if (float.TryParse(modifiers[i][1..], out float add)) { value += add; } break; case '-': if(float.TryParse(modifiers[i][1..], out float sub)) { value -= sub; } break; } } } placeholderDictionary[key] = value; } } private static string ReplaceTextUsingDict(Dictionary dictionary, string text) { var resStr = text; foreach (var key in dictionary.Keys) { resStr = resStr.Replace('{' + key + '}', dictionary[key].ToString()); } return resStr; } }