/// <summary> /// Handles a decorate entry, or throws if it cannot parse it. /// </summary> /// <param name="entry">The decorate base entry. This should have the /// name 'decorate' (case insensitive).</param> /// <param name="archive">The archive to look up definitions from. /// </param> /// <exception cref="Exception">If parsing fails.</exception> public static void HandleDefinitionsOrThrow(IEntry entry, IArchive archive) { DecorateParser parser = new DecorateParser(archive); bool success = parser.Parse(entry); if (!success) { throw new Exception("Unable to parse decorate entries"); } AddDefinitions(parser.Definitions); }
// Constructor internal StateGoto(ActorStructure actor, DecorateParser parser) { string firsttarget = ""; string secondtarget = ""; bool commentreached = false; bool offsetreached = false; string offsetstr = ""; int cindex = 0; // This is a bitch to parse because for some bizarre reason someone thought it // was funny to allow quotes here. Read the whole line and start parsing this manually. string line = parser.ReadLine(); // Skip whitespace while ((cindex < line.Length) && ((line[cindex] == ' ') || (line[cindex] == '\t'))) { cindex++; } // Parse first target while ((cindex < line.Length) && (line[cindex] != ':')) { // When a comment is reached, we're done here if (line[cindex] == '/') { if ((cindex + 1 < line.Length) && ((line[cindex + 1] == '/') || (line[cindex + 1] == '*'))) { commentreached = true; break; } } // Whitespace ends the string if ((line[cindex] == ' ') || (line[cindex] == '\t')) { break; } // + sign indicates offset start if (line[cindex] == '+') { cindex++; offsetreached = true; break; } // Ignore quotes if (line[cindex] != '"') { firsttarget += line[cindex]; } cindex++; } if (!commentreached && !offsetreached) { // Skip whitespace while ((cindex < line.Length) && ((line[cindex] == ' ') || (line[cindex] == '\t'))) { cindex++; } // Parse second target while (cindex < line.Length) { // When a comment is reached, we're done here if (line[cindex] == '/') { if ((cindex + 1 < line.Length) && ((line[cindex + 1] == '/') || (line[cindex + 1] == '*'))) { commentreached = true; break; } } // Whitespace ends the string if ((line[cindex] == ' ') || (line[cindex] == '\t')) { break; } // + sign indicates offset start if (line[cindex] == '+') { cindex++; offsetreached = true; break; } // Ignore quotes and semicolons if ((line[cindex] != '"') && (line[cindex] != ':')) { secondtarget += line[cindex]; } cindex++; } } // Try to find the offset if we still haven't found it yet if (!offsetreached) { // Skip whitespace while ((cindex < line.Length) && ((line[cindex] == ' ') || (line[cindex] == '\t'))) { cindex++; } if ((cindex < line.Length) && (line[cindex] == '+')) { cindex++; offsetreached = true; } } if (offsetreached) { // Parse offset while (cindex < line.Length) { // When a comment is reached, we're done here if (line[cindex] == '/') { if ((cindex + 1 < line.Length) && ((line[cindex + 1] == '/') || (line[cindex + 1] == '*'))) { commentreached = true; break; } } // Whitespace ends the string if ((line[cindex] == ' ') || (line[cindex] == '\t')) { break; } // Ignore quotes and semicolons if ((line[cindex] != '"') && (line[cindex] != ':')) { offsetstr += line[cindex]; } cindex++; } } // We should now have a first target, optionally a second target and optionally a sprite offset // Check if we don't have the class specified if (string.IsNullOrEmpty(secondtarget)) { // First target is the state to go to classname = actor.ClassName; statename = firsttarget.ToLowerInvariant().Trim(); } else { // First target is the base class to use // Second target is the state to go to classname = firsttarget.ToLowerInvariant().Trim(); statename = secondtarget.ToLowerInvariant().Trim(); } if (offsetstr.Length > 0) { int.TryParse(offsetstr, out spriteoffset); } if ((classname == "super") && (actor.BaseClass != null)) { classname = actor.BaseClass.ClassName; } }
public static int Main(string[] args) { DateTime startTime = DateTime.Now; try { // parse command line options List <string> decoratePaths = new List <string>(); List <string> acsFiles = new List <string>(); string otputDecorateFile = "decorate.txt"; string otputAcsFile = "acs.txt"; string libraryName = "DEFAULTLIB"; string mode = "zdoom"; OptionSet options = new OptionSet() { { "a|acs=", "ACS source files.", p => acsFiles.Add(p) }, { "d|decorate=", "Directory with user DECORATE files.", p => decoratePaths.Add(p) }, { "o|acsOut=", "Output ACS file. acs.txt is default.", p => otputAcsFile = p }, { "p|decorateOut=", "Output DECORATE file. decorate.txt is default.", p => otputDecorateFile = p }, { "m|mode=", "Mode (ZDoom or Skulltag), ZDoom is default.", p => mode = p }, { "l|library=", "Name of the ACS library.", p => libraryName = p } }; options.Parse(args); if (decoratePaths.Count == 0) { throw new ArgumentException("No input decorate path specified."); } if (acsFiles.Count == 0) { throw new ArgumentException("No input ACS file specified."); } DecorateParser parser = new DecorateParser(); // add native decorate files string applicationDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "/"; if (mode.Equals("ZDoom", StringComparison.OrdinalIgnoreCase)) { parser.AddFiles(new DirectoryInfo(applicationDirectory + "decorate/zdoom").GetFilesRecursive(), DecorateFileType.Native); } else { parser.AddFiles(new DirectoryInfo(applicationDirectory + "decorate/skulltag").GetFilesRecursive(), DecorateFileType.Native); } // add user decorate files var files = from path in decoratePaths from file in new DirectoryInfo(path).GetFilesRecursive() select file; parser.AddFiles(files, DecorateFileType.User); Console.WriteLine("Parsing DECORATE files..."); // parse the files var actors = parser.GetActors(); // print some stats var localActors = from actor in actors where !actor.IsFromNativeFile select actor; Console.WriteLine("Found " + actors.Count() + " actors (" + localActors.Count() + " user + " + (actors.Count() - localActors.Count()) + " native)"); // add the classId actor to each monster Actor classIdActor = new Actor() { Name = "__classId", Parent = actors.OfName("inventory").First() }; actors = actors.Append(classIdActor); var monsters = from actor in actors where actor.HasFlagEnabled("ISMONSTER") select actor; foreach (var monster in monsters) { monster.StateMachine.InsertStatesBeforeState( new List <State> { new FrameState() { }, new FrameState() { CodePointer = "A_TakeInventory(\"__classId\", 9999)" }, new FrameState() { CodePointer = "A_GiveInventory(\"__classId\", " + monster.ID + ")" } }, monster.StateMachine.Labels["spawn"]); } // generate ACS Console.WriteLine("Generating output ACS..."); using (var textWriter = new StreamWriter(otputAcsFile)) { var writer = new AcsWriter(textWriter, libraryName); writer.WriteCheckActorClass2(actors); writer.WriteGetWeapon(actors); writer.WriteGetCustomProperty(actors); writer.WriteGetWeaponCustomProperty(actors); writer.WriteOriginalContent(File.ReadAllText(acsFiles[0])); } // generate DECORATE Console.WriteLine("Generating output DECORATE..."); using (var textWriter = new StreamWriter(otputDecorateFile)) { var writer = new DecorateWriter(textWriter); writer.WriteActors(actors); } // print time stat TimeSpan timeDelta = DateTime.Now - startTime; Console.WriteLine("Done after " + Math.Round((double)timeDelta.TotalMilliseconds / 1000d, 2) + " seconds!"); return(0); } catch (IOException e) { Console.WriteLine(e.GetType().Name + ": " + e.Message); Console.WriteLine(string.Empty); Console.WriteLine("Stack trace:"); Console.WriteLine(e.StackTrace); return(-1); } }