您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

471 行
16 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using UnityEditor;
using UnityEngine;
using System.Threading.Tasks;
using System.Net.Http.Headers;
using System.Text;
using COSXML;
using COSXML.Model.Object;
using COSXML.Transfer;
using MetaCity.BundleKit.Editor.Utils;
using Newtonsoft.Json;
namespace MetaCity.BundleKit.Editor
{
public enum ServerType
{
None, // no need server
Official, // use official server
Customize // use customize server
}
public delegate void FailedCallBack();
public class MetacityBuildWindow : EditorWindow
{
private FailedCallBack _failedCallBack;
private Config _config = new Config();
private SerializedObject _portObject;
private SerializedProperty _portsProperty;
private SerializedProperty _envVerbsProperty;
private float _process = 0;
private string _processNote = "";
private bool _showProcessBar = false;
private bool _isPublishClick = false;
private PutObjectRequest _request;
private COSXMLUploadTask _uploadTask;
protected virtual void OnEnable()
{
_failedCallBack = CloseProcessBar;
_portObject = new SerializedObject(this);
_envVerbsProperty = _portObject.FindProperty("environmentVariables");
_portsProperty = _portObject.FindProperty("gameServerPorts");
_isPublishClick = false;
LoadConfig();
}
protected void OnDestroy() {
SaveConfig();
}
private void LoadConfig()
{
if (!Directory.Exists(Constants.TokenConfigPath))
{
Directory.CreateDirectory(Constants.TokenConfigPath);
}
var path=Path.Combine(Constants.TokenConfigPath,"config.json");
if (!System.IO.File.Exists(path))
{
_config = new Config();
var fs = System.IO.File.Create(path);
var json = JsonConvert.SerializeObject(_config);
byte[] array = Encoding.UTF8.GetBytes(json);
fs.Write(array);
fs.Close();
fs.Dispose();
return;
}
Config localConfig = JsonTools.FromFile<Config>(path);
if (localConfig != null)
{
_config = localConfig;
}
else
{
Debug.LogError("failed to deserialize config data");
}
}
private void SaveConfig()
{
if (!Directory.Exists(Constants.TokenConfigPath))
{
Directory.CreateDirectory(Constants.TokenConfigPath);
}
var path=Path.Combine(Constants.TokenConfigPath,"config.json");
if (!System.IO.File.Exists(path))
{
var fs = System.IO.File.Create(path);
var json = JsonConvert.SerializeObject(_config);
byte[] array = Encoding.UTF8.GetBytes(json);
fs.Write(array);
fs.Close();
fs.Dispose();
return;
}
JsonTools.ToFile(_config, path);
}
#region render UI
protected virtual void OnGUI()
{
EditorGUILayout.BeginVertical();
// RenderHelper();
//
// EditorGUILayout.Space(10);
//
// RenderPublishInfo();
//
// EditorGUILayout.Space(10);
RenderActions();
EditorGUILayout.EndVertical();
}
private void RenderHelper()
{
EditorGUILayout.HelpBox("\n" +
"Publish your cloudrendering build zip to metacity platform.\n" +
"\n"
, MessageType.Info);
}
private void RenderPublishInfo()
{
_config.templateName = EditorGUILayout.TextField(new GUIContent("Template Name"), _config.templateName);
_config.thumbnail = EditorGUILayout.TextField(new GUIContent("Template Thumbnail"), _config.thumbnail);
_config.memberLimit =
EditorGUILayout.IntSlider(new GUIContent("Template Member Limit"), _config.memberLimit, 5, 8);
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Template Description");
_config.description =
EditorGUILayout.TextArea(_config.description, EditorStyles.textArea, GUILayout.Height(50));
EditorGUILayout.Space(10);
EditorGUILayout.HelpBox("\n" +
"If you need to add/update build content, please export the build file in advance and compress it into zip.\n" +
"\n"
, MessageType.Warning);
_config.buildNeeded = EditorGUILayout.Toggle(new GUIContent("create/update Build"), _config.buildNeeded);
EditorGUI.indentLevel++;
}
private void RenderActions()
{
MetacityTokenWindow.Validate();
if (_isPublishClick)
{
_isPublishClick = false;
_showProcessBar = true;
Publish();
}
if (MetacityTokenWindow.IsAccessTokenValid)
{
if (GUILayout.Button($"Publish"))
{
_isPublishClick = true;
EditorUtility.SetDirty(this);
}
}
else
{
EditorGUILayout.HelpBox("\n" +
"Your access token is invalid. \n" +
"Please update your access token.\n" +
"\n", MessageType.Warning);
if (GUILayout.Button("Update Access Token"))
{
MetacityTokenWindow.OpenTokenWindow();
}
}
if (_showProcessBar)
{
Repaint();
if (EditorUtility.DisplayCancelableProgressBar("Upload File to COS", _processNote, _process))
{
_request?.Cancel();
_uploadTask?.Cancel();
CloseProcessBar();
Debug.Log("Publish canceled");
}
}
}
private async void Publish()
{
bool isValid = await MetacityClient.CheckAccessToken();
if (!isValid)
{
EditorUtility.SetDirty(this);
CloseProcessBar();
return;
}
if (string.IsNullOrEmpty(_config.templateId))
{
var result = await CreateNewTemplateByConfig(_failedCallBack);
if(!result) return;
}
else
{
var template = await MetacityClient.GetTemplateById(_config.templateId);
if (template == null)
{
var result = await CreateNewTemplateByConfig(_failedCallBack);
if(!result) return;
}
var templateResponse = await MetacityClient.UpdateTemplateById(template, _config.templateId, _config.templateName, _config.description,
_config.thumbnail, _config.buildId);
if (templateResponse == null)
{
CloseProcessBar();
}
}
SaveConfig();
Debug.Log("Template info has been updated.");
if (_config.buildNeeded)
{
var bundles = BuildEntry.LoadLastBuiltCatalog();
_config.assetBundles.Clear();
for (int i = 0; i < bundles.Count; i++)
{
_config.assetBundles.Add(new AssetBundle()
{
bundlePath = bundles[i].bundleLocalPath,
bundleName = bundles[i].bundleName,
bundleType = bundles[i].bundleType,
bundleHash = bundles[i].bundleHash,
bundleDependencies = bundles[i].bundleDependencies,
platform = bundles[i].bundlePlatform
});
}
if (string.IsNullOrEmpty(_config.buildId))
{
var result = await CreateNewCloudrenderingByConfig(_failedCallBack);
if (!result) return;
}
else
{
var cr = await MetacityClient.GetCloudrenderingById(_config.buildId);
if (cr == null)
{
var result = await CreateNewCloudrenderingByConfig(_failedCallBack);
if (!result) return;
}
}
_processNote = "Start upload ...";
var isSuccess = await UploadBundles(_config.assetBundles, _failedCallBack);
if (!isSuccess)
{
return;
}
bool isPublish = await MetacityClient.Publish(
_config.templateId,
_config.buildId,
_config.serverType.ToString(),
_config.assetBundles
);
if (isPublish)
{
Debug.Log("Publish successful.");
}
else
{
Debug.LogError("Publish Failed");
}
}
CloseProcessBar();
}
private void CloseProcessBar()
{
EditorUtility.ClearProgressBar();
_showProcessBar = false;
EditorUtility.SetDirty(this);
}
private async Task<bool> CreateNewTemplateByConfig(FailedCallBack callBack)
{
var template = await MetacityClient.CreateTemplate(_config.templateName, _config.description, _config.thumbnail);
if (template == null)
{
callBack.Invoke();
return false;
}
_config.templateId = template.id;
_config.templateName = template.name;
_config.description = template.description;
_config.thumbnail = template.banner;
return true;
}
private async Task<bool> CreateNewCloudrenderingByConfig(FailedCallBack callBack)
{
var cr = await MetacityClient.CreateCloudrendering(_config.templateName, _config.description,
_config.templateName);
if (cr == null)
{
callBack.Invoke();
return false;
}
_config.buildId = cr.id;
var template = await MetacityClient.GetTemplateById(_config.templateId);
if (template == null)
{
callBack.Invoke();
return false;
}
var templateResponse = await MetacityClient.UpdateTemplateById(template, _config.templateId, _config.templateName, _config.description,
_config.thumbnail, _config.buildId);
if (templateResponse == null)
{
callBack.Invoke();
return false;
}
return true;
}
private async void UpdateConfig()
{
_config.userId = await MetacityClient.GetUserId();
if(string.IsNullOrEmpty(_config.templateId)) return;
var template = await MetacityClient.GetTemplateById(_config.templateId);
_config.templateName = template.name;
_config.thumbnail = template.banner;
_config.description = template.description;
var assetBundles = await MetacityClient.GetAssetBundleByTemplateId(_config.templateId);
if (assetBundles.Count > 0)
{
_config.assetBundles.Clear();
foreach (var ab in assetBundles)
{
AssetBundle assetBundle = new AssetBundle()
{
bundleName = ab.bundleName,
bundlePath = ab.bundlePath,
bundleType = ab.bundleType,
bundleHash = ab.bundleHash,
bundleDependencies = ab.bundleDependencies,
platform = ab.platform,
extraInfo = ab.extraInfo
};
_config.assetBundles.Add(assetBundle);
}
}
}
#endregion
#region Upload cos
private async Task<bool> UploadBundles(List<AssetBundle> assetBundles, FailedCallBack onFailed)
{
CosXmlConfig config = new CosXmlConfig.Builder()
.SetRegion("ap-shanghai")
.SetDebugLog(true)
.Build();
var cosXml = new CosXmlServer(config, null);
int totalCount = assetBundles.Count;
int count = 1;
foreach (var assetBundle in assetBundles)
{
if (!File.Exists(assetBundle.bundlePath))
{
onFailed.Invoke();
return false;
}
try
{
var cosPath = $"{assetBundle.bundleName}-{assetBundle.bundleHash}";
string requestSignURL = await MetacityClient.GetUploadUrlAsync(cosPath);
_request = new PutObjectRequest(null, null, assetBundle.bundlePath);
_request.RequestURLWithSign = requestSignURL;
_request.SetCosProgressCallback(delegate(long completed, long total)
{
_process = (float) completed / total;
_processNote = string.Format("Upload({0}/{1})\n" +
"uploaded {2} of {3} bytes. {4:##.##} % complete...",
count,
totalCount,
completed,
total,
completed * 100.0 / total);
});
PutObjectResult result = cosXml.PutObject(_request);
if (result.IsSuccessful())
{
count++;
}
else
{
return false;
}
}
catch (COSXML.CosException.CosClientException clientEx)
{
Debug.LogException(clientEx);
}
catch (COSXML.CosException.CosServerException serverEx)
{
Debug.LogException(serverEx);
}
}
return true;
}
#endregion
private async Task<bool> PublishAssetBundles(List<AssetBundle> assetBundles)
{
bool upload = await UploadBundles(assetBundles, _failedCallBack);
if (upload)
{
return await MetacityClient.PublishAssetBundles(assetBundles);
}
return false;
}
}
}