JD2022-TU1/main/tools/apps/Orbit.AfterEffects/Actions/ShowInGameAction.cs

159 lines
6.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Orbit.AfterEffects.Workspaces;
using Plume.Icons;
using Plume.Perforce.Service.Api;
using Ubisoft.Perforce;
using Ubisoft.Perforce.Helper;
namespace Orbit.AfterEffects.Actions
{
/// <summary>
/// Run the current map in game
/// </summary>
public class ShowInGameAction : BaseAction
{
private readonly IPerforceService _perforceService;
private readonly IExplorerSelection _appContext;
/// <inheritdoc />
public ShowInGameAction(IPerforceService perforceService, IExplorerSelection appContext)
: base("Show in game", "Open the game with the latest version of the map from Perforce.", StandardIcon.Run)
{
_perforceService = perforceService ?? throw new ArgumentNullException(nameof(perforceService));
_appContext = appContext ?? throw new ArgumentNullException(nameof(appContext));
}
/// <inheritdoc />
public override void TryExecute()
{
App.Current.TaskManager.ExecuteAsync(RunInGame, $"Launching '{_appContext.SelectedExplorerAsset?.MapName}'");
}
private Task RunInGame()
{
return Task.Run(() =>
{
if (_appContext.SelectedExplorerAsset == null)
{
throw new InvalidOperationException("No asset selected.");
}
if (string.IsNullOrEmpty(_perforceService.CurrentClient?.Stream))
{
throw new InvalidOperationException("Perforce stream is invalid.");
}
// Get map files
string mapName = _appContext.SelectedExplorerAsset.MapName;
SyncMapFiles(mapName);
if (mapName.EndsWith("ALT", StringComparison.Ordinal))
SyncMapFiles(mapName.Substring(0, mapName.Length - 3));
// Check map isc file
string mapPath = Path.Combine(_perforceService.CurrentClient.Root, "data/World/Maps", mapName);
string iscPath = Path.Combine(mapPath, $"{mapName}_MAIN_SCENE.isc");
if (!File.Exists(iscPath))
{
throw new FileNotFoundException($"Unable to find ISC file of {mapName} at '{iscPath}'.");
}
Context.Logger.Info($"Launching '{iscPath}'...");
string engineExePath = Path.Combine(_perforceService.CurrentClient.Root, "engine/ua_engine.exe");
if (!File.Exists(engineExePath))
{
throw new FileNotFoundException($"Unable to find engine. Did you forget to do a Get Latest?", engineExePath);
}
Process.Start(engineExePath, iscPath);
});
}
private void SyncMapFiles(string mapName)
{
Context.NotificationManager.ShowInformation($"Getting {mapName}...");
string depotRoot = _perforceService.GetCurrentStreamDepotRoot();
string mapDepotPath = $"{depotRoot}/data/World/MAPS/{mapName}/";
string iscDepotPath = Path.Combine(mapDepotPath, $"{mapName}_MAIN_SCENE.isc");
if (!_perforceService.CurrentClient.IsDepotFileInView(iscDepotPath))
{
string currentStreamName = _perforceService.Connection.GetCurrentStream();
throw new InvalidOperationException($"Map '{mapName}' seems to be unavailable in {currentStreamName} stream. If you need it, please contact the 'JD Tech Data' team (JDTechData@ubisoft.com).");
}
var filesToSync = _perforceService.Connection.GetFiles(mapDepotPath).Where(file => MustSynchronize(file, mapName)).ToList();
Sync(filesToSync);
}
private void Sync(List<string> depotPaths)
{
var errors = new List<string>();
var result = _perforceService.Connection.Sync(depotPaths, "head", SyncOptions.None, PerforceWrapper.SyncType.Revision, errors);
if (result && errors.Count == 0)
{
return;
}
List<string> actualErrors = new List<string>();
List<string> justWarnings = new List<string>();
foreach (var log in errors)
{
if (log.StartsWith("[warning]"))
{
justWarnings.Add(log);
}
else
{
actualErrors.Add(log);
}
}
if (actualErrors.Any())
{
Context.Logger.Error(string.Join(Environment.NewLine, actualErrors));
throw new Exception($"Unable to sync map: {actualErrors.Count} errors occured.");
}
if (justWarnings.Any())
{
Context.Logger.Info(string.Join(Environment.NewLine, justWarnings));
}
}
/// <summary>
/// Indicates whether we want to sync a file or not, as all files are not required to launch the map in the engine
/// </summary>
private bool MustSynchronize(string depotPath, string mapName)
{
if (depotPath.Contains("/Background/"))
return false;
if (depotPath.Contains("/Recording/"))
return false;
if (depotPath.EndsWith(".psd"))
return false;
if (depotPath.EndsWith(".webm") && !depotPath.EndsWith($"{mapName}.webm"))
return false;
if (depotPath.EndsWith(".mpd"))
return false;
if (depotPath.EndsWith(".mp4"))
return false;
return true;
}
/// <inheritdoc />
public override bool CanExecute()
{
return _appContext.SelectedExplorerAsset != null
&& App.Current.PerforceIsOk
&& _perforceService.HasCurrentClient
&& !App.Current.TaskManager.TaskInProgress;
}
}
}