feat(gameplay): 更新单位属性和材质配置 - 调整多个单位的基础生命值和攻击力数值平衡 - 修改CoreBattleGround材质的纹理缩放比例 - 更新地砖材质颜色为白色 - 优化纹理资源设置,调整最大纹理尺寸并添加PlayableAds平台支持 - 修复弓箭手技能目标查找逻辑,改用统一的敌人检测方法 - 为水晶矿添加中立阵营设置和光球视觉效果同步 - 调整预制体中的全局缩放参数 - 为狼人和石巨人添加NavMeshAgent组件支持 - 优化水晶矿血条显示位置计算方式 ```
143 lines
5.2 KiB
C#
143 lines
5.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Security.Cryptography;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace UnityTcp.Editor.Helpers
|
|
{
|
|
/// <summary>
|
|
/// Prompt to restart Unity after the Bridge native plugin changes.
|
|
/// Pending lives in SessionState so a domain reload still shows the dialog.
|
|
/// </summary>
|
|
[InitializeOnLoad]
|
|
internal static class BridgeUpdateRestartPrompt
|
|
{
|
|
internal const string PendingKey = "UnityTcp.BridgeRestartPending";
|
|
internal const string LastDllHashKey = "UnityTcp.BridgeLastNativeDllHash";
|
|
private const string PromptedKey = "UnityTcp.BridgeRestartPrompted";
|
|
|
|
internal const string DialogTitle = "Codely Bridge Updated";
|
|
internal const string DialogMessage =
|
|
"The Codely Bridge package has been updated. Restart the Tuanjie Editor to load it.\n\n" +
|
|
"Codely Bridge 已更新。请重启团结编辑器以加载新版本。";
|
|
internal const string RestartButton = "Restart Now";
|
|
internal const string LaterButton = "Later";
|
|
|
|
internal static Func<string, string, string, string, bool> ShowDialog;
|
|
internal static Action RestartEditor;
|
|
internal static Func<bool> IsAutomated;
|
|
|
|
static BridgeUpdateRestartPrompt()
|
|
{
|
|
EditorApplication.delayCall += TryShowPendingPrompt;
|
|
}
|
|
|
|
internal static bool IsPending() => SessionState.GetBool(PendingKey, false);
|
|
|
|
internal static string LastKnownNativeDllHash() =>
|
|
SessionState.GetString(LastDllHashKey, null);
|
|
|
|
internal static void RememberNativeDllFromFile(string path)
|
|
{
|
|
string hash = TryHashFile(path);
|
|
if (string.IsNullOrEmpty(hash)) return;
|
|
SessionState.SetString(LastDllHashKey, hash);
|
|
}
|
|
|
|
/// <summary>
|
|
/// True when the incoming native plugin bytes differ from the
|
|
/// currently loaded plugin (or, if nothing is remembered yet, from
|
|
/// the changedFrom file). Missing changedFrom / unreadable files
|
|
/// are not an update.
|
|
/// </summary>
|
|
internal static bool IsNativeDllContentChanged(string fromDllPath, string toDllPath)
|
|
{
|
|
if (string.IsNullOrEmpty(fromDllPath) || string.IsNullOrEmpty(toDllPath))
|
|
return false;
|
|
|
|
string toHash = TryHashFile(toDllPath);
|
|
if (string.IsNullOrEmpty(toHash))
|
|
return false;
|
|
|
|
string known = LastKnownNativeDllHash();
|
|
if (!string.IsNullOrEmpty(known))
|
|
return known != toHash;
|
|
|
|
string fromHash = TryHashFile(fromDllPath);
|
|
if (string.IsNullOrEmpty(fromHash))
|
|
return false;
|
|
return fromHash != toHash;
|
|
}
|
|
|
|
internal static void MarkUpdated()
|
|
{
|
|
SessionState.SetBool(PendingKey, true);
|
|
SessionState.SetBool(PromptedKey, false);
|
|
}
|
|
|
|
internal static void TryShowPendingPrompt()
|
|
{
|
|
if (ShowDialog == null &&
|
|
(EditorApplication.isCompiling || EditorApplication.isUpdating))
|
|
{
|
|
EditorApplication.delayCall += TryShowPendingPrompt;
|
|
return;
|
|
}
|
|
|
|
bool automated = (IsAutomated ?? EditorAutomationGuard.IsAutomatedEditorRun)();
|
|
if (automated || !IsPending() || SessionState.GetBool(PromptedKey, false))
|
|
return;
|
|
|
|
SessionState.SetBool(PromptedKey, true);
|
|
SessionState.SetBool(PendingKey, false);
|
|
|
|
var show = ShowDialog ?? DefaultShowDialog;
|
|
if (show(DialogTitle, DialogMessage, RestartButton, LaterButton))
|
|
(RestartEditor ?? DefaultRestartEditor)();
|
|
}
|
|
|
|
internal static void ResetForTests()
|
|
{
|
|
SessionState.EraseBool(PendingKey);
|
|
SessionState.EraseBool(PromptedKey);
|
|
SessionState.EraseString(LastDllHashKey);
|
|
ShowDialog = null;
|
|
RestartEditor = null;
|
|
IsAutomated = null;
|
|
}
|
|
|
|
private static string TryHashFile(string path)
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrEmpty(path) || !File.Exists(path))
|
|
return null;
|
|
using (var md5 = MD5.Create())
|
|
using (var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
{
|
|
byte[] hash = md5.ComputeHash(stream);
|
|
return BitConverter.ToString(hash).Replace("-", "");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
CodelyLogger.LogWarning(
|
|
$"BridgeUpdateRestartPrompt: failed to hash '{path}': {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static bool DefaultShowDialog(string title, string message, string ok, string cancel)
|
|
=> EditorUtility.DisplayDialog(title, message, ok, cancel);
|
|
|
|
private static void DefaultRestartEditor()
|
|
{
|
|
string projectPath = Path.GetDirectoryName(Application.dataPath);
|
|
if (string.IsNullOrEmpty(projectPath))
|
|
projectPath = Directory.GetCurrentDirectory();
|
|
EditorApplication.OpenProject(projectPath);
|
|
}
|
|
}
|
|
}
|