/// <summary> /// Read mod luaAI from LuaAI.lua /// </summary> public static void ReadLuaAI(string filePath, ref Mod modInfo) { if (!File.Exists(filePath)) { return; } using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset = 0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config, 0, allText, filePath, out offset); List <Ai> modAis = new List <Ai>(); foreach (var kvp in table) { String name = ""; String desc = ""; foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { var value = (kvp2.Value as String); switch (kvp2.Key) { case "name": name = value; break; case "desc": desc = value; break; } } if (name != "" && desc != "") { var bot = new Ai() { Info = new AiInfoPair[2] { new AiInfoPair { Key = "shortName", Value = name }, //usually equivalent to AI folder name (aiName[i]) new AiInfoPair { Key = "description", Value = desc }, } }; modAis.Add(bot); } } modInfo.ModAis = modAis.ToArray(); } }
/// <summary> /// Get AI description from AIInfo.lua /// </summary> public static Ai GetAIInfo(string filePath) { if (!File.Exists(filePath)) { return(null); } var aiInfoList = new List <AiInfoPair>(); using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset = 0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config, 0, allText, filePath, out offset); foreach (var kvp in table) { String key = ""; String valueIn = ""; String desc = ""; var aiInfoOne = new AiInfoPair(); foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { var value = (kvp2.Value as String); switch (kvp2.Key) { case "key": key = value; break; case "value": valueIn = value; break; case "desc": desc = value; break; } } if (key != "" && valueIn != "") { aiInfoOne.Key = key; aiInfoOne.Value = valueIn; aiInfoOne.Description = desc; aiInfoList.Add(aiInfoOne); } } } return(new Ai() { Info = aiInfoList.ToArray() }); }
/// <summary> /// Tbis function convert the content of a table inside an input text into a Dictionary(String,Object) object. /// The parsing start from the first bracket '{' and end at the closing bracket '}' /// The search for bracket pairs "{}" start from argument "startIndex". /// The function will output the index of closing bracket '}' as variable "offset" when it finishes. /// The value in Dictionary(String,Object) will be another Dictionary(String,Object) when its a nexted table, or String when its normal value. /// Note: This reader don't parse function and return value, and dont pre-calculate any math statement embedded in LUA table (will fail). /// Example usage is in SkirmishControlTool.cs. Any improvement & simplification of this function is welcomed! /// Currently able to extract content of Spring related LUA config files (including able to handle commented line) & Spring Startscript (use ';' as content saperator) /// </summary> public static Dictionary <String, Object> ParseTable(TableReaderConfig config, int startIndex, String text, String filePath, out int offset) { var contentList = new Dictionary <String, Object>(); String prefix = config.prefix; String stringGlue = config.stringGlue; int stringCharType = 0; char[] stringChars = config.stringChars; bool blockStringChar = false; int blockStringCount = 0; String blockStringOpen = config.blockStringOpen; String blockStringClose = config.blockStringClose; bool blockStringString = false; int blockCommentCount = 0; String blockCommentOpen = config.blockCommentOpen; String blockCommentClose = config.blockCommentClose; bool blockComment = false; int commentCharCount = 0; String commentString = config.commentString; bool lineComment = false; bool inTable = false; char tableOpen = config.tableOpen; char tableClose = config.tableClose; char contentSeparator = config.contentSeparator; int contentIndex = 0; char[] newLineChar = config.newLineChar; char whitespaceA = config.whitespaceA; char whitespaceB = config.whitespaceB; String capturedValue1 = ""; String capturedValue2 = ""; Object capturedObject1 = null; char escapeCharSign = config.escapeCharSign; bool isEscapeCharNow = false; bool detectedUnspacedChar = false; bool detectedEqualSign = false; char equalSign = config.equalSign; int i = startIndex; while (i < text.Length) { //string block, [[ ]] " ' if (!lineComment && !blockComment) { if (blockStringString || blockStringChar) { //escape char for displaying " and ' char in string area if (text[i] == escapeCharSign) { if (!isEscapeCharNow) { blockStringCount = 0; isEscapeCharNow = true; i++; continue; } isEscapeCharNow = false; } } if (!isEscapeCharNow && !blockStringChar) { if (blockStringString) { if (text[i] == blockStringClose[blockStringCount]) { blockStringCount++; if (blockStringCount == blockStringClose.Length) { blockStringString = false; blockStringCount = 0; UndoCaptureThisChar(blockStringClose[0], detectedEqualSign, ref capturedValue1, ref capturedValue2); i++; continue; } } else { blockStringCount = 0; } } else { if (text[i] == blockStringOpen[blockStringCount]) { blockStringCount++; if (blockStringCount == blockStringOpen.Length) { blockStringString = true; blockStringCount = 0; UndoCaptureThisChar(blockStringOpen[0], detectedEqualSign, ref capturedValue1, ref capturedValue2); i++; continue; } } else { blockStringCount = 0; } } } if (!isEscapeCharNow && !blockStringString) { if (blockStringChar) { if (text[i] == stringChars[stringCharType]) { blockStringChar = false; i++; continue; } } else { if (text[i] == stringChars[0]) { blockStringChar = true; stringCharType = 0; i++; continue; } else if (text[i] == stringChars[1]) { blockStringChar = true; stringCharType = 1; i++; continue; } } } if (blockStringString || blockStringChar) { char newChar = text[i]; if (isEscapeCharNow && text[i] == 'n') //newline { newChar = '\n'; } isEscapeCharNow = false; CaptureChar(newChar, detectedEqualSign, ref capturedValue1, ref capturedValue2); i++; continue; } } //connector between string value, "..." if (!detectedUnspacedChar && text[i] == stringGlue[0]) { i++; continue; } //Whitespace if (text[i] == whitespaceA || text[i] == whitespaceB) { detectedUnspacedChar = false; i++; continue; } //Newline if (text[i] == newLineChar[0] || text[i] == newLineChar[1]) { lineComment = false; i++; continue; } //Block comment if (!blockComment) { if (text[i] == blockCommentOpen[blockCommentCount]) { blockCommentCount++; if (blockCommentCount == blockCommentOpen.Length) { blockComment = true; blockCommentCount = 0; i++; continue; } } else { blockCommentCount = 0; } } else { if (text[i] == blockCommentClose[blockCommentCount]) { blockCommentCount++; if (blockCommentCount == blockCommentClose.Length) { blockComment = false; blockCommentCount = 0; i++; continue; } } else { blockCommentCount = 0; } i++; continue; } //Line comment, -- if (!lineComment) { if (text[i] == commentString[commentCharCount]) { commentCharCount++; if (commentCharCount == commentString.Length) { lineComment = true; commentCharCount = 0; UndoCaptureThisChar(commentString[0], detectedEqualSign, ref capturedValue1, ref capturedValue2); i++; continue; } } else { commentCharCount = 0; } } else { i++; continue; } //{ and } if (!inTable && text[i] == tableOpen) { inTable = true; i++; continue; } else if (text[i] == tableOpen) { int offsetIn = 0; var list = ParseTable(config, i, text, filePath, out offsetIn); capturedObject1 = list; bool saved = SaveKeyValuePair(prefix, contentIndex, capturedValue1, capturedValue2, capturedObject1, filePath, detectedEqualSign, ref contentList); capturedValue1 = ""; capturedValue2 = ""; capturedObject1 = null; detectedEqualSign = false; if (saved) { contentIndex++; } i = i + offsetIn; continue; } else if (text[i] == tableClose) { SaveKeyValuePair(prefix, contentIndex, capturedValue1, capturedValue2, capturedObject1, filePath, detectedEqualSign, ref contentList); inTable = false; offset = (i - startIndex) + 1; //is out return(contentList); } if (!inTable) { i++; continue; } //content separator, "," if (text[i] == contentSeparator) { bool saved = SaveKeyValuePair(prefix, contentIndex, capturedValue1, capturedValue2, capturedObject1, filePath, detectedEqualSign, ref contentList); capturedValue1 = ""; capturedValue2 = ""; capturedObject1 = null; detectedEqualSign = false; if (saved) { contentIndex++; } i++; continue; } //key value separator, = if (text[i] == equalSign) { detectedEqualSign = true; i++; continue; } detectedUnspacedChar = true; CaptureChar(text[i], detectedEqualSign, ref capturedValue1, ref capturedValue2); i++; } offset = text.Length; return(contentList); }
void ReadReplayInfo(int index) { if (listBoxDemoList.Items.Count == 0 || index >= listBoxDemoList.Items.Count) { return; } ReplayListItem replayItem = (ReplayListItem)listBoxDemoList.Items[index]; if (replayItem.haveBeenUpdated) { return; } string pathOfFiles = replayItem.filePath; int firstSeparator = replayItem.fileName.IndexOf('_'); var demoDate = replayItem.fileName.Substring(0, firstSeparator + 1); if (demoDate.Length > 0) { int year = 0; int.TryParse(demoDate.Substring(0, 4), NumberStyles.Integer, CultureInfo.InvariantCulture, out year); int month = 0; int.TryParse(demoDate.Substring(4, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out month); int day = 0; int.TryParse(demoDate.Substring(6, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out day); int secondSeparator = replayItem.fileName.IndexOf('_', firstSeparator + 1); var demoTime = replayItem.fileName.Substring(firstSeparator + 1, secondSeparator + 1); int hour = 0; int.TryParse(demoTime.Substring(0, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out hour); int minute = 0; int.TryParse(demoTime.Substring(2, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out minute); int second = 0; int.TryParse(demoTime.Substring(4, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out second); replayItem.dateTime = new DateTime(year, month, day, hour, minute, second); } try{ using (FileStream fileStream = File.OpenRead(pathOfFiles)) using (var stream = new StreamReader(fileStream)) { replayItem.replaySize = (int)(fileStream.Length / 1024); String text = ""; string firstLine = stream.ReadLine(); String tmpText = ""; int openBracketCount = 0; bool inBracket = false; while ((openBracketCount > 0 || !inBracket) && !stream.EndOfStream) { tmpText = stream.ReadLine(); if (tmpText == null) { break; } if (tmpText.Length > 150) //skip, avoid waste time parsing it { continue; } text = text + tmpText; if (tmpText.StartsWith("{")) { inBracket = true; openBracketCount++; } else if (tmpText.StartsWith("}")) { openBracketCount--; } } if (text == "") { replayItem.crash = false; replayItem.haveBeenUpdated = true; return; } const char nullChar = '\0'; const char whiteSpace = ' '; string engineName = ""; int i = 24; while (i < firstLine.Length) { if (firstLine[i] == nullChar || firstLine[i] == whiteSpace) { break; } engineName = engineName + firstLine[i]; i++; } if (!engineName.Contains('.')) { engineName = engineName + ".0"; } replayItem.engine = engineName; int offset = 0; var config = new TableReaderConfig { contentSeparator = ';' }; var table = TableReader.ParseTable(config, 0, text, pathOfFiles, out offset); String gameName = ""; String hostName = ""; String mapName = ""; var allyPlayerCount = new int[32]; replayItem.players.Clear(); int totalElo = 0; int totalRank = 0; int eloCount = 0; int rankCount = 0; int aiCount = 0; foreach (var kvp in table) { //System.Diagnostics.Trace.TraceInformation("KEY: " + kvp.Key + " Value:" + (kvp.Value as String)); if (kvp.Key == "gametype") { gameName = (kvp.Value as String); } else if (kvp.Key == "mapname") { mapName = (kvp.Value as String); } else if (kvp.Key.StartsWith("ai")) { aiCount++; string name = ""; foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { switch (kvp2.Key) { case "shortname": name = (kvp2.Value as String); break; } } if (name != "") { replayItem.ais.Add(name); } } else if (kvp.Key == "myplayername") { hostName = (kvp.Value as String); } else if (kvp.Key.StartsWith("team")) { foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { if (kvp2.Key == "allyteam") { int numbers = 0; int.TryParse((kvp2.Value as String), NumberStyles.Integer, CultureInfo.InvariantCulture, out numbers); allyPlayerCount[numbers]++; break; } } } else if (kvp.Key.StartsWith("player")) { int eloNumbers = -1; int rankNumbers = -1; string name = ""; bool isSpectator = false; foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { switch (kvp2.Key) { case "name": name = (kvp2.Value as String); break; case "elo": int.TryParse((kvp2.Value as String), NumberStyles.Integer, CultureInfo.InvariantCulture, out eloNumbers); break; case "rank": int.TryParse((kvp2.Value as String), NumberStyles.Integer, CultureInfo.InvariantCulture, out rankNumbers); break; case "spectator": int numbers = 0; int.TryParse((kvp2.Value as String), NumberStyles.Integer, CultureInfo.InvariantCulture, out numbers); isSpectator = (numbers > 0); break; } } if (!isSpectator) { if (rankNumbers > -1) { rankCount++; totalRank = totalRank + rankNumbers; } if (eloNumbers > -1) { eloCount++; totalElo = totalElo + eloNumbers; } replayItem.players.Add(name); } } } String versusCount = ""; bool firstNumberEntered = false; for (int j = 0; j < allyPlayerCount.Length; j++) { if (allyPlayerCount[j] > 0) { if (!firstNumberEntered) { firstNumberEntered = true; versusCount = allyPlayerCount[j].ToString(); } else { versusCount = versusCount + "v" + allyPlayerCount[j]; } } } if (rankCount == 0) { rankCount = -1; //avoid div by 0 } if (eloCount == 0) { eloCount = -1; } //reference: http://www.dotnetperls.com/string-format //var formattedText = String.Format("Host:{0,-14} " + (versusCount!=""?"Balance:{1,-6} ":"") + "Map:{2,-23} " + (eloCount>0?"Average elo:{3,-5} ":"") + (rankCount>0?"Average rank:{4,-3}":"") + (aiCount>0?"have {5,-3} AI ":"") + "Game:{6,-10}", hostName, versusCount, mapName, totalElo/eloCount, totalRank/rankCount,aiCount,gameName); replayItem.aiCount = aiCount; replayItem.averageElo = totalElo / eloCount; replayItem.averageRank = totalRank / rankCount; replayItem.mapName = mapName; replayItem.gameName = gameName; replayItem.balance = versusCount; replayItem.hostName = hostName; } replayItem.crash = false; replayItem.haveBeenUpdated = true; }catch (Exception e) { replayItem.crash = true; replayItem.haveBeenUpdated = false; Trace.TraceError("LocalReplay info reader error: {0}", e); } }
/// <summary> /// Tbis function convert the content of a table inside an input text into a Dictionary(String,Object) object. /// The parsing start from the first bracket '{' and end at the closing bracket '}' /// The search for bracket pairs "{}" start from argument "startIndex". /// The function will output the index of closing bracket '}' as variable "offset" when it finishes. /// The value in Dictionary(String,Object) will be another Dictionary(String,Object) when its a nexted table, or String when its normal value. /// Note: This reader don't parse function and return value, and dont pre-calculate any math statement embedded in LUA table (will fail). /// Example usage is in SkirmishControlTool.cs. Any improvement & simplification of this function is welcomed! /// Currently able to extract content of Spring related LUA config files (including able to handle commented line) & Spring Startscript (use ';' as content saperator) /// </summary> public static Dictionary<String,Object> ParseTable(TableReaderConfig config, int startIndex, String text, String filePath, out int offset) { var contentList =new Dictionary<String,Object>(); String prefix= config.prefix; String stringGlue = config.stringGlue; int stringCharType = 0; char[] stringChars = config.stringChars; bool blockStringChar = false; int blockStringCount = 0; String blockStringOpen = config.blockStringOpen; String blockStringClose = config.blockStringClose; bool blockStringString = false; int blockCommentCount = 0; String blockCommentOpen = config.blockCommentOpen; String blockCommentClose = config.blockCommentClose; bool blockComment = false; int commentCharCount = 0; String commentString = config.commentString; bool lineComment = false; bool inTable = false; char tableOpen = config.tableOpen; char tableClose = config.tableClose; char contentSeparator = config.contentSeparator; int contentIndex = 0; char[] newLineChar = config.newLineChar; char whitespaceA = config.whitespaceA; char whitespaceB = config.whitespaceB; String capturedValue1 = ""; String capturedValue2 = ""; Object capturedObject1 = null; char escapeCharSign = config.escapeCharSign; bool isEscapeCharNow = false; bool detectedUnspacedChar = false; bool capture2isByStringChar = false; bool detectedEqualSign = false; char equalSign = config.equalSign; int i=startIndex; while(i<text.Length) { //string block, [[ ]] " ' if (!lineComment && !blockComment) { if (blockStringString || blockStringChar) { //escape char for displaying " and ' char in string area if(text[i]==escapeCharSign) { if (!isEscapeCharNow) { blockStringCount = 0; isEscapeCharNow=true; i++; continue; } isEscapeCharNow=false; } } if (!isEscapeCharNow && !blockStringChar) { if (blockStringString) { if (text[i]==blockStringClose[blockStringCount]) { blockStringCount++; if (blockStringCount==blockStringClose.Length) { blockStringString=false; blockStringCount=0; UndoCaptureThisChar(blockStringClose[0],detectedEqualSign,ref capturedValue1,ref capturedValue2); i++; continue; } }else blockStringCount=0; }else { if (text[i]==blockStringOpen[blockStringCount]) { blockStringCount++; if (blockStringCount==blockStringOpen.Length) { blockStringString=true; blockStringCount=0; UndoCaptureThisChar(blockStringOpen[0],detectedEqualSign,ref capturedValue1,ref capturedValue2); i++; continue; } }else blockStringCount=0; } } if (!isEscapeCharNow && !blockStringString) { if(blockStringChar) { if (text[i]==stringChars[stringCharType]) { blockStringChar=false; i++; continue; } }else { if (text[i]==stringChars[0]) { blockStringChar=true; stringCharType = 0; i++; continue; }else if (text[i]==stringChars[1]) { blockStringChar=true; stringCharType = 1; i++; continue; } } } if (blockStringString || blockStringChar) { char newChar = text[i]; if (detectedEqualSign) { if(!capture2isByStringChar) { capturedValue2=""; capture2isByStringChar=true; } } if (isEscapeCharNow && text[i]=='n') //newline newChar = '\n'; isEscapeCharNow = false; CaptureChar(newChar,detectedEqualSign,ref capturedValue1,ref capturedValue2); i++; continue; } } //connector between string value, "..." if (!detectedUnspacedChar && text[i]==stringGlue[0]) { i++; continue; } //Whitespace if (text[i]==whitespaceA || text[i]==whitespaceB) { detectedUnspacedChar = false; //i++; //continue; } //Newline if (text[i]==newLineChar[0] || text[i]==newLineChar[1]) { lineComment = false; i++; continue; } //Block comment if (!blockComment) { if (text[i]==blockCommentOpen[blockCommentCount]) { blockCommentCount++; if (blockCommentCount==blockCommentOpen.Length) { blockComment=true; blockCommentCount=0; i++; continue; } }else blockCommentCount=0; }else { if (text[i]==blockCommentClose[blockCommentCount]) { blockCommentCount++; if (blockCommentCount==blockCommentClose.Length) { blockComment=false; blockCommentCount=0; i++; continue; } }else blockCommentCount=0; i++; continue; } //Line comment, -- if(!lineComment) { if (text[i]==commentString[commentCharCount]) { commentCharCount++; if (commentCharCount==commentString.Length) { lineComment=true; commentCharCount=0; UndoCaptureThisChar(commentString[0],detectedEqualSign,ref capturedValue1,ref capturedValue2); i++; continue; } }else commentCharCount=0; }else { i++; continue; } //{ and } if (!inTable && text[i]==tableOpen) { inTable = true; i++; continue; } else if (text[i]==tableOpen) { int offsetIn = 0; var list = ParseTable(config,i,text,filePath,out offsetIn); capturedObject1=list; bool saved = SaveKeyValuePair(prefix,contentIndex,capturedValue1,capturedValue2,capturedObject1,capture2isByStringChar,filePath,detectedEqualSign,ref contentList); capturedValue1 = ""; capturedValue2 = ""; capturedObject1 = null; detectedEqualSign = false; capture2isByStringChar=false; if (saved) contentIndex++; i = i+offsetIn; continue; } else if (text[i]==tableClose) { SaveKeyValuePair(prefix,contentIndex,capturedValue1,capturedValue2,capturedObject1,capture2isByStringChar,filePath,detectedEqualSign,ref contentList); inTable = false; offset = (i-startIndex)+1; //is out return contentList; } if (!inTable) { i++; continue; } //content separator, "," if (text[i]==contentSeparator) { bool saved = SaveKeyValuePair(prefix,contentIndex,capturedValue1,capturedValue2,capturedObject1,capture2isByStringChar,filePath,detectedEqualSign,ref contentList); capturedValue1 = ""; capturedValue2 = ""; capturedObject1 = null; detectedEqualSign = false; capture2isByStringChar=false; if (saved) contentIndex++; i++; continue; } //key value separator, = if (text[i]==equalSign) { detectedEqualSign = true; i++; continue; } detectedUnspacedChar = true; CaptureChar(text[i],detectedEqualSign,ref capturedValue1,ref capturedValue2); i++; } offset = text.Length; return contentList; }
void ReadReplayInfo(int index) { if (listBoxDemoList.Items.Count==0 || index>=listBoxDemoList.Items.Count) return; ReplayListItem replayItem = (ReplayListItem)listBoxDemoList.Items[index]; if(replayItem.haveBeenUpdated) return; string pathOfFiles = replayItem.filePath; int firstSeparator = replayItem.fileName.IndexOf('_'); var demoDate = replayItem.fileName.Substring(0,firstSeparator+1); if (demoDate.Length>0) { int year=0; int.TryParse(demoDate.Substring(0,4),NumberStyles.Integer,CultureInfo.InvariantCulture,out year); int month=0; int.TryParse(demoDate.Substring(4,2),NumberStyles.Integer,CultureInfo.InvariantCulture,out month); int day=0; int.TryParse(demoDate.Substring(6,2),NumberStyles.Integer,CultureInfo.InvariantCulture,out day); int secondSeparator = replayItem.fileName.IndexOf('_',firstSeparator+1); var demoTime = replayItem.fileName.Substring(firstSeparator+1,secondSeparator+1); int hour=0; int.TryParse(demoTime.Substring(0,2),NumberStyles.Integer,CultureInfo.InvariantCulture,out hour); int minute=0; int.TryParse(demoTime.Substring(2,2),NumberStyles.Integer,CultureInfo.InvariantCulture,out minute); int second=0; int.TryParse(demoTime.Substring(4,2),NumberStyles.Integer,CultureInfo.InvariantCulture,out second); replayItem.dateTime = new DateTime(year,month,day,hour,minute,second); } try{ using (FileStream fileStream = File.OpenRead(pathOfFiles)) using (var stream = new StreamReader(fileStream)) { replayItem.replaySize = (int)(fileStream.Length/1024); String text = ""; string firstLine = stream.ReadLine(); String tmpText =""; int openBracketCount = 0; bool inBracket = false; while ((openBracketCount>0 || !inBracket) && !stream.EndOfStream) { tmpText = stream.ReadLine(); if (tmpText==null) break; if (tmpText.Length > 150) //skip, avoid waste time parsing it continue; text = text + tmpText; if (tmpText.StartsWith("{")) { inBracket = true; openBracketCount++; } else if (tmpText.StartsWith("}")) openBracketCount--; } if (text=="") { replayItem.crash = false; replayItem.haveBeenUpdated=true; return; } const char nullChar = '\0'; const char whiteSpace = ' '; string engineName = ""; int i=24; while(i<firstLine.Length) { if (firstLine[i] == nullChar || firstLine[i] == whiteSpace) break; engineName = engineName + firstLine[i]; i++; } if(!engineName.Contains('.')) engineName= engineName+".0"; replayItem.engine = engineName; int offset =0; var config = new TableReaderConfig {contentSeparator=';'}; var table = TableReader.ParseTable(config,0,text,pathOfFiles,out offset); String gameName= ""; String hostName= ""; String mapName= ""; var allyPlayerCount= new int[32]; replayItem.players.Clear(); int totalElo = 0; int totalRank = 0; int eloCount = 0; int rankCount = 0; int aiCount = 0; foreach(var kvp in table) { //System.Diagnostics.Trace.TraceInformation("KEY: " + kvp.Key + " Value:" + (kvp.Value as String)); if(kvp.Key=="gametype") { gameName = (kvp.Value as String); } else if (kvp.Key == "mapname") { mapName = (kvp.Value as String); } else if (kvp.Key.StartsWith("ai")) { aiCount++; string name=""; foreach (var kvp2 in (kvp.Value as Dictionary<String,Object>)) { switch(kvp2.Key) { case "shortname": name = (kvp2.Value as String); break; } } if (name!="") { replayItem.ais.Add(name); } } else if (kvp.Key=="myplayername") { hostName = (kvp.Value as String); } else if (kvp.Key.StartsWith("team")) { foreach (var kvp2 in (kvp.Value as Dictionary<String,Object>)) { if (kvp2.Key=="allyteam") { int numbers=0; int.TryParse((kvp2.Value as String),NumberStyles.Integer,CultureInfo.InvariantCulture,out numbers); allyPlayerCount[numbers]++; break; } } } else if (kvp.Key.StartsWith("player")) { int eloNumbers=-1; int rankNumbers=-1; string name=""; bool isSpectator = false; foreach (var kvp2 in (kvp.Value as Dictionary<String,Object>)) { switch(kvp2.Key) { case "name": name = (kvp2.Value as String); break; case "elo": int.TryParse((kvp2.Value as String),NumberStyles.Integer,CultureInfo.InvariantCulture,out eloNumbers); break; case "rank": int.TryParse((kvp2.Value as String),NumberStyles.Integer,CultureInfo.InvariantCulture,out rankNumbers); break; case "spectator": int numbers=0; int.TryParse((kvp2.Value as String),NumberStyles.Integer,CultureInfo.InvariantCulture,out numbers); isSpectator = (numbers>0); break; } } if (!isSpectator) { if (rankNumbers>-1) { rankCount++; totalRank = totalRank + rankNumbers; } if (eloNumbers>-1) { eloCount++; totalElo = totalElo + eloNumbers; } replayItem.players.Add(name); } } } String versusCount = ""; bool firstNumberEntered = false; for (int j=0;j<allyPlayerCount.Length;j++) { if (allyPlayerCount[j]>0) { if (!firstNumberEntered) { firstNumberEntered =true; versusCount = allyPlayerCount[j].ToString(); } else versusCount = versusCount + "v" + allyPlayerCount[j]; } } if (rankCount == 0) rankCount=-1; //avoid div by 0 if (eloCount == 0) eloCount=-1; //reference: http://www.dotnetperls.com/string-format //var formattedText = String.Format("Host:{0,-14} " + (versusCount!=""?"Balance:{1,-6} ":"") + "Map:{2,-23} " + (eloCount>0?"Average elo:{3,-5} ":"") + (rankCount>0?"Average rank:{4,-3}":"") + (aiCount>0?"have {5,-3} AI ":"") + "Game:{6,-10}", hostName, versusCount, mapName, totalElo/eloCount, totalRank/rankCount,aiCount,gameName); replayItem.aiCount = aiCount; replayItem.averageElo = totalElo/eloCount; replayItem.averageRank = totalRank/rankCount; replayItem.mapName = mapName; replayItem.gameName = gameName; replayItem.balance = versusCount; replayItem.hostName = hostName; } replayItem.crash = false; replayItem.haveBeenUpdated=true; }catch(Exception e) { replayItem.crash = true; replayItem.haveBeenUpdated = false; Trace.TraceError("LocalReplay info reader error: {0}",e); } }
/// <summary> /// Read options from EngineOptions.lua or ModOptions.lua /// </summary> public static void ReadOptionsTable(String filePath, ref Mod modInfo) { if (!File.Exists(filePath)) { return; } var allOptions = new List<Option>(); using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset =0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config,0,allText,filePath,out offset); foreach (var kvp in table) { var anOption = new Option(); bool isBoolOption = false; foreach(var kvp2 in (kvp.Value as Dictionary<String,Object>)) { var value = (kvp2.Value as String); float numbers; //uncomment to take a peek on what it read!: //System.Diagnostics.Trace.TraceWarning("key: " + kvp2.Key + " value:" + value); switch(kvp2.Key) { case "key": anOption.Key = value; break; case "name": anOption.Name = value; break; case "desc": anOption.Description = value; break; case "type": switch(value) { case "bool": anOption.Type = OptionType.Bool; isBoolOption = true; break; case "list": anOption.Type = OptionType.List; break; case "number": anOption.Type = OptionType.Number; break; case "string": anOption.Type = OptionType.String; break; case "section": anOption.Type = OptionType.Section; continue; default: anOption.Type = OptionType.Undefined; break; } break; case "def": anOption.Default = value; if (isBoolOption) { if (value=="false") anOption.Default = "0"; else anOption.Default = "1"; } break; case "min": float.TryParse(value,NumberStyles.Float,CultureInfo.InvariantCulture,out numbers); anOption.Min = numbers; break; case "max": float.TryParse(value,NumberStyles.Float,CultureInfo.InvariantCulture,out numbers); anOption.Max = numbers; break; case "step": float.TryParse(value,NumberStyles.Float,CultureInfo.InvariantCulture,out numbers); anOption.Step = numbers; break; case "maxlen": float.TryParse(value,NumberStyles.Float,CultureInfo.InvariantCulture,out numbers); anOption.StrMaxLen = numbers; break; case "items": var listOptions = new List<ListOption>(); foreach(var kvp3 in (kvp2.Value as Dictionary<String,Object>)) { var listOption = new ListOption(); foreach(var kvp4 in (kvp3.Value as Dictionary<String,Object>)) { var value2 = (kvp4.Value as String); switch(kvp4.Key) { case "key": listOption.Key = value2; break; case "name": listOption.Name = value2; break; case "desc": listOption.Description = value2; break; } } if (listOption.Key!=null) listOptions.Add(listOption); } anOption.ListOptions = listOptions; break; case "scope": anOption.Scope = value; break; case "section": anOption.Section = value; break; } } if (anOption.Key!=null) allOptions.Add(anOption); } } if (modInfo.Options!=null) modInfo.Options = modInfo.Options.ToList().Concat(allOptions).ToArray(); else modInfo.Options = allOptions.ToArray(); }
/// <summary> /// Read mod information from modInfo.lua /// </summary> public static void ParseModInfo(string filePath, ref Mod modInfo) { if (!File.Exists(filePath)) { return; } using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset =0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config,0,allText,filePath,out offset); foreach (var kvp in table) { var value = (kvp.Value as String); switch(kvp.Key) { case "name": modInfo.Name = value; break; case "description": modInfo.Description = value; break; case "shortname": modInfo.ShortName = value; break; case "version": modInfo.PrimaryModVersion = value; break; case "mutator": modInfo.Mutator = value; break; case "game": modInfo.Game = value; break; case "shortGame": modInfo.ShortGame = value; break; case "modtype": //TODO modtype?? break; case "depend": var listDepend = new List<string>(); foreach (var kvp2 in (kvp.Value as Dictionary<String,Object>)) { var value2 = (kvp2.Value as String); listDepend.Add(value2); } modInfo.Dependencies = listDepend; break; } } } }
/// <summary> /// Read mod luaAI from LuaAI.lua /// </summary> public static void ReadLuaAI(string filePath, ref Mod modInfo) { if (!File.Exists(filePath)) { return; } using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset =0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config,0,allText,filePath,out offset); List<Ai> modAis = new List<Ai>(); foreach (var kvp in table) { String name = ""; String desc = ""; foreach (var kvp2 in (kvp.Value as Dictionary<String,Object>)) { var value = (kvp2.Value as String); switch(kvp2.Key) { case "name": name = value; break; case "desc": desc = value; break; } } if (name!="" && desc!="") { var bot = new Ai() { Info = new AiInfoPair[2] { new AiInfoPair { Key = "shortName", Value = name } , //usually equivalent to AI folder name (aiName[i]) new AiInfoPair { Key = "description", Value = desc } , } }; modAis.Add(bot); } } modInfo.ModAis = modAis.ToArray(); } }
/// <summary> /// Get AI description from AIInfo.lua /// </summary> public static Ai GetAIInfo(string filePath) { if (!File.Exists(filePath)) { return null; } var aiInfoList = new List<AiInfoPair>(); using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset =0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config,0,allText,filePath,out offset); foreach (var kvp in table) { String key=""; String valueIn=""; String desc=""; var aiInfoOne = new AiInfoPair(); foreach (var kvp2 in (kvp.Value as Dictionary<String,Object>)) { var value = (kvp2.Value as String); switch(kvp2.Key) { case "key": key = value; break; case "value": valueIn= value; break; case "desc": desc = value; break; } } if (key!="" && valueIn!="") { aiInfoOne.Key = key; aiInfoOne.Value = valueIn; aiInfoOne.Description = desc; aiInfoList.Add(aiInfoOne); } } } return new Ai(){ Info= aiInfoList.ToArray() }; }
/// <summary> /// Read mission.lua file. /// </summary> public static void ReadMissionSlot(string filePath, ref Mod modInfo) { if (!File.Exists(filePath)) { return; } using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset =0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config,0,allText,filePath,out offset); var allSlots = new List<MissionSlot>(); foreach (var kvp in table) { var slot = new MissionSlot(); int numbers = 0; foreach (var kvp2 in (kvp.Value as Dictionary<String,Object>)) { var value = (kvp2.Value as String); switch(kvp2.Key) { case "AllyID": int.TryParse(value,NumberStyles.Integer,CultureInfo.InvariantCulture,out numbers); slot.AllyID = numbers; break; case "AllyName": slot.AllyName = value; break; case "IsHuman": slot.IsHuman = (value=="true"); break; case "IsRequired": slot.IsRequired = (value =="true"); break; case "TeamID": int.TryParse(value,NumberStyles.Integer,CultureInfo.InvariantCulture,out numbers); slot.TeamID = numbers; break; case "TeamName": slot.TeamName = value; break; case "Color": int.TryParse(value,NumberStyles.Integer,CultureInfo.InvariantCulture,out numbers); slot.Color = numbers; //var springColor = (MyCol)numbers; //slot.ColorR = springColor.R; //slot.ColorG = springColor.G; //slot.ColorB = springColor.B; break; //case "ColorR": // break; //case "ColorG": // break; //case "ColorB": // break; case "AiShortName": slot.AiShortName = value; break; case "AiVersion": slot.AiVersion = value; break; } } if (slot.AiShortName!=null) { allSlots.Add(slot); } } modInfo.MissionSlots = allSlots; } }
/// <summary> /// Parse sides name from gamedata/sidedata.lua and side icon (.bmp format with same name as side name) from sidepics/ /// </summary> public static void ReadSideInfo(string sidedataluaPath, string picPath, ref Mod modInfo) { if (!File.Exists(sidedataluaPath)) { modInfo.Sides = new string[0]; //modInfo.SideIcons = (new List<Byte[]>()).ToArray(); //modInfo.StartUnits = new PlasmaShared.SerializableDictionary<string, string>(new Dictionary<string,string>()); return; } using (FileStream fileStream = File.OpenRead(sidedataluaPath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset =0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config,0,allText,sidedataluaPath,out offset); List<String> sides = new List<String>(); List<byte[]> sideIcons = new List<byte[]>(); var startUnits = new Dictionary<string,string>(); //PlasmaShared.SerializableDictionary<string,string>(); foreach (var kvp in table) { String name = ""; String startunit = ""; foreach (var kvp2 in (kvp.Value as Dictionary<String,Object>)) { var value = (kvp2.Value as String); switch(kvp2.Key) { case "name": name = value; break; case "startunit": startunit = value; break; } } if (name!="") { var picBytes = new Byte[0]; try{ var picList = Directory.EnumerateFiles(picPath); using(FileStream fileStream2 = File.OpenRead(picList.First(x => SkirmishControlTool.GetFolderOrFileName(x).StartsWith(name,StringComparison.InvariantCultureIgnoreCase)))) { picBytes = new Byte[fileStream2.Length]; fileStream2.Read(picBytes,0,picBytes.Length); } }catch(Exception e) {System.Diagnostics.Trace.TraceError(e.ToString());} sides.Add(name); sideIcons.Add(picBytes); startUnits.Add(name,startunit); } } modInfo.Sides = sides.ToArray(); modInfo.SideIcons = sideIcons.ToArray(); modInfo.StartUnits = new SerializableDictionary<string, string>(startUnits); } }
/// <summary> /// Read options from EngineOptions.lua or ModOptions.lua /// </summary> public static void ReadOptionsTable(String filePath, ref Mod modInfo) { if (!File.Exists(filePath)) { return; } var allOptions = new List <Option>(); using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset = 0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config, 0, allText, filePath, out offset); foreach (var kvp in table) { var anOption = new Option(); bool isBoolOption = false; foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { var value = (kvp2.Value as String); float numbers; //uncomment to take a peek on what it read!: //System.Diagnostics.Trace.TraceWarning("key: " + kvp2.Key + " value:" + value); switch (kvp2.Key) { case "key": anOption.Key = value; break; case "name": anOption.Name = value; break; case "desc": anOption.Description = value; break; case "type": switch (value) { case "bool": anOption.Type = OptionType.Bool; isBoolOption = true; break; case "list": anOption.Type = OptionType.List; break; case "number": anOption.Type = OptionType.Number; break; case "string": anOption.Type = OptionType.String; break; case "section": anOption.Type = OptionType.Section; continue; default: anOption.Type = OptionType.Undefined; break; } break; case "def": anOption.Default = value; if (isBoolOption) { if (value == "false") { anOption.Default = "0"; } else { anOption.Default = "1"; } } break; case "min": float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out numbers); anOption.Min = numbers; break; case "max": float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out numbers); anOption.Max = numbers; break; case "step": float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out numbers); anOption.Step = numbers; break; case "maxlen": float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out numbers); anOption.StrMaxLen = numbers; break; case "items": var listOptions = new List <ListOption>(); foreach (var kvp3 in (kvp2.Value as Dictionary <String, Object>)) { var listOption = new ListOption(); foreach (var kvp4 in (kvp3.Value as Dictionary <String, Object>)) { var value2 = (kvp4.Value as String); switch (kvp4.Key) { case "key": listOption.Key = value2; break; case "name": listOption.Name = value2; break; case "desc": listOption.Description = value2; break; } } if (listOption.Key != null) { listOptions.Add(listOption); } } anOption.ListOptions = listOptions; break; case "scope": anOption.Scope = value; break; case "section": anOption.Section = value; break; } } if (anOption.Key != null) { allOptions.Add(anOption); } } } if (modInfo.Options != null) { modInfo.Options = modInfo.Options.ToList().Concat(allOptions).ToArray(); } else { modInfo.Options = allOptions.ToArray(); } }
/// <summary> /// Read mod information from modInfo.lua /// </summary> public static void ParseModInfo(string filePath, ref Mod modInfo) { if (!File.Exists(filePath)) { return; } using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset = 0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config, 0, allText, filePath, out offset); foreach (var kvp in table) { var value = (kvp.Value as String); switch (kvp.Key) { case "name": modInfo.Name = value; break; case "description": modInfo.Description = value; break; case "shortname": modInfo.ShortName = value; break; case "version": modInfo.PrimaryModVersion = value; break; case "mutator": modInfo.Mutator = value; break; case "game": modInfo.Game = value; break; case "shortGame": modInfo.ShortGame = value; break; case "modtype": //TODO modtype?? break; case "depend": var listDepend = new List <string>(); foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { var value2 = (kvp2.Value as String); listDepend.Add(value2); } modInfo.Dependencies = listDepend; break; } } } }
/// <summary> /// Read mission.lua file. /// </summary> public static void ReadMissionSlot(string filePath, ref Mod modInfo) { if (!File.Exists(filePath)) { return; } using (FileStream fileStream = File.OpenRead(filePath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset = 0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config, 0, allText, filePath, out offset); var allSlots = new List <MissionSlot>(); foreach (var kvp in table) { var slot = new MissionSlot(); int numbers = 0; foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { var value = (kvp2.Value as String); switch (kvp2.Key) { case "AllyID": int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out numbers); slot.AllyID = numbers; break; case "AllyName": slot.AllyName = value; break; case "IsHuman": slot.IsHuman = (value == "true"); break; case "IsRequired": slot.IsRequired = (value == "true"); break; case "TeamID": int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out numbers); slot.TeamID = numbers; break; case "TeamName": slot.TeamName = value; break; case "Color": int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out numbers); slot.Color = numbers; //var springColor = (MyCol)numbers; //slot.ColorR = springColor.R; //slot.ColorG = springColor.G; //slot.ColorB = springColor.B; break; //case "ColorR": // break; //case "ColorG": // break; //case "ColorB": // break; case "AiShortName": slot.AiShortName = value; break; case "AiVersion": slot.AiVersion = value; break; } } if (slot.AiShortName != null) { allSlots.Add(slot); } } modInfo.MissionSlots = allSlots; } }
/// <summary> /// Parse sides name from gamedata/sidedata.lua and side icon (.bmp format with same name as side name) from sidepics/ /// </summary> public static void ReadSideInfo(string sidedataluaPath, string picPath, ref Mod modInfo) { if (!File.Exists(sidedataluaPath)) { modInfo.Sides = new string[0]; //modInfo.SideIcons = (new List<Byte[]>()).ToArray(); //modInfo.StartUnits = new PlasmaShared.SerializableDictionary<string, string>(new Dictionary<string,string>()); return; } using (FileStream fileStream = File.OpenRead(sidedataluaPath)) using (var stream = new StreamReader(fileStream)) { var allText = stream.ReadToEnd(); int offset = 0; var config = new TableReaderConfig(); var table = TableReader.ParseTable(config, 0, allText, sidedataluaPath, out offset); List <String> sides = new List <String>(); List <byte[]> sideIcons = new List <byte[]>(); var startUnits = new Dictionary <string, string>(); //PlasmaShared.SerializableDictionary<string,string>(); foreach (var kvp in table) { String name = ""; String startunit = ""; foreach (var kvp2 in (kvp.Value as Dictionary <String, Object>)) { var value = (kvp2.Value as String); switch (kvp2.Key) { case "name": name = value; break; case "startunit": startunit = value; break; } } if (name != "") { var picBytes = new Byte[0]; try{ var picList = Directory.EnumerateFiles(picPath); using (FileStream fileStream2 = File.OpenRead(picList.First(x => SkirmishControlTool.GetFolderOrFileName(x).StartsWith(name, StringComparison.InvariantCultureIgnoreCase)))) { picBytes = new Byte[fileStream2.Length]; fileStream2.Read(picBytes, 0, picBytes.Length); } }catch (Exception e) { System.Diagnostics.Trace.TraceError(e.ToString()); } sides.Add(name); sideIcons.Add(picBytes); startUnits.Add(name, startunit); } } modInfo.Sides = sides.ToArray(); modInfo.SideIcons = sideIcons.ToArray(); modInfo.StartUnits = new SerializableDictionary <string, string>(startUnits); } }