using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using System.IO;
using ResMgr;
using GameEditor.AssetBundle;
using GameEditor.Core;
using GameCore;
using ResUpdate;
using GameLogic;
namespace GameEditor.FrameTool
{
public class FrameTool
{
///
/// 初始化游戏环境
///
//[MenuItem("GameFrame/InitResEnvironment", false, 1)]
//public static void InitResEnvironment()
//{
// ResourcesPathEditor.InitIgnoreList();
//}
///
/// 刷新资源配置文件
///
[MenuItem("GameFrame/刷新资源配置", false, 2)]
public static void RefreshResPathConfigs()
{
ResourcesPathEditor.CreateResourcePathConfig();
EditorUtil.ShowSureDialog("资源配置文件生成完毕!");
}
///
/// 检查资源循环依赖
///
[MenuItem("GameFrame/检查循环依赖", false, 2)]
public static void CheckDependences()
{
ResourcesPathEditor.ForEachCheckDependences();
EditorUtil.ShowSureDialog("检查完毕!");
}
///
/// 战斗服务端验证同步
///
[MenuItem("GameFrame/战斗逻辑同步", false, 2)]
public static void BattleLogicSync()
{
string p = Application.dataPath;
p = p.Substring(0, p.LastIndexOf('/'));
string t1 = p.Substring(p.LastIndexOf('/'), p.Length - p.LastIndexOf('/'));
p = p.Substring(0, p.LastIndexOf('/'));
string t2 = p.Substring(p.LastIndexOf('/'), p.Length - p.LastIndexOf('/'));
p = p.Substring(0, p.LastIndexOf('/'));
string p2 = p + "/battleWeb" + t2 + t1;
string[] files = Directory.GetFiles(AppConst.GameResRealPath + "/~Lua/Modules/Battle/Logic", "*.lua", SearchOption.AllDirectories);
foreach (var s in files)
{
string s2 = s.Replace(Application.dataPath + "/ManagedResources/~Lua", p2);
FileUtils.CopyFile(s, s2);
}
Debug.LogError("同步完成!");
}
///
/// 获取所有游戏
///
///
public static string[] GetAllGames() {
string fullPath = EditorUtil.GetFullPath(AppConst.GameResPath);
string[] directorys = Directory.GetDirectories(fullPath);
string[] games = new string[directorys.Length];
string game = string.Empty;
for (int i = 0; i < directorys.Length; i++)
{
game = Path.GetFileName(directorys[i]);
games[i] = game;
}
return games;
}
///
/// 刷新选中资源配置文件
///
[MenuItem("Assets/GameFrame/RefreshResPathConfig")]
public static void RefreshResPathConfig()
{
try
{
ResourcesPathEditor.CreateResourcePathConfig();
EditorUtil.ShowSureDialog("资源配置文件生成完毕!");
}
catch (Exception e)
{
Debug.LogErrorFormat("RefreshResPathConfigError:{0}", e.ToString());
}
}
///
/// 整体打包
///
public static void BuildAll()
{
AssetBundleBuilder.ClearMarks();
BuildGameAssetBundles();
}
[MenuItem("AssetBundle/MarkAllGame")]
///
/// 标记所有游戏
///
public static void MarkAllGame()
{
MarkGame(false);
ResourcesPathEditor.CreateResourcePathConfig();
}
///
/// 检查AB包的资源合法性
/// 1.AssetBundle的循环依赖
/// 2.AssetBundle的跨游戏依赖
///
public static void CheckAssetBundleStates() {
AssetBundleBuilder.ClearMarks();
MarkAllGame();
}
public static void AssetsDuplicatedInMultBundlesCache(int type)
{
string target;
foreach(var path in AssetBundleBrowser.AssetBundleModel.Model.AssetsDuplicatedInMultBundlesCache)
{
if(type == 1)
{
Debug.LogError("path:" + path);
}
else
{
Debug.LogError("正在移动:" + path);
string extension = Path.GetExtension(path).ToLower();
switch (extension)
{
case ".png":
case ".tga":
target = "Textures/";
break;
case ".mat":
target = "Materials/";
break;
case ".fbx":
target = "Models/";
break;
case ".anim":
case ".controller":
target = "Animations/";
break;
default:
target = null;
break;
}
if (target != null)
{
File.Move(Application.dataPath + path.Replace("Assets", ""),
AppConst.GameResRealPath + "/PublicArtRes/" + target + Path.GetFileNameWithoutExtension(path) + extension);
File.Move(Application.dataPath + path.Replace("Assets", "") + ".meta",
AppConst.GameResRealPath + "/PublicArtRes/" + target + Path.GetFileNameWithoutExtension(path) + extension + ".meta");
}
}
}
AssetDatabase.Refresh();
}
///
/// 打包游戏
///
public static void BuildGameAssetBundles()
{
AssetBundleBuilder.ClearMarks();
MarkGame(true);
string exportPath = AssetBundleConfig.GetExportPath(EditorUserBuildSettings.activeBuildTarget);
if (Directory.Exists(exportPath))
Directory.Delete(exportPath, true);
AssetBundleBuilder.BuildAssetBundleWithType(exportPath, AssetBundleConfig.LZ4Options, EditorUserBuildSettings.activeBuildTarget, CompressType.LZ4);
AssetBundleBuilder.BuildAssetBundleWithType(exportPath, AssetBundleConfig.LZMAOptions, EditorUserBuildSettings.activeBuildTarget, CompressType.LZMA);
CreateCRCFiles(exportPath);
AssetBundleBuilder.ClearManifest(exportPath);
EditorUtil.OpenFolderAndSelectFile(exportPath);
}
///
/// 拷贝AssetBundle到StreamingAssets
///
///
public static void CopyAssetBundleToStreamingAssets()
{
string exportPath = AssetBundleConfig.GetExportPath(EditorUserBuildSettings.activeBuildTarget);
string streamingPath = GetStreamingAssetPath(EditorUserBuildSettings.activeBuildTarget);
//Debug.LogError(streamingPath);
if (Directory.Exists(streamingPath)) Directory.Delete(streamingPath,true);
Directory.CreateDirectory(streamingPath);
FileUtils.ReplaceDir(exportPath, streamingPath);
//CopyResourceFiles();
}
///
/// 单打lua资源
///
public static bool BuildLuaAssetBundles()
{
AssetImporter ai = AssetImporter.GetAtPath(AppConst.GameResPath + "/LuaBytes");
if(ai == null)
{
Debug.LogError("lua资源不存在!请先打全包!");
return false;
}
AssetBundleBuilder.ClearMarks();
MarkGame(true);
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = ai.assetBundleName;
build.assetBundleVariant = ai.assetBundleVariant;
build.assetNames = new string[] { ai.assetPath };
AssetImporter ai2 = AssetImporter.GetAtPath(AppConst.GameResPath + "/ResConfigs");
AssetBundleBuild build2 = new AssetBundleBuild();
build2.assetBundleName = ai2.assetBundleName;
build2.assetBundleVariant = ai2.assetBundleVariant;
build2.assetNames = new string[] { ai2.assetPath };
string exportPath = AssetBundleConfig.GetExportPath(EditorUserBuildSettings.activeBuildTarget);
var manifest = BuildPipeline.BuildAssetBundles(exportPath, new AssetBundleBuild[] { build, build2 }, BuildAssetBundleOptions.DeterministicAssetBundle, EditorUserBuildSettings.activeBuildTarget);
// 加密 文件前加入128个空字符
foreach (var name in manifest.GetAllAssetBundles())
{
var uniqueSalt = Encoding.UTF8.GetBytes(name);
string pn = Path.Combine(exportPath, name);
byte[] oldData = File.ReadAllBytes(pn);
int len = (int)GameLogic.AppConst.EncyptBytesLength;
int newOldLen = len + oldData.Length;//定死了,128个空byte
var newData = new byte[newOldLen];
for (int tb = 0; tb < oldData.Length; tb++)
{
newData[len + tb] = oldData[tb];
}
FileStream fs = File.OpenWrite(pn);//打开写入进去
fs.Write(newData, 0, newOldLen);
fs.Close();
}
CreateCRCFiles(exportPath);
AssetBundleBuilder.ClearManifest(exportPath);
AssetDatabase.Refresh();
return true;
}
///
/// 数据目录
///
static string AppDataPath
{
get { return Application.dataPath.ToLower(); }
}
public static void CopyResourceFiles()
{
string AssetRoot = "StreamingAssets/Android";
if (BuildTarget.iOS == EditorUserBuildSettings.activeBuildTarget)
{
AssetRoot = "StreamingAssets/IOS";
}
string ResourcePath = "Resources/";
string resPath = AppDataPath + "/" + AssetRoot + "/";
///----------------------创建文件列表-----------------------
string newFilePath = resPath + "/" + ResourcePath;
if (Directory.Exists(newFilePath))
Directory.Delete(newFilePath, true);
Directory.CreateDirectory(newFilePath);
string sourcePath = Application.dataPath + "/Resources/";
string[] files = Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories);
foreach (var file in files)
{
FileInfo info = new FileInfo(file);
File.Copy(file, newFilePath + info.Name, true);
}
}
public static void SaveVersionFile()
{
}
///
/// 创建CRC文件
///
///
public static void CreateCRCFiles(string exportPath)
{
string fullPath = exportPath;
if (!Directory.Exists(fullPath))
return;
string[] files = Directory.GetFiles(fullPath, "*.unity3d", SearchOption.AllDirectories);
string savePath = string.Format("{0}/CRC/game.asset", Application.dataPath);
string saveAssetPath = EditorUtil.GetAssetsPath(savePath);
ResourceFiles resourceFiles = null;
if (File.Exists(savePath))
{
resourceFiles = AssetDatabase.LoadAssetAtPath(saveAssetPath);
}
else
{
string directory = Path.GetDirectoryName(savePath);
if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
resourceFiles = ScriptableObject.CreateInstance();
AssetDatabase.CreateAsset(resourceFiles,saveAssetPath);
}
if (resourceFiles == null)
{
string message = string.Format("资源CRC信息列表文件{0}错误,请查看", savePath);
EditorUtility.DisplayDialog("提示", message, "确定");
return;
}
if(resourceFiles.files==null)
resourceFiles.files = new List();
resourceFiles.files.Clear();
FileInfo info = null;
ResourceFile file = null;
for (int i = 0; i < files.Length; i++)
{
files[i] = EditorUtil.FixedWindowsPath(files[i]);
info = new FileInfo(files[i]);
file = new ResourceFile();
file.id = i + 1;
file.fileName = files[i].Replace(exportPath+"/",string.Empty);
file.size = info.Length;
file.crc = FileToCRC32.GetFileCRC32(files[i]);
resourceFiles.files.Add(file);
}
EditorUtility.SetDirty(resourceFiles);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
AssetBundleBuilder.BuildAssetBundle(resourceFiles, "files", exportPath, AssetBundleConfig.LZMAOptions, EditorUserBuildSettings.activeBuildTarget);
}
///
/// 拷贝Lua文件
///
public static void CopyLuaFiles() {
try
{
string luaBytesFullPath = EditorUtil.GetFullPath(string.Format("{0}/LuaBytes", AppConst.GameResPath));
if (!Directory.Exists(luaBytesFullPath))
{
Directory.CreateDirectory(luaBytesFullPath);
}
List files = EditorUtil.GetFiles(luaBytesFullPath, "*", SearchOption.AllDirectories);
for (int i = 0; i < files.Count; i++) {
File.Delete(files[i]);
}
string luaFullPath = EditorUtil.GetFullPath(string.Format("{0}/~Lua", AppConst.GameResPath));
files = EditorUtil.GetFiles(luaFullPath, "*.lua", SearchOption.AllDirectories);
string inPath = string.Empty;
string outPath = string.Empty;
for (int i = 0; i < files.Count; i++) {
inPath = files[i];
outPath = inPath.Replace(luaFullPath+"/", string.Empty).Replace("/","%").Replace(".lua",".bytes");
outPath = luaBytesFullPath + "/" + outPath;
//FileUtils.CopyFile(inPath, outPath);
Packager.EncodeLuaFile(inPath, outPath);
}
Debug.LogFormat("拷贝Lua文件完成!");
AssetDatabase.Refresh();
}
catch (Exception e) {
Debug.LogErrorFormat("CopyLuaFiles error:{0}",e);
}
}
///
/// 处理lua文件
///
///
///
public static void HandleLuaFile(string inpath, string outPath) {
}
///
/// 标记一个游戏
///
public static void MarkGame(bool refreshConfig = false)
{
try
{
//拷贝Lua文件
CopyLuaFiles();
//标记Lua
string buildConfigPath = string.Format("{0}/EditorConfigs/BuildConfigs.asset", AppConst.GameResPath);
AssetBundleBuildConfigs configs = AssetDatabase.LoadAssetAtPath(buildConfigPath);
AssetBundleBuildConfig[] paths = configs.OneFloderOneBundle;
for (int i = 0; i < paths.Length; i++)
{
if (string.IsNullOrEmpty(paths[i].Path))
{
Debug.LogErrorFormat("MarkGame error:BuildConfigs contain null floder." + paths[i].Path);
continue;
}
AssetBundleBuilder.MarkOneFloderOneBundle(paths[i].Path, paths[i].CompressType);
}
paths = configs.SubFloderOneBundle;
for (int i = 0; i < paths.Length; i++)
{
if (string.IsNullOrEmpty(paths[i].Path))
{
Debug.LogErrorFormat("MarkGame error:BuildConfigs contain null floder.");
continue;
}
AssetBundleBuilder.MarkSubFloderOneBundle(paths[i].Path,paths[i].CompressType);
}
paths = configs.OneAssetOneBundle;
for (int i = 0; i < paths.Length; i++)
{
if (string.IsNullOrEmpty(paths[i].Path))
{
Debug.LogErrorFormat("MarkGame error:BuildConfigs contain null floder");
continue;
}
AssetBundleBuilder.MarkOneAssetOneBundle(paths[i].Path, true, paths[i].CompressType);
}
if (refreshConfig)ResourcesPathEditor.CreateResourcePathConfig();
Debug.LogFormat("标记游戏完成!");
}
catch (Exception e)
{
Debug.LogErrorFormat("MarkGameError:{0}", e);
}
}
///
/// 获取流媒体目录
///
///
///
public static string GetStreamingAssetPath(BuildTarget target) {
string floder = "Other";
switch (target)
{
case BuildTarget.Android:
floder = "Android";
break;
case BuildTarget.iOS:
floder = "IOS";
break;
case BuildTarget.StandaloneWindows:
floder = "Windows";
break;
case BuildTarget.StandaloneWindows64:
floder = "Windows";
break;
}
return Application.streamingAssetsPath + "/" + floder;
}
}
}