#if UNITY_EDITOR using ConjureOS.MetadataWindow; using System; using System.IO; using System.IO.Compression; using UnityEditor; using UnityEngine; namespace ConjureOS.UploaderWindow { public class ConjureArcadeUploadProcessor { private const string logConjureArcade = "Conjure Arcade: "; private const string GameFolder = "game\\"; private const string MediasFolder = "medias\\"; private const string TempFolder = "temp\\"; private const string MetadataFileName = "metadata.txt"; /// /// Build and upload the game to the web server. /// Must use valid Conjure Arcade metadata, or the process will fail. /// /// The Conjure Arcade metadata of the game /// The metadata validator public void BuildAndUpload(ConjureArcadeMetadata metadata, ConjureArcadeMetadataValidator metadataValidator) { // Step 1: Validate metadata if (!metadataValidator.ValidateMetadata(metadata)) { ShowErrorDialog( "Some entries in the game metadata are incorrect. " + "You must fix them in order to upload the game to the web server."); return; } // Step 2: Build game string fileName; // Name of the executable file string fileExtension; // Extension of the executable file string buildDirectoryPath; // Path to the build directory string tempDirectoryPath; // Path to the temp directory, located inside the build directory try { // Get current build settings BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions(); buildPlayerOptions = BuildPlayerWindow.DefaultBuildMethods.GetBuildPlayerOptions(buildPlayerOptions); // Get file and directory data fileName = Path.GetFileNameWithoutExtension(buildPlayerOptions.locationPathName); fileExtension = Path.GetExtension(buildPlayerOptions.locationPathName); buildDirectoryPath = Path.GetDirectoryName(buildPlayerOptions.locationPathName) + "\\"; tempDirectoryPath = buildDirectoryPath + TempFolder; // Change Build Settings build directory to the temp directory // Generated location for the game is of the format "...BuildDirectory\temp\game\ProductName.extension" buildPlayerOptions.locationPathName = tempDirectoryPath + GameFolder + fileName + fileExtension; // Build the game BuildPipeline.BuildPlayer(buildPlayerOptions); } catch (BuildPlayerWindow.BuildMethodException) { // Exception called when the user manually closes the "File Chooser" window Debug.Log(logConjureArcade + "Build & Upload canceled."); return; } catch (Exception e) { ShowErrorDialog("An error occured when building the game."); Debug.LogError(e); return; } // "game" folder content is compressed CompressAndDelete(tempDirectoryPath + GameFolder, tempDirectoryPath + "game.zip"); // Step 3: Copy images to the temp directory string mediasDirectoryPath = tempDirectoryPath + MediasFolder; string thumbnailPath = CopyAndRenameImage(metadata.Thumbnail, mediasDirectoryPath, "thumbnail"); string gameplayImagePath = CopyAndRenameImage(metadata.GameplayImage, mediasDirectoryPath, "gameplayImage"); // Step 4: Generate metadata inside the temp directory metadata.UpdateUneditableData(); string metadataContent = GenerateMetadata(metadata, thumbnailPath, gameplayImagePath, fileName + fileExtension); if (!WriteMetadataFile(metadataContent, tempDirectoryPath)) { ShowErrorDialog("An error occured when generating the metadata file."); return; } // Step 5: Convert all files int a ".conj" string conjFilePath = buildDirectoryPath + fileName + ".conj"; CompressAndDelete(tempDirectoryPath, conjFilePath); // Step 6: Upload game and metadata to the webserver // TODO Add server connection / upload // Step 7: Show success feedback to the user Debug.Log(logConjureArcade + "Game was build and upload to the web server."); EditorUtility.DisplayDialog( "Success", "Game was build and upload to the web server.", "Ok"); } private static void ShowErrorDialog(string description) { EditorUtility.DisplayDialog("Fail to Build and Upload Game", description, "Ok"); Debug.LogError(logConjureArcade + description); } private static string CopyAndRenameImage(Texture2D image, string newDirectoryPath, string newFileName) { string relativePath = AssetDatabase.GetAssetPath(image); // We check and remove "Assets" at the start of the relative path because // Application.dataPath already gives us the path to the assets folder // Ex: Assets/Images/ --> Images/ string oldAbsolutePath = Application.dataPath + relativePath.Substring(6); // We find the image, copy it to the new folder (newDirectoryPath), change its name and keep its extension FileInfo file = new FileInfo(oldAbsolutePath); string fullFileName = string.Format("{0}{1}", newFileName, file.Extension); if (file.Exists) { // Delete file in new directory if it already exists string newFilePath = string.Format("{0}{1}", newDirectoryPath, fullFileName); if (!Directory.Exists(newDirectoryPath)) { // Check if new directory exists, and create it // If folder doesn't exist, the file cannot be copied Directory.CreateDirectory(newDirectoryPath); } else if (File.Exists(newFilePath)) { // Check if file exists, and delete it File.Delete(newFilePath); } file.CopyTo(newFilePath); } return fullFileName; } private string GenerateMetadata( ConjureArcadeMetadata metadata, string thumbnailFileName, string gameplayImageFileName, string fileName) { string newLine = Environment.NewLine; string content = ""; content += "id: " + metadata.Id + newLine + "game: " + metadata.GameTitle + newLine + "version: " + metadata.Version + newLine + "description: " + metadata.Description + newLine + "players: " + metadata.MinNumPlayer + "-" + metadata.MaxNumPlayer + newLine + "leaderboard: " + metadata.UseLeaderboard + newLine + "thumbnailPath: " + thumbnailFileName + newLine + "imagePath: " + gameplayImageFileName + newLine + "release: " + FormatDate(metadata.ReleaseDate) + newLine + "modification: " + FormatDate(metadata.LastGameUpdate) + newLine + "file: " + GameFolder + fileName + newLine; // Adding developers content += "developers: "; foreach (string developer in metadata.Developers) { content += developer + ", "; } content += newLine; // Adding genres content += "genres:" + newLine; foreach (GameGenre gameGenre in metadata.Genres) { string genre = ConjureArcadeMetadata.GenreOptions[gameGenre.selectedGenre]; content += " " + genre + newLine; } return content; } private bool WriteMetadataFile(string content, string directoryPath) { string fullPath = directoryPath + MetadataFileName; try { if (File.Exists(fullPath)) { File.Delete(fullPath); } // Write content using (FileStream fs = File.Create(fullPath)) { byte[] encodedContent = new System.Text.UTF8Encoding(true).GetBytes(content); fs.Write(encodedContent, 0, encodedContent.Length); } } catch (Exception e) { Debug.LogError(e.Message); return false; } return true; } private void CompressAndDelete(string sourceDirectoryPath, string destinationArchiveFileName) { ZipFile.CreateFromDirectory(sourceDirectoryPath, destinationArchiveFileName); Directory.Delete(sourceDirectoryPath, true); } private string FormatDate(DateTime date) { return date.Day.ToString() + "-" + date.Month.ToString() + "-" + date.Year.ToString(); } } } #endif