159 lines
6.1 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|