maint: hotreload updated to 1.13.7

This commit is contained in:
Chris
2026-01-06 22:42:15 -05:00
parent 796dbca5d8
commit 105da8850a
128 changed files with 3538 additions and 738 deletions

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Collections;
using UnityEngine;
@@ -52,4 +51,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Collections.Generic;
using System.IO;
@@ -86,6 +85,11 @@ namespace SingularityGroup.HotReload {
/// </summary>
public string buildMachineRequestOrigin;
/// <summary>
/// Used to define which language the package is translated to
/// </summary>
public string locale;
[JsonIgnore]
public HashSet<string> DefineSymbolsAsHashSet {
get {
@@ -168,4 +172,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Collections.Generic;
using System.Reflection;
@@ -38,4 +37,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,5 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -10,6 +8,7 @@ using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using SingularityGroup.HotReload.DTO;
using SingularityGroup.HotReload.Localization;
using JetBrains.Annotations;
using SingularityGroup.HotReload.Burst;
using SingularityGroup.HotReload.HarmonyLib;
@@ -33,16 +32,17 @@ namespace SingularityGroup.HotReload {
public List<SField> addedFields = new List<SField>();
public readonly List<SMethod> patchedSMethods = new List<SMethod>();
public bool inspectorModified;
public bool inspectorFieldAdded;
public readonly List<Tuple<SMethod, string>> patchFailures = new List<Tuple<SMethod, string>>();
public readonly List<string> patchExceptions = new List<string>();
}
class FieldHandler {
public readonly Action<Type, FieldInfo> storeField;
public readonly Func<Type, FieldInfo, bool> storeField;
public readonly Action<Type, FieldInfo, FieldInfo> registerInspectorFieldAttributes;
public readonly Func<Type, string, bool> hideField;
public FieldHandler(Action<Type, FieldInfo> storeField, Func<Type, string, bool> hideField, Action<Type, FieldInfo, FieldInfo> registerInspectorFieldAttributes) {
public FieldHandler(Func<Type, FieldInfo, bool> storeField, Func<Type, string, bool> hideField, Action<Type, FieldInfo, FieldInfo> registerInspectorFieldAttributes) {
this.storeField = storeField;
this.hideField = hideField;
this.registerInspectorFieldAttributes = registerInspectorFieldAttributes;
@@ -79,7 +79,7 @@ namespace SingularityGroup.HotReload {
try {
LoadPatches(PersistencePath);
} catch(Exception ex) {
Log.Error("Encountered exception when loading patches from disk:\n{0}", ex);
Log.Error($"{Localization.Translations.Logging.LoadingPatchesFromDiskError}\n{ex}");
}
}
}
@@ -91,12 +91,12 @@ namespace SingularityGroup.HotReload {
void LoadPatches(string filePath) {
PlayerLog("Loading patches from file {0}", filePath);
PlayerLog(Localization.Translations.Logging.LoadingPatchesFromFile, filePath);
var file = new FileInfo(filePath);
if(file.Exists) {
var bytes = File.ReadAllText(filePath);
var patches = JsonConvert.DeserializeObject<List<MethodPatchResponse>>(bytes);
PlayerLog("Loaded {0} patches from disk", patches.Count.ToString());
PlayerLog(Localization.Translations.Logging.LoadedPatchesFromDisk, patches.Count.ToString());
foreach (var patch in patches) {
RegisterPatches(patch, persist: false);
}
@@ -114,13 +114,13 @@ namespace SingularityGroup.HotReload {
}
internal RegisterPatchesResult RegisterPatches(MethodPatchResponse patches, bool persist) {
PlayerLog("Register patches.\nWarnings: {0} \nMethods:\n{1}", string.Join("\n", patches.failures), string.Join("\n", patches.patches.SelectMany(p => p.modifiedMethods).Select(m => m.displayName)));
PlayerLog(Localization.Translations.Logging.RegisterPatches, string.Join("\n", patches.failures), string.Join("\n", patches.patches.SelectMany(p => p.modifiedMethods).Select(m => m.displayName)));
pendingPatches.Add(patches);
return ApplyPatches(persist);
}
RegisterPatchesResult ApplyPatches(bool persist) {
PlayerLog("ApplyPatches. {0} patches pending.", pendingPatches.Count);
PlayerLog(Localization.Translations.Logging.ApplyPatchesPending, pendingPatches.Count);
EnsureSymbolResolver();
var result = new RegisterPatchesResult();
@@ -161,7 +161,7 @@ namespace SingularityGroup.HotReload {
Dispatch.OnHotReload(result.patchedMethods).Forget();
}
} catch(Exception ex) {
Log.Warning("Exception occured when handling method patch. Exception:\n{0}", ex);
Log.Warning($"{Localization.Translations.Logging.ExceptionHandlingMethodPatch}\n{ex}");
} finally {
pendingPatches.Clear();
}
@@ -185,7 +185,7 @@ namespace SingularityGroup.HotReload {
if (didLog || !UnityEventHelper.UnityMethodsAdded()) {
return;
}
Log.Warning("A new Scene was loaded while new unity event methods were added at runtime. MonoBehaviours in the Scene will not trigger these new events.");
Log.Warning(Localization.Translations.Logging.SceneLoadedWithNewUnityEventMethods);
didLog = true;
};
}
@@ -200,7 +200,7 @@ namespace SingularityGroup.HotReload {
try {
UnityEventHelper.EnsureUnityEventMethod(newMethod);
} catch(Exception ex) {
Log.Warning("Encountered exception in EnsureUnityEventMethod: {0} {1}", ex.GetType().Name, ex.Message);
Log.Warning(Localization.Translations.Logging.ExceptionEnsureUnityEventMethod, ex.GetType().Name, ex.Message);
}
MethodUtils.DisableVisibilityChecks(newMethod);
if (!patch.patchMethods.Any(m => m.metadataToken == sMethod.metadataToken)) {
@@ -231,7 +231,7 @@ namespace SingularityGroup.HotReload {
{ StatKey.PatchId, patch.patchId },
{ StatKey.Detailed_Exception, ex.ToString() },
}).Forget();
result.patchExceptions.Add($"Edit requires full recompile to apply: Encountered exception when applying a patch.\nCommon causes: editing code that failed to patch previously, an unsupported change, or a real bug in Hot Reload.\nIf you think this is a bug, please report the issue on Discord and include a code-snippet before/after.\nException: {ex}");
result.patchExceptions.Add($"{Localization.Translations.Logging.ExceptionApplyingPatch}\nException: {ex}");
}
}
}
@@ -247,7 +247,7 @@ namespace SingularityGroup.HotReload {
} catch (SymbolResolvingFailedException) {
// ignore, not a unity event method if can't resolve
} catch(Exception ex) {
Log.Warning("Encountered exception in RemoveUnityEventMethod: {0} {1}", ex.GetType().Name, ex.Message);
Log.Warning(Localization.Translations.Logging.ExceptionRemoveUnityEventMethod, ex.GetType().Name, ex.Message);
}
}
}
@@ -261,7 +261,7 @@ namespace SingularityGroup.HotReload {
var declaringType = SymbolResolver.Resolve(sField.declaringType);
var method = SymbolResolver.Resolve(sMethod);
if (!(method is MethodInfo initializer)) {
Log.Warning($"Failed registering initializer for field {sField.fieldName} in {sField.declaringType.typeName}. Field value might not be initialized correctly. Invalid method.");
Log.Warning(string.Format(Localization.Translations.Logging.FailedRegisteringInitializerInvalidMethod, sField.fieldName, sField.declaringType.typeName));
continue;
}
// We infer if the field is static by the number of parameters the method has
@@ -276,7 +276,7 @@ namespace SingularityGroup.HotReload {
{ StatKey.PatchId, resp.id },
{ StatKey.Detailed_Exception, e.ToString() },
}).Forget();
Log.Warning($"Failed registering initializer for field {sField.fieldName} in {sField.declaringType.typeName}. Field value might not be initialized correctly. Exception: {e.Message}");
Log.Warning(string.Format(Localization.Translations.Logging.FailedRegisteringInitializerException, sField.fieldName, sField.declaringType.typeName, e.Message));
}
}
}
@@ -292,7 +292,7 @@ namespace SingularityGroup.HotReload {
{ StatKey.PatchId, resp.id },
{ StatKey.Detailed_Exception, e.ToString() },
}).Forget();
Log.Warning($"Failed registering new field definitions for field {sField.fieldName} in {sField.declaringType.typeName}. Exception: {e.Message}");
Log.Warning(string.Format(Localization.Translations.Logging.FailedRegisteringNewFieldDefinitions, sField.fieldName, sField.declaringType.typeName, e.Message));
}
}
}
@@ -310,7 +310,7 @@ namespace SingularityGroup.HotReload {
{ StatKey.PatchId, resp.id },
{ StatKey.Detailed_Exception, e.ToString() },
}).Forget();
Log.Warning($"Failed removing initializer for field {sField.fieldName} in {sField.declaringType.typeName}. Field value might not be initialized correctly. Exception: {e.Message}");
Log.Warning(string.Format(Localization.Translations.Logging.FailedRemovingInitializer, sField.fieldName, sField.declaringType.typeName, e.Message));
}
}
}
@@ -333,7 +333,7 @@ namespace SingularityGroup.HotReload {
{ StatKey.PatchId, resp.id },
{ StatKey.Detailed_Exception, e.ToString() },
}).Forget();
Log.Warning($"Failed removing field value from {f.fieldName} in {f.declaringType.typeName}. Field value in code might not be up to date. Exception: {e.Message}");
Log.Warning(string.Format(Localization.Translations.Logging.FailedRemovingFieldValue, f.fieldName, f.declaringType.typeName, e.Message));
}
}
for (var i = 0; i < renamedReshapedFieldsFrom.Length; i++) {
@@ -356,7 +356,7 @@ namespace SingularityGroup.HotReload {
{ StatKey.PatchId, resp.id },
{ StatKey.Detailed_Exception, e.ToString() },
}).Forget();
Log.Warning($"Failed moving field value from {fromField} to {toField} in {toField.declaringType.typeName}. Field value in code might not be up to date. Exception: {e.Message}");
Log.Warning(Localization.Translations.Logging.FailedMovingFieldValue, fromField, toField, toField.declaringType.typeName, e.Message);
}
}
}
@@ -400,7 +400,7 @@ namespace SingularityGroup.HotReload {
{ StatKey.PatchId, resp.id },
{ StatKey.Detailed_Exception, e.ToString() },
}).Forget();
Log.Warning($"Failed updating field attributes of {original.fieldName} in {original.declaringType.typeName}. Updates might not reflect in the inspector. Exception: {e.Message}");
Log.Warning(string.Format(Localization.Translations.Logging.FailedUpdatingFieldAttributes, original.fieldName, original.declaringType.typeName, e.Message));
}
}
}
@@ -414,14 +414,14 @@ namespace SingularityGroup.HotReload {
try {
var declaringType = SymbolResolver.Resolve(sField.declaringType);
var field = SymbolResolver.Resolve(sField);
fieldHandler?.storeField?.Invoke(declaringType, field);
result.inspectorFieldAdded = fieldHandler?.storeField?.Invoke(declaringType, field) ?? false;
result.inspectorModified = true;
} catch (Exception e) {
RequestHelper.RequestEditorEventWithRetry(new Stat(StatSource.Client, StatLevel.Error, StatFeature.Patching, StatEventType.AddInspectorField), new EditorExtraData {
{ StatKey.PatchId, patchId },
{ StatKey.Detailed_Exception, e.ToString() },
}).Forget();
Log.Warning($"Failed adding field {sField.fieldName}:{sField.declaringType.typeName} to the inspector. Field will not be displayed. Exception: {e.Message}");
Log.Warning(string.Format(Localization.Translations.Logging.FailedAddingFieldToInspector, sField.fieldName, sField.declaringType.typeName, e.Message));
}
}
result.addedFields.AddRange(sFields);
@@ -444,7 +444,7 @@ namespace SingularityGroup.HotReload {
{ StatKey.PatchId, patchId },
{ StatKey.Detailed_Exception, e.ToString() },
}).Forget();
Log.Warning($"Failed hiding field {sField.fieldName}:{sField.declaringType.typeName} from the inspector. Exception: {e.Message}");
Log.Warning(string.Format(Localization.Translations.Logging.FailedHidingFieldFromInspector, sField.fieldName, sField.declaringType.typeName, e.Message));
}
}
if (alteredFieldHidden) {
@@ -466,22 +466,21 @@ namespace SingularityGroup.HotReload {
RequestHelper.RequestEditorEventWithRetry(new Stat(StatSource.Client, StatLevel.Error, StatFeature.Patching, StatEventType.DebuggerAttached), new EditorExtraData {
{ StatKey.PatchId, patchId },
}).Forget();
return "Patching methods is not allowed while the Debugger is attached. You can change this behavior in settings if Hot Reload is compatible with the debugger you're running.";
return Localization.Translations.Logging.DebuggerAttachedNotAllowed;
}
if (DateTime.UtcNow - start > TimeSpan.FromMilliseconds(500)) {
Log.Info("Hot Reload apply took {0}", (DateTime.UtcNow - start).TotalMilliseconds);
Log.Info(Localization.Translations.Logging.HotReloadApplyTook, (DateTime.UtcNow - start).TotalMilliseconds);
}
if(state.match == null) {
var error = "Edit requires full recompile to apply: Method mismatch: {0}, patch: {1}. \nCommon causes: editing code that failed to patch previously, an unsupported change, or a real bug in Hot Reload.\nIf you think this is a bug, please report the issue on Discord and include a code-snippet before/after.";
RequestHelper.RequestEditorEventWithRetry(new Stat(StatSource.Client, StatLevel.Error, StatFeature.Patching, StatEventType.MethodMismatch), new EditorExtraData {
{ StatKey.PatchId, patchId },
}).Forget();
return string.Format(error, sOriginalMethod.simpleName, patchMethod.Name);
return string.Format(Localization.Translations.Logging.MethodMismatch, sOriginalMethod.simpleName, patchMethod.Name);
}
PlayerLog("Detour method {0:X8} {1}, offset: {2}", sOriginalMethod.metadataToken, patchMethod.Name, state.offset);
PlayerLog(Localization.Translations.Logging.DetourMethod, sOriginalMethod.metadataToken, patchMethod.Name, state.offset);
DetourResult result;
DetourApi.DetourMethod(state.match, patchMethod, out result);
if (result.success) {
@@ -617,7 +616,7 @@ namespace SingularityGroup.HotReload {
}
string HandleMethodPatchFailure(SMethod method, Exception exception) {
return $"Edit requires full recompile to apply: Failed to apply patch for method {method.displayName} in assembly {method.assemblyName}.\nCommon causes: editing code that failed to patch previously, an unsupported change, or a real bug in Hot Reload.\nIf you think this is a bug, please report the issue on Discord and include a code-snippet before/after.\nException: {exception}";
return string.Format(Localization.Translations.Logging.FailedToApplyPatchForMethod, method.displayName, method.assemblyName, exception);
}
void EnsureSymbolResolver() {
@@ -664,12 +663,12 @@ namespace SingularityGroup.HotReload {
filePath = Path.GetFullPath(filePath);
var dir = Path.GetDirectoryName(filePath);
if(string.IsNullOrEmpty(dir)) {
throw new ArgumentException("Invalid path: " + filePath, nameof(filePath));
throw new ArgumentException(string.Format(Localization.Translations.Logging.InvalidPath, filePath), nameof(filePath));
}
Directory.CreateDirectory(dir);
var history = patchHistory.ToList();
PlayerLog("Saving {0} applied patches to {1}", history.Count, filePath);
PlayerLog(Localization.Translations.Logging.SavingAppliedPatches, history.Count, filePath);
await Task.Run(() => {
using (FileStream fs = File.Create(filePath))
@@ -717,4 +716,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -32,9 +32,9 @@ namespace SingularityGroup.HotReload.Demo {
// Update is called once per frame
void Update() {
if (Demo.I.IsServerRunning()) {
informationText.text = "Hot Reload is running";
informationText.text = Localization.Translations.Common.HotReloadIsRunning;
} else {
informationText.text = "Hot Reload is not running";
informationText.text = Localization.Translations.Common.HotReloadIsNotRunning;
}
// // 2. Editing functions in monobehaviours, normal classes or static classes

View File

@@ -34,9 +34,9 @@ namespace SingularityGroup.HotReload.Demo {
handle.Complete();
if (Demo.I.IsServerRunning()) {
informationText.text = "Hot Reload is running";
informationText.text = Localization.Translations.Common.HotReloadIsRunning;
} else {
informationText.text = "Hot Reload is not running";
informationText.text = Localization.Translations.Common.HotReloadIsNotRunning;
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.IO;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace SingularityGroup.HotReload {
internal static class HotReloadSettingsHelper {
public static UnityEngine.GameObject GetOrCreateSettingsPrefab(string prefabAssetPath) {
#if UNITY_EDITOR
var prefab = AssetDatabase.LoadAssetAtPath<UnityEngine.GameObject>(prefabAssetPath);
if (prefab == null) {
// when you use HotReload as a unitypackage, prefab is somewhere inside your assets folder
var guids = AssetDatabase.FindAssets("HotReloadPrompts t:prefab", new string[]{"Assets"});
var paths = guids.Select(guid => AssetDatabase.GUIDToAssetPath(guid));
var promptsPrefabPath = paths.FirstOrDefault(assetpath => Path.GetFileName(assetpath) == "HotReloadPrompts.prefab");
if (promptsPrefabPath != null) {
prefab = AssetDatabase.LoadAssetAtPath<UnityEngine.GameObject>(promptsPrefabPath);
}
}
if (prefab == null) {
throw new Exception(Localization.Translations.Errors.FailedPromptsPrefab);
}
return prefab;
#else
return null;
#endif
}
public static HotReloadSettingsObject GetSettingsObject(string editorAssetPath) {
#if UNITY_EDITOR
return AssetDatabase.LoadAssetAtPath<HotReloadSettingsObject>(editorAssetPath);
#else
return null;
#endif
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4bff36678f3d4a2bb24c477d28f96888
timeCreated: 1765129558

View File

@@ -1,14 +1,8 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Linq;
using JetBrains.Annotations;
using System.IO;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace SingularityGroup.HotReload {
/// <summary>
/// HotReload runtime settings. These can be changed while the app is running.
@@ -62,11 +56,7 @@ namespace SingularityGroup.HotReload {
private static HotReloadSettingsObject LoadSettings() {
HotReloadSettingsObject settings;
if (Application.isEditor) {
#if UNITY_EDITOR
settings = AssetDatabase.LoadAssetAtPath<HotReloadSettingsObject>(editorAssetPath);
#else
settings = null;
#endif
settings = HotReloadSettingsHelper.GetSettingsObject(editorAssetPath);
} else {
// load from Resources (assumes that build includes the resource)
settings = Resources.Load<HotReloadSettingsObject>(resourceName);
@@ -93,38 +83,21 @@ namespace SingularityGroup.HotReload {
// Call this during build, just to be sure the field is correct. (I had some issues with it while editing the prefab)
public void EnsurePrefabSetCorrectly() {
#if UNITY_EDITOR
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabAssetPath);
if (prefab == null) {
// when you use HotReload as a unitypackage, prefab is somewhere inside your assets folder
var guids = AssetDatabase.FindAssets("HotReloadPrompts t:prefab", new string[]{"Assets"});
var paths = guids.Select(guid => AssetDatabase.GUIDToAssetPath(guid));
var promptsPrefabPath = paths.FirstOrDefault(assetpath => Path.GetFileName(assetpath) == "HotReloadPrompts.prefab");
if (promptsPrefabPath != null) {
prefab = AssetDatabase.LoadAssetAtPath<GameObject>(promptsPrefabPath);
}
}
if (prefab == null) {
throw new Exception("Failed to find PromptsPrefab (are you using Hot Reload as a package?");
}
PromptsPrefab = prefab;
#endif
PromptsPrefab = HotReloadSettingsHelper.GetOrCreateSettingsPrefab(prefabAssetPath);
}
public void EnsurePrefabNotInBuild() {
#if UNITY_EDITOR
PromptsPrefab = null;
#endif
}
// put the stored settings here
[Header("Build Settings")]
[Tooltip("Should the Hot Reload runtime be included in development builds? HotReload is never included in release builds.")]
[Header(Localization.Translations.MenuItems.BuildSettings)]
[Tooltip(Localization.Translations.MenuItems.IncludeInBuildTooltip)]
public bool IncludeInBuild = true;
[Header("Player Settings")]
[Header(Localization.Translations.MenuItems.PlayerSettings)]
public bool AllowAndroidAppToMakeHttpRequests = false;
#region hidden
@@ -137,4 +110,3 @@ namespace SingularityGroup.HotReload {
#endregion settings
}
}
#endif

View File

@@ -1,5 +1,4 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System.Net.Http;
using System.Net.Http;
namespace SingularityGroup.HotReload {
@@ -15,5 +14,3 @@ namespace SingularityGroup.HotReload {
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload {
public interface IServerHealthCheck {
bool IsServerHealthy { get; }
@@ -8,4 +7,3 @@ namespace SingularityGroup.HotReload {
void CheckHealth();
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using UnityEngine;
using UnityEngine.UI;
@@ -24,4 +23,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
#if UNITY_ANDROID && !UNITY_EDITOR
#define MOBILE_ANDROID
#endif
@@ -61,4 +60,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -7,7 +7,7 @@ PluginImporter:
executionOrder: {}
defineConstraints:
- ENABLE_MONO
- DEVELOPMENT_BUILD
- DEVELOPMENT_BUILD || UNITY_EDITOR
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 1

View File

@@ -8,7 +8,7 @@ PluginImporter:
defineConstraints:
- ENABLE_MONO
- UNITY_2019_4_OR_NEWER
- DEVELOPMENT_BUILD
- DEVELOPMENT_BUILD || UNITY_EDITOR
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 1

View File

@@ -8,7 +8,7 @@ PluginImporter:
defineConstraints:
- ENABLE_MONO
- UNITY_2020_3_OR_NEWER
- DEVELOPMENT_BUILD
- DEVELOPMENT_BUILD || UNITY_EDITOR
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 1

View File

@@ -8,7 +8,7 @@ PluginImporter:
defineConstraints:
- ENABLE_MONO
- UNITY_2022_2_OR_NEWER
- DEVELOPMENT_BUILD
- DEVELOPMENT_BUILD || UNITY_EDITOR
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 1

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 392d4a942d5d4d26872be33e375c8d32
timeCreated: 1759652490

View File

@@ -0,0 +1,46 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload.Localization {
internal static partial class Translations {
public static class Common {
public static string UnknownException;
public static string HotReloadIsRunning;
public static string HotReloadIsNotRunning;
public static string UnableToResolveMethod;
public static string UnableToResolveType;
public static string UnableToResolveField;
public static string HotReloadUnreachable;
public static string TryingToReconnect;
public static string Disconnected;
public static string Unknown;
public static void LoadEnglish() {
UnknownException = "unknown exception";
HotReloadIsRunning = "Hot Reload is running";
HotReloadIsNotRunning = "Hot Reload is not running";
UnableToResolveMethod = "Unable to resolve method";
UnableToResolveType = "Unable to resolve type";
UnableToResolveField = "Unable to resolve field";
HotReloadUnreachable = "Hot Reload was unreachable for 5 seconds, trying to reconnect...";
TryingToReconnect = "Trying to reconnect...";
Disconnected = "Disconnected";
Unknown = "unknown";
}
public static void LoadSimplifiedChinese() {
UnknownException = "未知异常";
HotReloadIsRunning = "Hot Reload 正在运行";
HotReloadIsNotRunning = "Hot Reload 未运行";
UnableToResolveMethod = "无法解析方法";
UnableToResolveType = "无法解析类型";
UnableToResolveField = "无法解析字段";
HotReloadUnreachable = "Hot Reload 5 秒内无法访问,正在尝试重新连接...";
TryingToReconnect = "正在尝试重新连接...";
Disconnected = "已断开连接";
Unknown = "未知";
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 71c2ede153664ef48b2919d3c42da1a3
timeCreated: 1762538401

View File

@@ -0,0 +1,82 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload.Localization {
internal static partial class Translations {
public static class Dialogs {
public static string Information;
public static string ContinueButtonText;
public static string CancelButtonText;
public static string DifferentProjectSummary;
public static string DifferentProjectSuggestion;
public static string DifferentCommitSummary;
public static string DifferentCommitSuggestion;
public static string ConnectionStateConnecting;
public static string ConnectionStateHandshaking;
public static string ConnectionStateDifferencesFound;
public static string ConnectionStateConnected;
public static string ConnectionStateCancelled;
public static string Patches;
public static string IsConnected;
public static string NoWiFiNetwork;
public static string WaitForCompiling;
public static string TargetNetworkIsReachable;
public static string AutoPairEncounteredIssue;
public static string ConnectionFailed;
public static string TryingToReconnect;
public static string Disconnected;
public static string PatchesStatus;
public static void LoadEnglish() {
Information = "Information";
ContinueButtonText = "Continue";
CancelButtonText = "Cancel";
DifferentProjectSummary = "Hot Reload was started from a different project";
DifferentProjectSuggestion = "Please run Hot Reload from the matching Unity project";
DifferentCommitSummary = "Editor and current build are on different commits";
DifferentCommitSuggestion = "This can cause errors when the build was made on an old commit.";
ConnectionStateConnecting = "Connecting ...";
ConnectionStateHandshaking = "Handshaking ...";
ConnectionStateDifferencesFound = "Differences found";
ConnectionStateConnected = "Connected!";
ConnectionStateCancelled = "Cancelled";
Patches = "Patches";
IsConnected = "Is this device connected to {0}?";
NoWiFiNetwork = "WiFi";
WaitForCompiling = "Wait for compiling to finish before trying again";
TargetNetworkIsReachable = "Make sure you're on the same {0} network. Also ensure Hot Reload is running";
AutoPairEncounteredIssue = "Auto-pair encountered an issue";
ConnectionFailed = "Connection failed";
TryingToReconnect = "Trying to reconnect ...";
Disconnected = "Disconnected";
PatchesStatus = "Patches: {0} pending, {1} applied";
}
public static void LoadSimplifiedChinese() {
Information = "信息";
ContinueButtonText = "继续";
CancelButtonText = "取消";
DifferentProjectSummary = "Hot Reload 从不同的项目启动";
DifferentProjectSuggestion = "请从匹配的 Unity 项目运行 Hot Reload";
DifferentCommitSummary = "编辑器和当前构建在不同的提交上";
DifferentCommitSuggestion = "当构建是在旧的提交上进行时,这可能会导致错误。";
ConnectionStateConnecting = "正在连接 ...";
ConnectionStateHandshaking = "正在握手 ...";
ConnectionStateDifferencesFound = "发现差异";
ConnectionStateConnected = "已连接!";
ConnectionStateCancelled = "已取消";
Patches = "补丁";
IsConnected = "此设备是否已连接到 {0}";
NoWiFiNetwork = "WiFi";
WaitForCompiling = "请等待编译完成后再试";
TargetNetworkIsReachable = "请确保您在同一个 {0} 网络中。还要确保 Hot Reload 正在运行";
AutoPairEncounteredIssue = "自动配对遇到问题";
ConnectionFailed = "连接失败";
TryingToReconnect = "正在尝试重新连接 ...";
Disconnected = "已断开连接";
PatchesStatus = "补丁:{0} 待处理,{1} 已应用";
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3970cf8b2b8a47dd9d16ce5051375690
timeCreated: 1762538420

View File

@@ -0,0 +1,73 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload.Localization {
internal static partial class Translations {
public static class Errors {
public static string MethodNameMismatch;
public static string DeclaringTypeNameMismatch;
public static string IsGenericMethodDefinitionMismatch;
public static string MissingThisParameter;
public static string ThisParameterTypeMismatch;
public static string ParameterCountMismatch;
public static string ParameterTypeMismatch;
public static string ReturnTypeMismatch;
public static string GenericParameterNotGenericType;
public static string GenericParameterDidNotExist;
public static string IsPlayerWithHotReloadFalse;
public static string UnknownExceptionReadingBuildInfo;
public static string BuildInfoNotFound;
public static string FailedPromptsPrefab;
public static string HandshakeFailedInvalidBuildTarget;
public static string BuildTargetMismatch;
public static string UnableToResolveMethodInAssembly;
public static string UnableToResolveTypeInAssembly;
public static string UnableToResolveFieldInAssembly;
public static void LoadEnglish() {
MethodNameMismatch = "Method name mismatch";
DeclaringTypeNameMismatch = "Declaring type name mismatch";
IsGenericMethodDefinitionMismatch = "IsGenericMethodDefinition mismatch";
MissingThisParameter = "missing this parameter";
ThisParameterTypeMismatch = "this parameter type mismatch";
ParameterCountMismatch = "parameter count mismatch";
ParameterTypeMismatch = "parameter type mismatch";
ReturnTypeMismatch = "Return type mismatch";
GenericParameterNotGenericType = "Generic parameter did not resolve to generic type definition";
GenericParameterDidNotExist = "Generic parameter did not exist on the generic type definition";
IsPlayerWithHotReloadFalse = "IsPlayerWithHotReload() is false";
UnknownExceptionReadingBuildInfo = "Uknown exception happened when reading build info";
BuildInfoNotFound = "Uknown issue happened when reading build info.";
FailedPromptsPrefab = "Failed to find PromptsPrefab (are you using Hot Reload as a package?";
HandshakeFailedInvalidBuildTarget = "Server did not declare its current Unity activeBuildTarget in the handshake response. Will assume it is {0}.";
BuildTargetMismatch = "Your Unity project is running on {0}. You may need to switch it to {1} for Hot Reload to work.";
UnableToResolveMethodInAssembly = "Unable to resolve method {0} in assembly {1}";
UnableToResolveTypeInAssembly = "Unable to resolve type with name: {0} in assembly {1}";
UnableToResolveFieldInAssembly = "Unable to resolve field with name: {0} in assembly {1}";
}
public static void LoadSimplifiedChinese() {
MethodNameMismatch = "方法名称不匹配";
DeclaringTypeNameMismatch = "声明类型名称不匹配";
IsGenericMethodDefinitionMismatch = "IsGenericMethodDefinition 不匹配";
MissingThisParameter = "缺少 this 参数";
ThisParameterTypeMismatch = "this 参数类型不匹配";
ParameterCountMismatch = "参数数量不匹配";
ParameterTypeMismatch = "参数类型不匹配";
ReturnTypeMismatch = "返回类型不匹配";
GenericParameterNotGenericType = "泛型参数未解析为泛型类型定义";
GenericParameterDidNotExist = "泛型参数在泛型类型定义上不存在";
IsPlayerWithHotReloadFalse = "IsPlayerWithHotReload() 为 false";
UnknownExceptionReadingBuildInfo = "读取构建信息时发生未知异常";
BuildInfoNotFound = "读取构建信息时发生未知问题。";
FailedPromptsPrefab = "未能找到 PromptsPrefab您是否将 Hot Reload 作为软件包使用?";
HandshakeFailedInvalidBuildTarget = "服务器在握手响应中未声明其当前的 Unity activeBuildTarget。将假定为 {0}。";
BuildTargetMismatch = "您的 Unity 项目正在 {0} 上运行。您可能需要将其切换到 {1} 才能使 Hot Reload 工作。";
UnableToResolveMethodInAssembly = "无法在程序集 {1} 中解析方法 {0}";
UnableToResolveTypeInAssembly = "无法在程序集 {1} 中解析名称为 {0} 的类型";
UnableToResolveFieldInAssembly = "无法在程序集 {1} 中解析名称为 {0} 的字段";
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c96d2f0898524320839b84cf22fcd820
timeCreated: 1762538447

View File

@@ -0,0 +1,178 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload.Localization {
internal static partial class Translations {
public static class Logging {
// Server and Connection
public static string HotReloadUnreachableDisconnecting;
public static string RequestHandshakeToServer;
public static string ServerHealthyAfterHandshake;
// Polling Errors
public static string PollMethodPatchesFailed;
public static string PollPatchStatusFailed;
public static string PollAssetChangesFailed;
// Request Errors
public static string DeserializingResponseFailed;
public static string RequestTimeout;
// Method Invocation
public static string InvokeOnHotReloadFailed;
public static string InvokeOnHotReloadLocalFailed;
// Build and Player
public static string HotReloadNotAvailableBuildSettings;
public static string BuildInfoNotFound;
// Method Compatibility
public static string UnknownIssue;
// Patch Loading/Saving
public static string LoadingPatchesFromDiskError;
public static string LoadingPatchesFromFile;
public static string LoadedPatchesFromDisk;
public static string SavingAppliedPatches;
// Patch Registration/Application
public static string RegisterPatches;
public static string ApplyPatchesPending;
public static string DetourMethod;
// Exceptions
public static string ExceptionHandlingMethodPatch;
public static string ExceptionApplyingPatch;
public static string ExceptionEnsureUnityEventMethod;
public static string ExceptionRemoveUnityEventMethod;
public static string InvalidPath;
// Field Operations
public static string FailedRegisteringInitializerInvalidMethod;
public static string FailedRegisteringInitializerException;
public static string FailedRegisteringNewFieldDefinitions;
public static string FailedRemovingInitializer;
public static string FailedRemovingFieldValue;
public static string FailedMovingFieldValue;
public static string FailedUpdatingFieldAttributes;
public static string FailedAddingFieldToInspector;
public static string FailedHidingFieldFromInspector;
// Method Patching
public static string DebuggerAttachedNotAllowed;
public static string MethodMismatch;
public static string FailedToApplyPatchForMethod;
public static string HotReloadApplyTook;
// Unity Events
public static string SceneLoadedWithNewUnityEventMethods;
public static void LoadEnglish() {
HotReloadUnreachableDisconnecting = "Hot Reload was unreachable for {0} seconds, disconnecting";
RequestHandshakeToServer = "Request handshake to Hot Reload server with hostname: {0}";
ServerHealthyAfterHandshake = "Server is healthy after first handshake? {0}";
PollMethodPatchesFailed = "PollMethodPatches failed with code {0} {1} {2}";
PollPatchStatusFailed = "PollPatchStatus failed with code {0} {1} {2}";
PollAssetChangesFailed = "PollAssetChanges failed with code {0} {1} {2}";
DeserializingResponseFailed = "Deserializing response failed with {0}: {1}";
RequestTimeout = "Request timeout";
InvokeOnHotReloadFailed = "[InvokeOnHotReload] {0} {1} failed. Exception:\n{2}";
InvokeOnHotReloadLocalFailed = "[InvokeOnHotReloadLocal] {0} {1} failed. Exception:\n{2}";
HotReloadNotAvailableBuildSettings = "Hot Reload is not available in this build because one or more build settings were not supported.";
BuildInfoNotFound = "Build info not found";
UnknownIssue = "unknown issue";
LoadingPatchesFromDiskError = "Encountered exception when loading patches from disk:";
LoadingPatchesFromFile = "Loading patches from file {0}";
LoadedPatchesFromDisk = "Loaded {0} patches from disk";
SavingAppliedPatches = "Saving {0} applied patches to {1}";
RegisterPatches = "Register patches.\nWarnings: {0} \nMethods:\n{1}";
ApplyPatchesPending = "ApplyPatches. {0} patches pending.";
DetourMethod = "Detour method {0:X8} {1}, offset: {2}";
ExceptionHandlingMethodPatch = "Exception occured when handling method patch. Exception:";
ExceptionApplyingPatch = "Edit requires full recompile to apply: Encountered exception when applying a patch.\nCommon causes: editing code that failed to patch previously, an unsupported change, or a real bug in Hot Reload.\nIf you think this is a bug, please report the issue on Discord and include a code-snippet before/after.";
ExceptionEnsureUnityEventMethod = "Encountered exception in EnsureUnityEventMethod: {0} {1}";
ExceptionRemoveUnityEventMethod = "Encountered exception in RemoveUnityEventMethod: {0} {1}";
InvalidPath = "Invalid path: {0}";
FailedRegisteringInitializerInvalidMethod = "Failed registering initializer for field {0} in {1}. Field value might not be initialized correctly. Invalid method.";
FailedRegisteringInitializerException = "Failed registering initializer for field {0} in {1}. Field value might not be initialized correctly. Exception: {2}";
FailedRegisteringNewFieldDefinitions = "Failed registering new field definitions for field {0} in {1}. Exception: {2}";
FailedRemovingInitializer = "Failed removing initializer for field {0} in {1}. Field value might not be initialized correctly. Exception: {2}";
FailedRemovingFieldValue = "Failed removing field value from {0} in {1}. Field value in code might not be up to date. Exception: {2}";
FailedMovingFieldValue = "Failed moving field value from {0} to {1} in {2}. Field value in code might not be up to date. Exception: {3}";
FailedUpdatingFieldAttributes = "Failed updating field attributes of {0} in {1}. Updates might not reflect in the inspector. Exception: {2}";
FailedAddingFieldToInspector = "Failed adding field {0}:{1} to the inspector. Field will not be displayed. Exception: {2}";
FailedHidingFieldFromInspector = "Failed hiding field {0}:{1} from the inspector. Exception: {2}";
DebuggerAttachedNotAllowed = "Patching methods is not allowed while the Debugger is attached. You can change this behavior in settings if Hot Reload is compatible with the debugger you're running.";
MethodMismatch = "Edit requires full recompile to apply: Method mismatch: {0}, patch: {1}. \nCommon causes: editing code that failed to patch previously, an unsupported change, or a real bug in Hot Reload.\nIf you think this is a bug, please report the issue on Discord and include a code-snippet before/after.";
FailedToApplyPatchForMethod = "Edit requires full recompile to apply: Failed to apply patch for method {0} in assembly {1}.\nCommon causes: editing code that failed to patch previously, an unsupported change, or a real bug in Hot Reload.\nIf you think this is a bug, please report the issue on Discord and include a code-snippet before/after.\nException: {2}";
HotReloadApplyTook = "Hot Reload apply took {0}";
SceneLoadedWithNewUnityEventMethods = "A new Scene was loaded while new unity event methods were added at runtime. MonoBehaviours in the Scene will not trigger these new events.";
}
public static void LoadSimplifiedChinese() {
HotReloadUnreachableDisconnecting = "Hot Reload {0} 秒内无法访问,正在断开连接";
RequestHandshakeToServer = "向 Hot Reload 服务器请求握手,主机名:{0}";
ServerHealthyAfterHandshake = "第一次握手后服务器是否健康?{0}";
PollMethodPatchesFailed = "PollMethodPatches 失败,代码 {0} {1} {2}";
PollPatchStatusFailed = "PollPatchStatus 失败,代码 {0} {1} {2}";
PollAssetChangesFailed = "PollAssetChanges 失败,代码 {0} {1} {2}";
DeserializingResponseFailed = "反序列化响应失败,{0}{1}";
RequestTimeout = "请求超时";
InvokeOnHotReloadFailed = "[InvokeOnHotReload] {0} {1} 失败。异常:\n{2}";
InvokeOnHotReloadLocalFailed = "[InvokeOnHotReloadLocal] {0} {1} 失败。异常:\n{2}";
HotReloadNotAvailableBuildSettings = "由于一个或多个构建设置不受支持Hot Reload 在此构建中不可用。";
BuildInfoNotFound = "未找到构建信息";
UnknownIssue = "未知问题";
LoadingPatchesFromDiskError = "从磁盘加载补丁时遇到异常:";
LoadingPatchesFromFile = "从文件 {0} 加载补丁";
LoadedPatchesFromDisk = "从磁盘加载了 {0} 个补丁";
SavingAppliedPatches = "将 {0} 个已应用的补丁保存到 {1}";
RegisterPatches = "注册补丁。\n警告{0} \n方法\n{1}";
ApplyPatchesPending = "ApplyPatches。{0} 个补丁待处理。";
DetourMethod = "Detour 方法 {0:X8} {1},偏移量:{2}";
ExceptionHandlingMethodPatch = "处理方法补丁时发生异常。异常:";
ExceptionApplyingPatch = "编辑需要完全重新编译才能应用:应用补丁时遇到异常。\n常见原因编辑之前修补失败的代码、不支持的更改或 Hot Reload 中的真正错误。\n如果您认为这是一个错误请在 Discord 上报告问题并附上之前/之后的代码片段。";
ExceptionEnsureUnityEventMethod = "在 EnsureUnityEventMethod 中遇到异常:{0} {1}";
ExceptionRemoveUnityEventMethod = "在 RemoveUnityEventMethod 中遇到异常:{0} {1}";
InvalidPath = "无效路径:{0}";
FailedRegisteringInitializerInvalidMethod = "在 {1} 中为字段 {0} 注册初始化程序失败。字段值可能未正确初始化。方法无效。";
FailedRegisteringInitializerException = "在 {1} 中为字段 {0} 注册初始化程序失败。字段值可能未正确初始化。异常:{2}";
FailedRegisteringNewFieldDefinitions = "在 {1} 中为字段 {0} 注册新字段定义失败。异常:{2}";
FailedRemovingInitializer = "在 {1} 中为字段 {0} 删除初始化程序失败。字段值可能未正确初始化。异常:{2}";
FailedRemovingFieldValue = "从 {1} 中的 {0} 删除字段值失败。代码中的字段值可能不是最新的。异常:{2}";
FailedMovingFieldValue = "在 {2} 中将字段值从 {0} 移动到 {1} 失败。代码中的字段值可能不是最新的。异常:{3}";
FailedUpdatingFieldAttributes = "在 {1} 中更新 {0} 的字段属性失败。更新可能不会反映在检查器中。异常:{2}";
FailedAddingFieldToInspector = "将字段 {0}:{1} 添加到检查器失败。字段将不会显示。异常:{2}";
FailedHidingFieldFromInspector = "从检查器中隐藏字段 {0}:{1} 失败。异常:{2}";
DebuggerAttachedNotAllowed = "附加调试器时不允许修补方法。如果 Hot Reload 与您正在运行的调试器兼容,您可以在设置中更改此行为。";
MethodMismatch = "编辑需要完全重新编译才能应用:方法不匹配:{0},补丁:{1}。\n常见原因编辑之前修补失败的代码、不支持的更改或 Hot Reload 中的真正错误。\n如果您认为这是一个错误请在 Discord 上报告问题并附上之前/之后的代码片段。";
FailedToApplyPatchForMethod = "编辑需要完全重新编译才能应用:为程序集 {1} 中的方法 {0} 应用补丁失败。\n常见原因编辑之前修补失败的代码、不支持的更改或 Hot Reload 中的真正错误。\n如果您认为这是一个错误请在 Discord 上报告问题并附上之前/之后的代码片段。\n异常{2}";
HotReloadApplyTook = "Hot Reload 应用耗时 {0}";
SceneLoadedWithNewUnityEventMethods = "在运行时添加新的 unity 事件方法时加载了新场景。场景中的 MonoBehaviours 不会触发这些新事件。";
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bbabe74466b6cb84bb5d2e98d9779397
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload.Localization {
internal static partial class Translations {
public static class MenuItems {
public const string UIControls = PackageConst.DefaultLocale == Locale.SimplifiedChinese ? "UI 控件" : "UI controls";
public const string Information = PackageConst.DefaultLocale == Locale.SimplifiedChinese ? "信息" : "Information";
public const string Other = PackageConst.DefaultLocale == Locale.SimplifiedChinese ? "其他" : "Other";
public const string FalllbackEventSystem = PackageConst.DefaultLocale == Locale.SimplifiedChinese ? "当项目未能及早创建 EventSystem 时使用" : "Used when project does not create an EventSystem early enough";
public const string BuildSettings = PackageConst.DefaultLocale == Locale.SimplifiedChinese ? "构建设置" : "Build Settings";
public const string IncludeInBuildTooltip = PackageConst.DefaultLocale == Locale.SimplifiedChinese ? "Hot Reload 运行时是否应包含在开发版本中HotReload 永远不会包含在发布版本中。" : "Should the Hot Reload runtime be included in development builds? HotReload is never included in release builds.";
public const string PlayerSettings = PackageConst.DefaultLocale == Locale.SimplifiedChinese ? "播放器设置" : "Player Settings";
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 12be1a0b0b06402da21c46ae29d60746
timeCreated: 1762675925

View File

@@ -0,0 +1,34 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload.Localization {
internal static partial class Translations {
public static class Settings {
public static string BuildSettings;
public static string IncludeInBuildTooltip;
public static string PlayerSettings;
public static string Other;
public static string FallbackEventSystemTooltip;
public static string NoEventSystemWarning;
public static void LoadEnglish() {
BuildSettings = "Build Settings";
IncludeInBuildTooltip = "Should the Hot Reload runtime be included in development builds? HotReload is never included in release builds.";
PlayerSettings = "Player Settings";
Other = "Other";
FallbackEventSystemTooltip = "Used when project does not create an EventSystem early enough";
NoEventSystemWarning = "No EventSystem is active, enabling an EventSystem inside Hot Reload {0} prefab. A Unity EventSystem and an Input module is required for tapping buttons on the Unity UI.";
}
public static void LoadSimplifiedChinese() {
BuildSettings = "构建设置";
IncludeInBuildTooltip = "Hot Reload 运行时是否应包含在开发版本中HotReload 永远不会包含在发布版本中。";
PlayerSettings = "播放器设置";
Other = "其他";
FallbackEventSystemTooltip = "当项目未能及早创建 EventSystem 时使用";
NoEventSystemWarning = "没有活动的 EventSystem正在 Hot Reload {0} 预制件内启用 EventSystem。点击 Unity UI 上的按钮需要 Unity EventSystem 和输入模块。";
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0fe4b08bd0d64689be16dc995c89bf1a
timeCreated: 1762538464

View File

@@ -0,0 +1,51 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload.Localization {
public static class Locale {
public const string SimplifiedChinese = "zh";
public const string English = "en";
}
internal static partial class Translations {
static string loadedLocale;
static Translations() {
LoadDefaultLocalization();
}
public static void LoadDefaultLocalization() {
LoadLocalization(PackageConst.DefaultLocale);
}
static void LoadLocalization(string locale) {
if (loadedLocale == locale) {
return;
}
if (locale == Locale.SimplifiedChinese) {
LoadSimplifiedChinese();
} else {
LoadEnglish();
}
loadedLocale = locale;
}
public static void LoadEnglish() {
// Load strings from subclasses
Common.LoadEnglish();
Dialogs.LoadEnglish();
Errors.LoadEnglish();
Settings.LoadEnglish();
Logging.LoadEnglish();
Utility.LoadSimplifiedChinese();
}
static void LoadSimplifiedChinese() {
Common.LoadSimplifiedChinese();
Dialogs.LoadSimplifiedChinese();
Errors.LoadSimplifiedChinese();
Settings.LoadSimplifiedChinese();
Logging.LoadSimplifiedChinese();
Utility.LoadSimplifiedChinese();
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 25df321785e144999ae89a3396247f3d
timeCreated: 1759652512

View File

@@ -0,0 +1,45 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
namespace SingularityGroup.HotReload.Localization {
internal static partial class Translations {
public static class Utility {
public static string BuildSettings;
public static string IncludeInBuildTooltip;
public static string PlayerSettings;
public static string Other;
public static string FallbackEventSystemTooltip;
public static string NoEventSystemWarning;
public static string OnHotReloadWarning;
public static string MethodCallWarning;
public static string OnHotReloadLocalCallWarning;
public static string OnHotReloadLocalWarning;
public static void LoadEnglish() {
BuildSettings = "Build Settings";
IncludeInBuildTooltip = "Should the Hot Reload runtime be included in development builds? HotReload is never included in release builds.";
PlayerSettings = "Player Settings";
Other = "Other";
FallbackEventSystemTooltip = "Used when project does not create an EventSystem early enough";
NoEventSystemWarning = "No EventSystem is active, enabling an EventSystem inside Hot Reload {0} prefab. A Unity EventSystem and an Input module is required for tapping buttons on the Unity UI.";
OnHotReloadWarning = "failed. Make sure it has 0 parameters, or 1 parameter with type List<MethodPatch>. Exception:";
MethodCallWarning = "failed. Make sure it's a method with 0 parameters either static or defined on MonoBehaviour.";
OnHotReloadLocalCallWarning = "failed. Make sure it has 0 parameters. Exception:";
OnHotReloadLocalWarning = "failed to find method {0}. Make sure it exists within the same class.";
}
public static void LoadSimplifiedChinese() {
BuildSettings = "构建设置";
IncludeInBuildTooltip = "Hot Reload 运行时是否应包含在开发版本中HotReload 永远不会包含在发布版本中。";
PlayerSettings = "播放器设置";
Other = "其他";
FallbackEventSystemTooltip = "当项目未能及早创建 EventSystem 时使用";
NoEventSystemWarning = "没有活动的 EventSystem正在 Hot Reload {0} 预制件内启用 EventSystem。点击 Unity UI 上的按钮需要 Unity EventSystem 和输入模块。";
OnHotReloadWarning = "失败。请确保它有 0 个参数,或 1 个类型为 List<MethodPatch> 的参数。异常:";
MethodCallWarning = "失败。请确保它是一个具有 0 个参数的方法,静态或在 MonoBehaviour 上定义。";
OnHotReloadLocalCallWarning = "失败。请确保它有 0 个参数。异常:";
OnHotReloadLocalWarning = "未能找到方法 {0}。请确保它存在于同一个类中。";
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 25823cb7b37e421ca5119f326f3e1b21
timeCreated: 1762675217

View File

@@ -1,8 +1,7 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Reflection;
using SingularityGroup.HotReload.MonoMod.Utils;
using SingularityGroup.HotReload.Localization;
namespace SingularityGroup.HotReload {
static class MethodCompatiblity {
@@ -17,12 +16,12 @@ namespace SingularityGroup.HotReload {
if(!ReferenceEquals(previousMethodInfo, null) && !ReferenceEquals(patchMethodInfo, null)) {
return AreMethodInfosCompatible(previousMethodInfo, patchMethodInfo);
}
return "unknown issue";
return Localization.Translations.Logging.UnknownIssue;
}
static string AreMethodBasesCompatible(MethodBase previousMethod, MethodBase patchMethod) {
if(previousMethod.Name != patchMethod.Name) {
return "Method name mismatch";
return Localization.Translations.Errors.MethodNameMismatch;
}
//Declaring type of patch method is different from the target method but their full name (namespace + name) is equal
bool isDeclaringTypeCompatible = false;
@@ -35,11 +34,11 @@ namespace SingularityGroup.HotReload {
declaringType = declaringType.BaseType;
}
if (!isDeclaringTypeCompatible) {
return "Declaring type name mismatch";
return Localization.Translations.Errors.DeclaringTypeNameMismatch;
}
//Check in case type parameter overloads to distinguish between: void M<T>() { } <-> void M() { }
if(previousMethod.IsGenericMethodDefinition != patchMethod.IsGenericMethodDefinition) {
return "IsGenericMethodDefinition mismatch";
return Localization.Translations.Errors.IsGenericMethodDefinitionMismatch;
}
var prevParams = previousMethod.GetParameters();
@@ -62,11 +61,11 @@ namespace SingularityGroup.HotReload {
//Special case: patch method for an instance method is static and has an explicit this parameter.
//If the patch method doesn't have any parameters it is not compatible.
if(patchParams.Length == 0) {
return "missing this parameter";
return Localization.Translations.Errors.MissingThisParameter;
}
//this parameter has to be the declaring type
if(!ParamTypeMatches(patchParams[0].ParameterType, previousMethod.DeclaringType)) {
return "this parameter type mismatch";
return Localization.Translations.Errors.ThisParameterTypeMismatch;
}
//Ignore the this parameter and compare the remaining ones.
patchParamsSegment = new ArraySegment<ParameterInfo>(patchParams, 1, patchParams.Length - 1);
@@ -93,11 +92,11 @@ namespace SingularityGroup.HotReload {
static string CompareParameters(ArraySegment<ParameterInfo> x, ArraySegment<ParameterInfo> y) {
if(x.Count != y.Count) {
return "parameter count mismatch";
return Localization.Translations.Errors.ParameterCountMismatch;
}
for (var i = 0; i < x.Count; i++) {
if(x.Array[i + x.Offset].ParameterType != y.Array[i + y.Offset].ParameterType) {
return "parameter type mismatch";
return Localization.Translations.Errors.ParameterTypeMismatch;
}
}
return null;
@@ -109,8 +108,7 @@ namespace SingularityGroup.HotReload {
}
static string AreMethodInfosCompatible(MethodInfo x, MethodInfo y) {
return AreMethodBasesCompatible(x, y) ?? (x.ReturnType == y.ReturnType ? null : "Return type mismatch");
return AreMethodBasesCompatible(x, y) ?? (x.ReturnType == y.ReturnType ? null : Localization.Translations.Errors.ReturnTypeMismatch);
}
}
}
#endif

View File

@@ -1,5 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Collections.Generic;
using SingularityGroup.HotReload.DTO;
@@ -713,4 +711,3 @@ namespace SingularityGroup.HotReload.JsonConverters {
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Reflection;
@@ -32,4 +31,3 @@ namespace SingularityGroup.HotReload {
#endif
}
}
#endif

View File

@@ -1,13 +1,15 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using SingularityGroup.HotReload.Localization;
using UnityEngine;
using UnityEngine.UI;
namespace SingularityGroup.HotReload {
internal class ConnectionDialog : MonoBehaviour {
[Header("UI controls")]
[Header(Localization.Translations.MenuItems.UIControls)]
public Button buttonHide;
[Header("Information")]
[Header(Localization.Translations.MenuItems.Information)]
public Text textSummary;
public Text textSuggestion;
@@ -38,7 +40,7 @@ namespace SingularityGroup.HotReload {
}
/// <param name="summary">One of the <see cref="ConnectionSummary"/> constants</param>
public void SetSummary(string summary = ConnectionSummary.Connected) {
public void SetSummary(string summary) {
if (textSummary != null) textSummary.text = summary;
isConnected = summary == ConnectionSummary.Connected;
}
@@ -49,7 +51,7 @@ namespace SingularityGroup.HotReload {
void Update() {
textSuggestion.enabled = isConnected;
if (SyncPatchCounts()) {
textSuggestion.text = $"Patches: {pendingPatches} pending, {patchesApplied} applied";
textSuggestion.text = string.Format(Localization.Translations.Dialogs.PatchesStatus, pendingPatches, patchesApplied);
}
}
@@ -67,14 +69,14 @@ namespace SingularityGroup.HotReload {
/// Therefore, we use short and simple messages.
/// </remarks>
internal static class ConnectionSummary {
public const string Cancelled = "Cancelled";
public const string Connecting = "Connecting ...";
public const string Handshaking = "Handshaking ...";
public const string DifferencesFound = "Differences found";
public const string Connected = "Connected!";
public static string Cancelled => Localization.Translations.Dialogs.ConnectionStateCancelled;
public static string Connecting => Localization.Translations.Dialogs.ConnectionStateConnecting;
public static string Handshaking => Localization.Translations.Dialogs.ConnectionStateHandshaking;
public static string DifferencesFound => Localization.Translations.Dialogs.ConnectionStateDifferencesFound;
public static string Connected => Localization.Translations.Dialogs.ConnectionStateConnected;
// reconnecting can be shown for a long time, so a longer message is okay
public const string TryingToReconnect = "Trying to reconnect ...";
public const string Disconnected = "Disconnected";
public static string TryingToReconnect => Localization.Translations.Dialogs.TryingToReconnect;
public static string Disconnected => Localization.Translations.Dialogs.Disconnected;
}
}
#endif

View File

@@ -14,8 +14,8 @@ namespace SingularityGroup.HotReload {
public GameObject connectedPrompt;
public GameObject questionPrompt;
[Header("Other")]
[Tooltip("Used when project does not create an EventSystem early enough")]
[Header(Localization.Translations.MenuItems.Other)]
[Tooltip(Localization.Translations.MenuItems.FalllbackEventSystem)]
public GameObject fallbackEventSystem;
#region Singleton
@@ -33,7 +33,7 @@ namespace SingularityGroup.HotReload {
if (_I == null) {
// allow showing prompts in editor (for testing)
if (!Application.isEditor && !PlayerEntrypoint.IsPlayerWithHotReload()) {
throw new NotSupportedException("IsPlayerWithHotReload() is false");
throw new NotSupportedException(Localization.Translations.Errors.IsPlayerWithHotReloadFalse);
}
var go = Instantiate(HotReloadSettingsObject.I.PromptsPrefab,
new Vector3(0, 0, 0), Quaternion.identity);
@@ -134,8 +134,7 @@ namespace SingularityGroup.HotReload {
/// Scene must contain an EventSystem and StandaloneInputModule, otherwise clicking/tapping on the overlay does nothing.
private void DoEnsureEventSystem() {
if (EventSystem.current == null) {
Log.Info($"No EventSystem is active, enabling an EventSystem inside Hot Reload {name} prefab." +
" A Unity EventSystem and an Input module is required for tapping buttons on the Unity UI.");
Log.Info(string.Format(Localization.Translations.Settings.NoEventSystemWarning, name));
fallbackEventSystem.SetActive(true);
}
}

View File

@@ -1,17 +1,18 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Threading.Tasks;
using SingularityGroup.HotReload.Localization;
using UnityEngine;
using UnityEngine.UI;
namespace SingularityGroup.HotReload {
class QuestionDialog : MonoBehaviour {
[Header("Information")]
[Header(Localization.Translations.MenuItems.Information)]
public Text textSummary;
public Text textSuggestion;
[Header("UI controls")]
[Header(Localization.Translations.MenuItems.UIControls)]
public Button buttonContinue;
public Button buttonCancel;
public Button buttonMoreInfo;
@@ -50,9 +51,11 @@ namespace SingularityGroup.HotReload {
internal class Config {
public string summary;
public string suggestion;
public string continueButtonText = "Continue";
public string cancelButtonText = "Cancel";
public string moreInfoUrl = "https://hotreload.net/documentation#handling-different-commits";
public string continueButtonText = Localization.Translations.Dialogs.ContinueButtonText;
public string cancelButtonText = Localization.Translations.Dialogs.CancelButtonText;
public string moreInfoUrl = PackageConst.DefaultLocale == Locale.SimplifiedChinese ?
"https://hotreload.net/zh/documentation/on-device#处理不同的提交" :
"https://hotreload.net/documentation/on-device#handling-different-commits";
}
/// hide this dialog

View File

@@ -1,11 +1,12 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using JetBrains.Annotations;
using SingularityGroup.HotReload.Localization;
using UnityEngine;
using UnityEngine.UI;
namespace SingularityGroup.HotReload {
internal class RetryDialog : MonoBehaviour {
[Header("UI controls")]
[Header(Localization.Translations.MenuItems.UIControls)]
public Button buttonHide;
public Button buttonRetryAutoPair;
public Button buttonTroubleshoot;
@@ -52,7 +53,10 @@ namespace SingularityGroup.HotReload {
});
buttonTroubleshoot.onClick.AddListener(() => {
Application.OpenURL("https://hotreload.net/documentation#connection-issues");
var docsUrl = PackageConst.DefaultLocale == Locale.SimplifiedChinese ?
"https://hotreload.net/zh/documentation/on-device#连接问题" :
"https://hotreload.net/documentation/on-device#connection-issues" ;
Application.OpenURL(docsUrl);
});
}
@@ -73,9 +77,9 @@ namespace SingularityGroup.HotReload {
// assumes that auto-pair already tried for several seconds
// suggestions to help the user when auto-pair is failing
var networkText = Application.isMobilePlatform ? "WiFi" : "LAN/WiFi";
var noWifiNetwork = $"Is this device connected to {networkText}?";
var waitForCompiling = "Wait for compiling to finish before trying again";
var targetNetworkIsReachable = $"Make sure you're on the same {networkText} network. Also ensure Hot Reload is running";
var noWifiNetwork = string.Format(Localization.Translations.Dialogs.IsConnected, networkText);
var waitForCompiling = Localization.Translations.Dialogs.WaitForCompiling;
var targetNetworkIsReachable = string.Format(Localization.Translations.Dialogs.TargetNetworkIsReachable, networkText);
if (Application.internetReachability != NetworkReachability.ReachableViaLocalAreaNetwork) {
textSuggestion.text = noWifiNetwork;
@@ -87,7 +91,7 @@ namespace SingularityGroup.HotReload {
textSuggestion.text = targetNetworkIsReachable;
}
textSummary.text = autoConnect ? "Auto-pair encountered an issue" : "Connection failed";
textSummary.text = autoConnect ? Localization.Translations.Dialogs.AutoPairEncounteredIssue : Localization.Translations.Dialogs.ConnectionFailed;
if (enableDebugging && textForDebugging) {
textForDebugging.enabled = true;

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Runtime.InteropServices;
@@ -193,4 +192,3 @@ namespace SingularityGroup.HotReload.Interop {
RequireSecObject = 32768, // 0x00008000
}
}
#endif

View File

@@ -1,5 +1,4 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
#pragma warning disable CS0618 // obsolete warnings (stay warning-free also in newer unity versions)
#pragma warning disable CS0618 // obsolete warnings (stay warning-free also in newer unity versions)
using System;
using System.Collections.Generic;
using System.Linq;
@@ -8,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using Object = UnityEngine.Object;
using SingularityGroup.HotReload.Localization;
#if UNITY_EDITOR
using UnityEditor;
#endif
@@ -48,7 +48,7 @@ namespace SingularityGroup.HotReload {
InvokeInstanceMethodStatic(patchMethod, go);
}
} else {
Log.Warning($"[{nameof(InvokeOnHotReloadLocal)}] {patchMethod.DeclaringType?.Name} {patchMethod.Name} failed. Make sure it's a method with 0 parameters either static or defined on MonoBehaviour.");
Log.Warning($"[{nameof(InvokeOnHotReloadLocal)}] {patchMethod.DeclaringType?.Name} {patchMethod.Name} {Localization.Translations.Utility.MethodCallWarning}");
}
}
@@ -57,7 +57,7 @@ namespace SingularityGroup.HotReload {
var reloadMethod = reloadForType?.GetMethod(attrib.methodToInvoke, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (reloadMethod == null) {
Log.Warning($"[{nameof(InvokeOnHotReloadLocal)}] failed to find method {attrib.methodToInvoke}. Make sure it exists within the same class.");
Log.Warning($"[{nameof(InvokeOnHotReloadLocal)}] {string.Format(Localization.Translations.Utility.OnHotReloadLocalWarning, attrib.methodToInvoke)}");
return;
}
if (reloadMethod.IsStatic) {
@@ -67,7 +67,7 @@ namespace SingularityGroup.HotReload {
InvokeInstanceMethod(reloadMethod, go, null);
}
} else {
Log.Warning($"[{nameof(InvokeOnHotReloadLocal)}] {reloadMethod.DeclaringType?.Name} {reloadMethod.Name} failed. Make sure it's a method with 0 parameters either static or defined on MonoBehaviour.");
Log.Warning($"[{nameof(InvokeOnHotReloadLocal)}] {reloadMethod.DeclaringType?.Name} {reloadMethod.Name} {Localization.Translations.Utility.MethodCallWarning}");
}
}
@@ -154,7 +154,7 @@ namespace SingularityGroup.HotReload {
}
} catch (Exception e) {
if (m.GetParameters().Length != 0) {
Log.Warning($"[{attrName}] {m.DeclaringType?.Name} {m.Name} failed. Make sure it has 0 parameters, or 1 parameter with type List<MethodPatch>. Exception:\n{e}");
Log.Warning($"[{attrName}] {m.DeclaringType?.Name} {m.Name} {Localization.Translations.Utility.OnHotReloadWarning}\n{e}");
} else {
Log.Warning($"[{attrName}] {m.DeclaringType?.Name} {m.Name} failed. Exception\n{e}");
}
@@ -170,9 +170,9 @@ namespace SingularityGroup.HotReload {
}
} catch (Exception e) {
if (m.GetParameters().Length != 0) {
Log.Warning($"[InvokeOnHotReload] {m.DeclaringType?.Name} {m.Name} failed. Make sure it has 0 parameters, or 1 parameter with type List<MethodPatch>. Exception:\n{e}");
Log.Warning($"[InvokeOnHotReload] {m.DeclaringType?.Name} {m.Name} {Localization.Translations.Utility.OnHotReloadWarning}\n{e}");
} else {
Log.Warning($"[InvokeOnHotReload] {m.DeclaringType?.Name} {m.Name} failed. Exception:\n{e}");
Log.Warning(string.Format(Localization.Translations.Logging.InvokeOnHotReloadFailed, m.DeclaringType?.Name, m.Name, e));
}
}
}
@@ -182,13 +182,12 @@ namespace SingularityGroup.HotReload {
m.Invoke(null, new object[] { go });
} catch (Exception e) {
if (m.GetParameters().Length != 0) {
Log.Warning($"[InvokeOnHotReloadLocal] {m.DeclaringType?.Name} {m.Name} failed. Make sure it has 0 parameters. Exception:\n{e}");
Log.Warning($"[InvokeOnHotReloadLocal] {m.DeclaringType?.Name} {m.Name} {Localization.Translations.Utility.OnHotReloadLocalCallWarning}\n{e}");
} else {
Log.Warning($"[InvokeOnHotReloadLocal] {m.DeclaringType?.Name} {m.Name} failed. Exception:\n{e}");
Log.Warning(Localization.Translations.Logging.InvokeOnHotReloadLocalFailed, m.DeclaringType?.Name, m.Name, e);
}
}
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using UnityEngine;
namespace SingularityGroup.HotReload {
@@ -8,13 +7,15 @@ namespace SingularityGroup.HotReload {
public static bool IsAssetStoreBuild => true;
public const string Version = "1.13.7";
public const string Version = "1.13.13";
// Never higher than Version
// Used for the download
public const string ServerVersion = "1.13.7";
public const string ServerVersion = "1.13.11";
public const string PackageName = "com.singularitygroup.hotreload";
public const string DefaultLocale = Localization.Locale.English;
// avoids unreachable code warnings from using const
public static string DefaultLocaleField = DefaultLocale;
public const string LibraryCachePath = "Library/" + PackageName;
public const string ConfigFileName = "hot-reload-config.json";
}
}
#endif

View File

@@ -1,5 +1,4 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System;
using SingularityGroup.HotReload.Newtonsoft.Json;
using UnityEngine;
@@ -38,4 +37,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System.IO;
namespace SingularityGroup.HotReload {
@@ -12,4 +11,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,8 +1,8 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Threading;
using System.Threading.Tasks;
using SingularityGroup.HotReload.DTO;
using SingularityGroup.HotReload.Localization;
namespace SingularityGroup.HotReload {
@@ -80,14 +80,14 @@ namespace SingularityGroup.HotReload {
var secondsSinceHealthy = TimeSinceServerHealthy().TotalSeconds;
var reconnectTimeout = 30; // seconds
if (secondsSinceHealthy > 2) {
Log.Info("Hot Reload was unreachable for 5 seconds, trying to reconnect...");
Log.Info(Localization.Translations.Common.HotReloadUnreachable);
// feedback for the user so they know why patches are not applying
Prompts.SetConnectionState($"{ConnectionSummary.TryingToReconnect} {reconnectTimeout - secondsSinceHealthy:F0}s", false);
Prompts.ShowConnectionDialog();
}
if (secondsSinceHealthy > reconnectTimeout) {
// give up on the server, give user a way to connect to another
Log.Info($"Hot Reload was unreachable for {reconnectTimeout} seconds, disconnecting");
Log.Info(string.Format(Localization.Translations.Logging.HotReloadUnreachableDisconnecting, reconnectTimeout));
var disconnectedServer = RequestHelper.ServerInfo;
Disconnect().Forget();
// Let user tap button to retry connecting to the same server (maybe just need to run Hot Reload again)
@@ -114,4 +114,3 @@ namespace SingularityGroup.HotReload {
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
#if UNITY_ANDROID && !UNITY_EDITOR
#define MOBILE_ANDROID
#endif
@@ -18,6 +17,7 @@ using UnityEngine.Networking;
using UnityEngine;
using Debug = UnityEngine.Debug;
using System.IO;
using SingularityGroup.HotReload.Localization;
namespace SingularityGroup.HotReload {
// entrypoint for Unity Player builds. Not necessary in Unity Editor.
@@ -42,10 +42,11 @@ namespace SingularityGroup.HotReload {
bool onlyPrefabMissing;
if (!IsPlayerWithHotReload(out onlyPrefabMissing)) {
if (onlyPrefabMissing) {
Log.Warning("Hot Reload is not available in this build because one or more build settings were not supported.");
Log.Warning(Localization.Translations.Logging.HotReloadNotAvailableBuildSettings);
}
return;
}
Translations.LoadDefaultLocalization();
TryAutoConnect().Forget();
}
@@ -55,14 +56,14 @@ namespace SingularityGroup.HotReload {
buildInfo = await GetBuildInfo();
} catch (Exception e) {
if (e is IOException) {
Log.Warning("Hot Reload is not available in this build because one or more build settings were not supported.");
Log.Warning(Localization.Translations.Logging.HotReloadNotAvailableBuildSettings);
} else {
Log.Error($"Uknown exception happened when reading build info\n{e.GetType().Name}: {e.Message}");
Log.Error($"{Localization.Translations.Errors.UnknownExceptionReadingBuildInfo}\n{e.GetType().Name}: {e.Message}");
}
return;
}
if (buildInfo == null) {
Log.Error($"Uknown issue happened when reading build info.");
Log.Error(Localization.Translations.Errors.BuildInfoNotFound);
return;
}
@@ -92,7 +93,7 @@ namespace SingularityGroup.HotReload {
public static Task TryConnectToIpAndPort(string ip, int port) {
ip = ip.Trim();
if (buildInfo == null) {
throw new ArgumentException("Build info not found");
throw new ArgumentException(Localization.Translations.Logging.BuildInfoNotFound);
}
buildInfo.buildMachineHostName = ip;
buildInfo.buildMachinePort = port;
@@ -115,7 +116,7 @@ namespace SingularityGroup.HotReload {
PlayerCodePatcher.UpdateHost(null).Forget();
}
Log.Info($"Server is healthy after first handshake? {handshakeOk}");
Log.Info(string.Format(Localization.Translations.Logging.ServerHealthyAfterHandshake, handshakeOk));
}
/// on Android, streaming assets are inside apk zip, which can only be read using unity web request
@@ -158,4 +159,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,5 +1,4 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
@@ -11,6 +10,7 @@ using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using SingularityGroup.HotReload.DTO;
using SingularityGroup.HotReload.Localization;
using SingularityGroup.HotReload.Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
@@ -45,7 +45,9 @@ namespace SingularityGroup.HotReload {
static class RequestHelper {
internal const ushort defaultPort = 33242;
internal const string defaultServerHost = "127.0.0.1";
const string ChangelogURL = "https://d2tc55zjhw51ly.cloudfront.net/releases/latest/changelog.json";
const string ChangelogURL = PackageConst.DefaultLocale == Locale.SimplifiedChinese ?
"https://d2tc55zjhw51ly.cloudfront.net/releases/latest/changelog-zh.json" :
"https://d2tc55zjhw51ly.cloudfront.net/releases/latest/changelog.json";
static readonly string defaultOrigin = Path.GetDirectoryName(UnityHelper.DataPath);
public static string origin { get; private set; } = defaultOrigin;
@@ -161,7 +163,7 @@ namespace SingularityGroup.HotReload {
//Server shut down
await Task.Delay(5000);
} else {
Log.Info("PollMethodPatches failed with code {0} {1} {2}", (int)result.statusCode, result.responseText, result.exception);
Log.Info(Localization.Translations.Logging.PollMethodPatchesFailed, (int)result.statusCode, result.responseText, result.exception);
}
} finally {
pollPending = false;
@@ -189,7 +191,7 @@ namespace SingularityGroup.HotReload {
//Server shut down
await Task.Delay(5000);
} else {
Log.Info("PollPatchStatus failed with code {0} {1} {2}", (int)result.statusCode, result.responseText, result.exception);
Log.Info(Localization.Translations.Logging.PollPatchStatusFailed, (int)result.statusCode, result.responseText, result.exception);
}
} finally {
pollPatchStatusPending = false;
@@ -229,7 +231,7 @@ namespace SingularityGroup.HotReload {
//Server shut down
await Task.Delay(5000);
} else {
Log.Info("PollAssetChanges failed with code {0} {1} {2}", (int)result.statusCode, result.responseText, result.exception);
Log.Info(Localization.Translations.Logging.PollAssetChangesFailed, (int)result.statusCode, result.responseText, result.exception);
}
} finally {
assetPollPending = false;
@@ -249,6 +251,19 @@ namespace SingularityGroup.HotReload {
return null;
}
public static async Task<EditorsWithoutHRResponse> RequestEditorsWithoutHRRunning(int timeoutSeconds = 30) {
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds));
var resp = await PostJson(CreateUrl(serverInfo) + "/editorsWithoutHR", "", timeoutSeconds, cts.Token);
if (resp.statusCode == HttpStatusCode.OK) {
try {
return JsonConvert.DeserializeObject<EditorsWithoutHRResponse>(resp.responseText);
} catch {
return null;
}
}
return null;
}
public static async Task<LoginStatusResponse> RequestLogin(string email, string password, int timeoutSeconds) {
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds));
var json = SerializeRequestBody(new Dictionary<string, object> {
@@ -280,10 +295,10 @@ namespace SingularityGroup.HotReload {
try {
return JsonConvert.DeserializeObject<LoginStatusResponse>(resp.responseText);
} catch (Exception ex) {
return LoginStatusResponse.FromRequestError($"Deserializing response failed with {ex.GetType().Name}: {ex.Message}");
return LoginStatusResponse.FromRequestError(string.Format(Localization.Translations.Logging.DeserializingResponseFailed, ex.GetType().Name, ex.Message));
}
} else {
return LoginStatusResponse.FromRequestError(resp.responseText ?? "Request timeout");
return LoginStatusResponse.FromRequestError(resp.responseText ?? Localization.Translations.Logging.RequestTimeout);
}
}
@@ -442,4 +457,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,8 +1,8 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using SingularityGroup.HotReload.Localization;
namespace SingularityGroup.HotReload {
internal class ServerHandshake {
@@ -97,8 +97,8 @@ namespace SingularityGroup.HotReload {
// handle objections in order of obviousness, most obvious goes first
if (results.HasFlag(Result.DifferentProject)) {
await Prompts.ShowQuestionDialog(new QuestionDialog.Config {
summary = "Hot Reload was started from a different project",
suggestion = "Please run Hot Reload from the matching Unity project",
summary = Localization.Translations.Dialogs.DifferentProjectSummary,
suggestion = Localization.Translations.Dialogs.DifferentProjectSuggestion,
continueButtonText = "OK",
cancelButtonText = null,
});
@@ -109,8 +109,8 @@ namespace SingularityGroup.HotReload {
if (results.HasFlag(Result.DifferentCommit)) {
Prompts.SetConnectionState(ConnectionSummary.DifferencesFound);
bool yes = await Prompts.ShowQuestionDialog(new QuestionDialog.Config {
summary = "Editor and current build are on different commits",
suggestion = "This can cause errors when the build was made on an old commit.",
summary = Localization.Translations.Dialogs.DifferentCommitSummary,
suggestion = Localization.Translations.Dialogs.DifferentCommitSuggestion,
continueButtonText = "Connect",
});
if (yes) {
@@ -188,7 +188,7 @@ namespace SingularityGroup.HotReload {
Log.Debug("Won't send handshake request because server is not healhy");
return results;
}
Log.Info("Request handshake to Hot Reload server with hostname: {0}", info.hostName);
Log.Info(string.Format(Localization.Translations.Logging.RequestHandshakeToServer, info.hostName));
//Log.Debug("Handshake with projectOmissionRegex: \"{0}\"", buildInfo.projectOmissionRegex);
var response = await RequestHelper.RequestHandshake(info, buildInfo.DefineSymbolsAsHashSet,
buildInfo.projectOmissionRegex);
@@ -228,10 +228,10 @@ namespace SingularityGroup.HotReload {
if (remoteBuildTarget == null) {
// Should never happen. Server responsed with an error when no BuildInfo at all.
Log.Warning("Server did not declare its current Unity activeBuildTarget in the handshake response. Will assume it is {0}.", buildInfo.activeBuildTarget);
Log.Warning(string.Format(Localization.Translations.Errors.HandshakeFailedInvalidBuildTarget, buildInfo.activeBuildTarget));
results |= Result.QuietWarning;
} else if (remoteBuildTarget != buildInfo.activeBuildTarget) {
Log.Warning("Your Unity project is running on {0}. You may need to switch it to {1} for Hot Reload to work.", remoteBuildTarget, buildInfo.activeBuildTarget);
Log.Warning(string.Format(Localization.Translations.Errors.BuildTargetMismatch, remoteBuildTarget, buildInfo.activeBuildTarget));
results |= Result.QuietWarning;
}
@@ -242,4 +242,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Threading.Tasks;
@@ -55,4 +54,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -21,7 +21,8 @@
],
"autoReferenced": false,
"defineConstraints": [
"ENABLE_MONO"
"ENABLE_MONO",
"DEVELOPMENT_BUILD || UNITY_EDITOR"
],
"versionDefines": [],
"noEngineReferences": false

View File

@@ -1,10 +1,9 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Collections.Generic;
using System.Reflection;
using SingularityGroup.HotReload.DTO;
using SingularityGroup.HotReload.RuntimeDependencies;
using SingularityGroup.HotReload.Localization;
namespace SingularityGroup.HotReload {
internal class SymbolResolver {
@@ -32,11 +31,11 @@ namespace SingularityGroup.HotReload {
result = assmeblies[i].GetLoadedModules()[0].ResolveType(t.metadataToken);
if (t.isGenericParameter) {
if (!result.IsGenericTypeDefinition) {
throw new SymbolResolvingFailedException(t, new ApplicationException("Generic parameter did not resolve to generic type definition"));
throw new SymbolResolvingFailedException(t, new ApplicationException(Localization.Translations.Errors.GenericParameterNotGenericType));
}
var genericParameters = result.GetGenericArguments();
if (t.genericParameterPosition >= genericParameters.Length) {
throw new SymbolResolvingFailedException(t, new ApplicationException("Generic parameter did not exist on the generic type definition"));
throw new SymbolResolvingFailedException(t, new ApplicationException(Localization.Translations.Errors.GenericParameterDidNotExist));
}
result = genericParameters[t.genericParameterPosition];
}
@@ -96,4 +95,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,17 +1,16 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using SingularityGroup.HotReload.DTO;
using SingularityGroup.HotReload.Localization;
namespace SingularityGroup.HotReload {
internal class SymbolResolvingFailedException : Exception {
public SymbolResolvingFailedException(SMethod m, Exception inner)
: base($"Unable to resolve method {m.displayName} in assembly {m.assemblyName}", inner) { }
: base(string.Format(Localization.Translations.Errors.UnableToResolveMethodInAssembly, m.displayName, m.assemblyName), inner) { }
public SymbolResolvingFailedException(SType t, Exception inner)
: base($"Unable to resolve type with name: {t.typeName} in assembly {t.assemblyName}", inner) { }
: base(string.Format(Localization.Translations.Errors.UnableToResolveTypeInAssembly, t.typeName, t.assemblyName), inner) { }
public SymbolResolvingFailedException(SField t, Exception inner)
: base($"Unable to resolve field with name: {t.fieldName} in assembly {t.assemblyName}", inner) { }
: base(string.Format(Localization.Translations.Errors.UnableToResolveFieldInAssembly, t.fieldName, t.assemblyName), inner) { }
}
}
#endif

View File

@@ -1,8 +1,8 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using SingularityGroup.HotReload.Localization;
namespace SingularityGroup.HotReload {
internal static class TaskExtensions {
@@ -10,7 +10,7 @@ namespace SingularityGroup.HotReload {
try {
await task;
if(task.IsFaulted) {
throw task.Exception ?? new Exception("unknown exception " + task);
throw task.Exception ?? new Exception(Localization.Translations.Common.UnknownException + " " + task);
}
token.ThrowIfCancellationRequested();
}
@@ -45,4 +45,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,5 +1,4 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using System;
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using UnityEngine;
@@ -223,4 +222,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif

View File

@@ -1,4 +1,3 @@
#if ENABLE_MONO && (DEVELOPMENT_BUILD || UNITY_EDITOR)
using UnityEngine;
namespace SingularityGroup.HotReload {
@@ -39,4 +38,3 @@ namespace SingularityGroup.HotReload {
}
}
}
#endif