using System.Linq; using System.Xml.Linq; namespace Barotrauma { abstract class GenericPrefabFile : ContentFile where T : Prefab { protected GenericPrefabFile(ContentPackage contentPackage, ContentPath path) : base(contentPackage, path) { } protected abstract bool MatchesSingular(Identifier identifier); protected abstract bool MatchesPlural(Identifier identifier); protected abstract PrefabCollection Prefabs { get; } protected abstract T CreatePrefab(ContentXElement element); private void LoadFromXElement(ContentXElement parentElement, bool overriding) { Identifier elemName = parentElement.NameAsIdentifier(); var childElements = parentElement.Elements() #if DEBUG .OrderBy(e => Rand.Int(int.MaxValue, Rand.RandSync.Unsynced)).ToArray() #endif ; if (parentElement.IsOverride()) { foreach (var element in childElements) { LoadFromXElement(element, true); } } else if (elemName == "clear") { Prefabs.AddOverrideFile(this); } else if (MatchesSingular(elemName)) { T prefab = CreatePrefab(parentElement); try { Prefabs.Add(prefab, overriding); } catch { //clean up before rethrowing, since some prefab types might lock resources prefab.Dispose(); Prefabs.Remove(prefab); throw; } } else if (MatchesPlural(elemName)) { foreach (var element in childElements) { LoadFromXElement(element, overriding); } } else { DebugConsole.ThrowError($"GenericPrefabFile: Invalid {GetType().Name} element: {parentElement.Name} in {Path}", contentPackage: ContentPackage); } } public override sealed void LoadFile() { XDocument doc = XMLExtensions.TryLoadXml(Path); if (doc == null) { return; } var rootElement = doc.Root.FromPackage(ContentPackage); LoadFromXElement(rootElement, false); } public override sealed void UnloadFile() { Prefabs.RemoveByFile(this); } public sealed override void Sort() { Prefabs.SortAll(); } } }