/// <summary> /// Replace strings with the device dependent ones. /// </summary> /// <param name="zip">ZipFile, which contains the Lua file.</param> /// <param name="player">Device, for which we would change the strings.</param> /// <returns>The updated Lua code.</returns> public string UpdateLua ( ZipFile zip, Player player) { // Get input stream for Lua file string luaCode = getLuaCode(zip,filenameGwz); // Now parse the Lua file Lexer lexer = new Lexer (); // Split the Lua code into tokens // This time we know, that the Lua file is ok, so we didn't ceare about errors TokenReader tr = null; tr = lexer.Lex ( luaCode ); // Go to the beginning of the token stream tr.p = 0; // Now replace all strings with the right special character strings foreach ( Token t in tr.tokens ) if ( t.Type == TokenType.DoubleQuoteString || t.Type == TokenType.LongString || t.Type == TokenType.SingleQuoteString ) t.Data = player.ConvertString ( t.Data ); // Now create the Lua file again StringBuilder result = new StringBuilder ( luaCode.Length ); for (int i = 0; i < tr.tokens.Count - 3;i++ ) { if (tr.tokens[i].Leading.Count > 0) foreach (Token lt in tr.tokens[i].Leading) result.Append(lt.Data); switch (tr.tokens[i].Type) { case TokenType.DoubleQuoteString: result.AppendFormat("\"{0}\"", tr.tokens[i].Data); break; case TokenType.LongString: result.Append(tr.tokens[i].Data); break; case TokenType.SingleQuoteString: result.AppendFormat("\'{0}\'", tr.tokens[i].Data); break; case TokenType.EndOfStream: break; default: result.Append(tr.tokens[i].Data); break; } } result.Append("\n\n"); // If there are code, we should insert for this device, we do this now if (player.HasCode()) { string code = player.GetCode(tr.tokens[tr.tokens.Count - 2].Data); if (code != "") result.Append(code); } // If there is a library, we should insert, we do it now // Append "return cartridge" at the end result.Append("\n\n"); result.Append(tr.tokens[tr.tokens.Count - 3].Data); result.Append(" "); result.Append(tr.tokens[tr.tokens.Count - 2].Data); return result.ToString (); }
/// <summary> /// Compile the file filename for device and place user and completionCode into the resulting gwc file /// </summary> /// <param name="filename">Filename of the gwz file with path.</param> /// <param name="device">Name of the device for which the resulting gwc is compiled.</param> /// <param name="username">Username, which is wrote to gwc file and later used as Player.Name.</param> /// <param name="userid">User ID from Groundspeak, which is wrote to gwc file.</param> /// <param name="completionCode">CompletionCode, which is wrote to gwc file and later used as Player.CompletionCode.</param> /// <returns>Memory stream with the gwc file.</returns> public MemoryStream Compile(string filename, DeviceType device, string username = "", long userid = 0, string completionCode = "") { // Create object for player specific code Player player = new Player(device); // Create parser with filename Parser parser = new Parser(filename); // Open gwz for later use ZipFile zip = new ZipFile(parser.FilenameGwz); // Create object for all data belonging to the cartridge Cartridge cartridge = new Cartridge (); // Check, if the gwz file has the right format if (!parser.CheckGWZ(zip, cartridge)) { // Error in parsing gwz file throw new InvalidOperationException(String.Format("Line {0}, Column {1}: {2}", parser.Errors[0].Line, parser.Errors[0].Column, parser.Errors[0].Message)); } // Create LuaInterface LuaInterface lua = new LuaInterface(); string luaCode; // Create new Lua file with player specific characters and all other stuff luaCode = parser.UpdateLua(zip,player); // Only for debug reasons // saveLuaCode(luaCode); // Now we have a string with the Lua code, which have the right coding // So go on and compile the Lua code // LoadString of Lua code = compile Lua code LuaFunction func = lua.LoadString(luaCode, cartridge.Name); // Dump Lua code to memory stream, so we could later save it to gwc file MemoryStream luaBinary = new MemoryStream(); dumpCode(lua.LuaState,luaBinary); // Create memory stream to write gwc file MemoryStream stream = new MemoryStream(); BinaryWriter output = new BinaryWriter(stream); long savePosition; // Write gwc signature output.Write(new byte[7] { 0x02, 0x0a, 0x43, 0x41, 0x52, 0x54, 0x00 }); // Write number of images output.Write(getShort((short)(cartridge.MediaList.Count+1))); // Write media table for (int i = 0; i <= cartridge.MediaList.Count; i++) { output.Write(getShort((short)i)); output.Write(getInt((int)0)); } // Write size of header output.Write(getInt(0)); // Save position, where header starts long startHeader = output.BaseStream.Position; // Write header // Write position output.Write(getDouble((float) cartridge.Latitude)); output.Write(getDouble((float) cartridge.Longitude)); output.Write(getDouble((float) cartridge.Altitude)); // Write creation date // TODO: Replace with creation date string date = cartridge.CreateDate; output.Write(getLong(0)); // Write media index short splash = -1; for (int i = 0; i < cartridge.MediaList.Count; i++) if (cartridge.Splash != null && cartridge.Splash.Equals(cartridge.MediaList[i].Variable)) splash = (short)(i + 1); output.Write(getShort(splash)); // Write icon index short icon = -1; for (int i = 0; i < cartridge.MediaList.Count; i++) if (cartridge.Icon != null && cartridge.Icon.Equals(cartridge.MediaList[i].Variable)) icon = (short)(i + 1); output.Write(getShort(icon)); // Write cartridge type output.Write(getAscii(player.ConvertGWCString(cartridge.Activity))); // Write player data output.Write(getAscii(player.ConvertGWCString(username))); output.Write(getLong(userid)); // Write cartridge relevant information output.Write(getAscii(player.ConvertGWCString(cartridge.Name))); output.Write(getAscii(cartridge.Id)); output.Write(getAscii(player.ConvertGWCString(cartridge.Description))); output.Write(getAscii(player.ConvertGWCString(cartridge.StartingLocationDescription))); output.Write(getAscii(cartridge.Version)); output.Write(getAscii(player.ConvertGWCString(cartridge.Author))); output.Write(getAscii(player.ConvertGWCString(cartridge.Company))); output.Write(getAscii(player.ConvertGWCString(cartridge.TargetDevice))); // Write CompletionCode length output.Write(getInt(completionCode.Length+1)); // Write CompletionCode output.Write(getAscii(completionCode)); // Save position for later writing savePosition = output.BaseStream.Position; // Goto header length position and save the length output.BaseStream.Position = startHeader - 4; output.Write(getInt((int) (savePosition - startHeader))); output.BaseStream.Position = savePosition; // Write Lua binary code writeToMediaTable(output,0); output.Write(getInt((int)luaBinary.Length)); output.Write(luaBinary.ToArray()); // Now save all media files for (short i = 0; i < cartridge.MediaList.Count; i++) { // Write position for media table writeToMediaTable(output, (short)(i+1)); // Check media for right entry cartridge.MediaList[i].Entry = player.CheckMedia(cartridge.MediaList[i]); // Save media if (cartridge.MediaList[i].Entry == -1) { // No valid media file is found in resource list output.Write((byte) 0); } else { // Valid file found, so save type, length and bytes output.Write((byte) 1); output.Write(getInt(cartridge.MediaList[i].MediaType)); byte[] media = cartridge.MediaList[i].GetMediaAsByteArray(zip); output.Write(getInt(media.Length)); output.Write(media); } } return stream; }