public BehaviorTree ReadData(IEnumerable <string> paths) { var cancelledLines = new List <string>(); var removedBehaviors = new List <string>(); var newBehaviors = new Dictionary <string, Behavior>(); foreach (var path in paths) { var file = new FileData { FileName = path, RawLines = new List <string>(), OriginalLines = new List <string>(), OriginalLineNumbers = new List <int>() }; int originalLineNumber = 0; try { using (var aiConfig = File.OpenText(path)) { while (!aiConfig.EndOfStream) { file.OriginalLineNumbers.Add(originalLineNumber); var line = aiConfig.ReadLine(); var rawLine = line; originalLineNumber++; while (line != null && line.EndsWith(@"\\") && !aiConfig.EndOfStream) { line = line.Substring(0, line.Length - 2); var newLine = aiConfig.ReadLine(); line += newLine; rawLine += "\n" + newLine; originalLineNumber++; } file.RawLines.Add(rawLine); } } files.Add(file); } catch (System.IO.IOException) { // Ignore } } foreach (var file in files) { foreach (var rawLine in file.RawLines) { if (rawLine.StartsWith("-")) { cancelledLines.Add(rawLine.Substring(1)); } } } string section = ""; for (fileIndex = 0; fileIndex < files.Count; fileIndex++) { var file = files[fileIndex]; for (lineIndex = 0; lineIndex < file.RawLines.Count; lineIndex++) { var rawLine = file.RawLines[lineIndex]; var line = rawLine; file.OriginalLines.Add(rawLine); if (line.StartsWith("-")) { continue; } if (line.StartsWith("+")) { line = line.Substring(1); } if (cancelledLines.Contains(line)) { continue; } lineTokens = LexConfig(line).ToArray(); currentTokenIndex = 0; if (lineTokens.Length == 0) { continue; } if (CurrentToken == "[") { section = string.Join("", lineTokens.Select(t => t.Text)); continue; } string property = CurrentToken.ToLowerInvariant(); Behavior node; switch (property) { case "behaviors": if (!String.Equals(section, "[XComGame.X2AIBTBehaviorTree]", StringComparison.InvariantCultureIgnoreCase)) { continue; } EatToken("behaviors"); EatToken("="); node = ParseBehavior(); node.RawText = rawLine; node.FileName = file.FileName; node.OriginalLineNumber = file.OriginalLineNumbers[file.OriginalLines.Count - 1]; file.OriginalLines[file.OriginalLines.Count - 1] = string.Format("%[{0}]", node.BehaviorName); if (node.BehaviorName != null) { BT[node.Key] = node; } break; case "newbehaviors": if (!String.Equals(section, "[LW_Overhaul.UIScreenListener_Shell]", StringComparison.InvariantCultureIgnoreCase)) { continue; } EatToken("newbehaviors"); EatToken("="); node = ParseBehavior(); node.RawText = rawLine; node.FileName = file.FileName; node.OriginalLineNumber = file.OriginalLineNumbers[file.OriginalLines.Count - 1]; file.OriginalLines[file.OriginalLines.Count - 1] = string.Format("%[{0}]", node.BehaviorName); if (node.BehaviorName != null) { newBehaviors[node.Key] = node; } break; case "behaviorremovals": if (!String.Equals(section, "[LW_Overhaul.UIScreenListener_Shell]", StringComparison.InvariantCultureIgnoreCase)) { continue; } EatToken("behaviorremovals"); EatToken("="); removedBehaviors.Add(CurrentToken); EatToken(); break; default: continue; } } } foreach (var behaviorName in removedBehaviors) { BT.Remove(behaviorName); } foreach (var newBehavior in newBehaviors) { BT[newBehavior.Key] = newBehavior.Value; } return(new BehaviorTree(BT)); }
private Behavior ParseBehavior() { var node = new Behavior(); EatToken("("); while (currentTokenIndex < lineTokens.Length) { int index; switch (CurrentToken.ToLowerInvariant()) { case "behaviorname": EatToken(); EatToken("="); node.BehaviorName = CurrentToken; EatToken(); break; case "nodetype": EatToken(); EatToken("="); node.NodeType = CurrentToken; EatToken(); break; case "child": EatToken(); EatToken("["); index = int.Parse(CurrentToken); EatToken(); while (node.Child.Count < index + 1) { node.Child.Add(""); } EatToken("]"); EatToken("="); node.Child[index] = CurrentToken; EatToken(); break; case "param": EatToken(); EatToken("["); index = int.Parse(CurrentToken); EatToken(); while (node.Param.Count < index + 1) { node.Param.Add(""); } EatToken("]"); EatToken("="); node.Param[index] = CurrentToken; EatToken(); break; case "intent": EatToken(); EatToken("="); EatToken(); break; default: // Unexpected token! ParseError("field name"); EatToken(); while (currentTokenIndex < lineTokens.Length && CurrentToken != "," && CurrentToken != ")") { EatToken(); } break; } if (CurrentToken == ")") { EatToken(); break; } EatToken(",", ")"); // Allow an optional "," before the closing ")" if (CurrentToken == ")") { EatToken(); break; } } return(node); }