public async Task Run(OperationArguments args) { var platformTasks = args.Platforms.Select(platform => Task.Run(async() => { Console.WriteLine("Starting compilation for " + platform + "..."); var targetPlatform = (TargetPlatform)Enum.Parse(typeof(TargetPlatform), platform); var targetOutputPath = Path.Combine(new DirectoryInfo(args.OutputPath).FullName, platform); Directory.CreateDirectory(targetOutputPath); var kernel = new StandardKernel(); kernel.Load <ProtogameAssetModule>(); var sourceLayer = kernel.Get <LocalFilesystemAssetFsLayer>(new NamedConstructorArgument("basePath", Environment.CurrentDirectory)); kernel.Unbind <IAssetFsLayer>(); kernel.Bind <IAssetFsLayer>().ToMethod(ctx => sourceLayer); kernel.Bind <IAssetFsLayer>().ToMethod(ctx => ctx.Kernel.Get <LocalFilesystemAssetFsLayer>(new NamedConstructorArgument("basePath", targetOutputPath))); kernel.Unbind <ICompiledAssetFs>(); kernel.Rebind <ICompiledAssetFs>().ToMethod(ctx => ctx.Kernel.Get <HostCompiledAssetFs>(new NamedConstructorArgument("targetPlatform", targetPlatform))); kernel.Rebind <IRenderBatcher>().To <NullRenderBatcher>(); kernel.Unbind <IAssetCompiler>(); (new ProtogameAssetModule()).LoadRawAssetStrategies(kernel); LoadAndBindTypes(kernel, args.Assemblies); var compiledAssetFs = kernel.Get <ICompiledAssetFs>(); var assetFs = kernel.Get <IAssetFs>(); Console.WriteLine("Scanning for content..."); var compilationTasks = await compiledAssetFs.ListTasks().ConfigureAwait(false); var saveTasks = new List <Task>(); var expectedPaths = new ConcurrentBag <string>(); foreach (var compilationTask in compilationTasks) { saveTasks.Add(compilationTask.ContinueWith(async compiledAssetTask => { var compiledAsset = await compiledAssetTask.ConfigureAwait(false); var originalAsset = await assetFs.Get(compiledAsset.Name).ConfigureAwait(false); var targetPath = Path.Combine(targetOutputPath, compiledAsset.Name.Replace('.', Path.DirectorySeparatorChar)) + ".bin"; // Check that the source file exists on disk in order to add it to the expected paths. if (await sourceLayer.Get(compiledAsset.Name).ConfigureAwait(false) != null) { expectedPaths.Add(targetPath); } if (originalAsset.ModificationTimeUtcTimestamp < compiledAsset.ModificationTimeUtcTimestamp) { Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); using (var writer = new FileStream(targetPath, FileMode.Create, FileAccess.Write, FileShare.None)) { Console.WriteLine("Saving " + compiledAsset.Name + " to disk for " + platform + "..."); using (var stream = await compiledAsset.GetContentStream().ConfigureAwait(false)) { await stream.CopyToAsync(writer).ConfigureAwait(false); } } } })); } await Task.WhenAll(saveTasks).ConfigureAwait(false); Console.WriteLine("Deleting compiled assets that have no source asset..."); var allActualCompiledAssets = FindAllCompiledAssets(targetOutputPath).Select(x => Path.Combine(targetOutputPath, x.Replace('.', Path.DirectorySeparatorChar) + ".bin").ToLowerInvariant()).ToArray(); var allExpectedCompiledAssets = expectedPaths.Select(x => x.ToLowerInvariant()).ToArray(); var hashsetWorking = new HashSet <string>(allActualCompiledAssets); var hashsetExpected = new HashSet <string>(allExpectedCompiledAssets); hashsetWorking.ExceptWith(hashsetExpected); foreach (var compiledAssetOnDisk in hashsetWorking) { Console.WriteLine("Deleting " + compiledAssetOnDisk + "..."); File.Delete(compiledAssetOnDisk); } })).ToArray(); await Task.WhenAll(platformTasks); }
public static void Main(string[] args) { var assemblies = new List <string>(); var platforms = new List <string>(); var output = string.Empty; var operation = string.Empty; string androidPlatformTools = null; var options = new OptionSet { { "a|assembly=", "Load an assembly.", v => assemblies.Add(v) }, { "p|platform=", "Specify one or more platforms to target.", v => platforms.Add(v) }, { "o|output=", "Specify the output folder for the compiled assets.", v => output = v }, { "m|operation=", "Specify the mode of operation (either 'compile', 'server' or 'builtin', default is 'compile').", v => operation = v }, { "android-platform-tools=", "Specifies the path to ADB (used for connecting to a game running on an Android device)", v => androidPlatformTools = v }, }; try { options.Parse(args); } catch (OptionException ex) { Console.Write("ProtogameAssetTool.exe: "); Console.WriteLine(ex.Message); Console.WriteLine("Try `ProtogameAssetTool.exe --help` for more information."); Environment.Exit(1); return; } var operationArguments = new OperationArguments { Assemblies = assemblies.ToArray(), Platforms = platforms.ToArray(), AndroidPlatformTools = androidPlatformTools, OutputPath = output }; IOperation operationInst; switch (operation) { case "remote": throw new NotSupportedException(); case "server": operationInst = new ServerOperation(); break; case "builtin": operationInst = new BuiltinOperation(); break; case "compile": default: operationInst = new CompileOperation(); break; } var task = Task.Run(async() => await operationInst.Run(operationArguments).ConfigureAwait(false)); task.Wait(); }