diff --git a/AxibugEmuOnline.Client/Assets/Resources/Icons/conflict.png b/AxibugEmuOnline.Client/Assets/Resources/Icons/conflict.png new file mode 100644 index 00000000..ddac9c54 Binary files /dev/null and b/AxibugEmuOnline.Client/Assets/Resources/Icons/conflict.png differ diff --git a/AxibugEmuOnline.Client/Assets/Resources/Icons/conflict.png.meta b/AxibugEmuOnline.Client/Assets/Resources/Icons/conflict.png.meta new file mode 100644 index 00000000..7bf58ce5 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Resources/Icons/conflict.png.meta @@ -0,0 +1,130 @@ +fileFormatVersion: 2 +guid: 994c93ed03dadee49974aebf3cb5365d +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Resources/Icons/disconnect.png b/AxibugEmuOnline.Client/Assets/Resources/Icons/disconnect.png new file mode 100644 index 00000000..f92db37c Binary files /dev/null and b/AxibugEmuOnline.Client/Assets/Resources/Icons/disconnect.png differ diff --git a/AxibugEmuOnline.Client/Assets/Resources/Icons/disconnect.png.meta b/AxibugEmuOnline.Client/Assets/Resources/Icons/disconnect.png.meta new file mode 100644 index 00000000..9f97d6fe --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Resources/Icons/disconnect.png.meta @@ -0,0 +1,130 @@ +fileFormatVersion: 2 +guid: 630c435b903e3dc4e80038c0a531162d +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Resources/Icons/sync.png b/AxibugEmuOnline.Client/Assets/Resources/Icons/sync.png new file mode 100644 index 00000000..0249e5ca Binary files /dev/null and b/AxibugEmuOnline.Client/Assets/Resources/Icons/sync.png differ diff --git a/AxibugEmuOnline.Client/Assets/Resources/Icons/sync.png.meta b/AxibugEmuOnline.Client/Assets/Resources/Icons/sync.png.meta new file mode 100644 index 00000000..6d0ef801 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Resources/Icons/sync.png.meta @@ -0,0 +1,130 @@ +fileFormatVersion: 2 +guid: c5a9535bb63e1f14f9a1528566864ab2 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Resources/Icons/synced.png b/AxibugEmuOnline.Client/Assets/Resources/Icons/synced.png new file mode 100644 index 00000000..d6690b06 Binary files /dev/null and b/AxibugEmuOnline.Client/Assets/Resources/Icons/synced.png differ diff --git a/AxibugEmuOnline.Client/Assets/Resources/Icons/synced.png.meta b/AxibugEmuOnline.Client/Assets/Resources/Icons/synced.png.meta new file mode 100644 index 00000000..b9281df5 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Resources/Icons/synced.png.meta @@ -0,0 +1,130 @@ +fileFormatVersion: 2 +guid: 28db37d78cad20f4397804dfa4572829 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Resources/NES/NesEmulator.prefab b/AxibugEmuOnline.Client/Assets/Resources/NES/NesEmulator.prefab index d539bc20..ed720f00 100644 --- a/AxibugEmuOnline.Client/Assets/Resources/NES/NesEmulator.prefab +++ b/AxibugEmuOnline.Client/Assets/Resources/NES/NesEmulator.prefab @@ -551,13 +551,13 @@ RectTransform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4232056521759880276} - m_LocalRotation: {x: 1, y: 0, z: 0, w: 0} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalScale: {x: 1, y: -1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4232056520494431727} - m_LocalEulerAnglesHint: {x: 180, y: 0, z: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} diff --git a/AxibugEmuOnline.Client/Assets/Resources/UIPrefabs/OptionUI.prefab b/AxibugEmuOnline.Client/Assets/Resources/UIPrefabs/OptionUI.prefab index 120a9d77..94f5a72d 100644 --- a/AxibugEmuOnline.Client/Assets/Resources/UIPrefabs/OptionUI.prefab +++ b/AxibugEmuOnline.Client/Assets/Resources/UIPrefabs/OptionUI.prefab @@ -1688,7 +1688,7 @@ RectTransform: m_GameObject: {fileID: 5162569472849600096} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: -1, z: 1} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5970282275929291192} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs index 92ea219c..fba7703f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs @@ -63,6 +63,12 @@ namespace AxibugEmuOnline.Client.ClientCore { return s_persistentRoot + "/" + emuPlatform.ToString(); } + + public static string UserPersistenDataPath(RomPlatformType emuPlatform) + { + return string.Format("{0}/{1}", PersistentDataPath(emuPlatform), user.userdata.UID); + } + public static string PersistentDataRoot() => s_persistentRoot; public static RomLib GetRomLib(RomPlatformType platform) diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFile.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFile.cs index d0077d9d..30882e71 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFile.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFile.cs @@ -1,14 +1,15 @@ using AxibugEmuOnline.Client.ClientCore; using AxibugEmuOnline.Client.Tools; using AxibugProtobuf; +using MAME.Core; using System; using System.IO; using System.Runtime.InteropServices; namespace AxibugEmuOnline.Client { - /// 存档文件管理类 - public class SaveFile + /// 存档文件抽象类 + public partial class SaveFile { public SavCloudApi CloudAPI => App.SavMgr.CloudApi; @@ -28,8 +29,8 @@ namespace AxibugEmuOnline.Client { get { - var path = App.PersistentDataPath(EmuPlatform); - path = $"{path}/Slot/{EmuPlatform}/{RomID}"; + var path = App.UserPersistenDataPath(EmuPlatform); + path = $"{path}/Slot/{RomID}"; Directory.CreateDirectory(path); @@ -38,7 +39,24 @@ namespace AxibugEmuOnline.Client } } + public bool IsBusy + { + get + { + if (FSM.CurrentState is DownloadingState) return true; + else if (FSM.CurrentState is UploadingState) return true; + + return false; + } + } + + public SimpleFSM.State GetState() + { + return FSM.CurrentState; + } + public event Action OnSavSuccessed; + public event Action OnStateChanged; /// 存档顺序号,用于判断云存档和本地存档的同步状态,是否存在冲突 public uint Sequecen { get; private set; } @@ -55,11 +73,12 @@ namespace AxibugEmuOnline.Client EmuPlatform = platform; SlotIndex = slotIndex; FSM = new SimpleFSM(this); - FSM.AddState(); + FSM.AddState(); FSM.AddState(); FSM.AddState(); FSM.AddState(); FSM.AddState(); + FSM.OnStateChanged += FSM_OnStateChanged; IsEmpty = !File.Exists(FilePath); @@ -82,7 +101,12 @@ namespace AxibugEmuOnline.Client streaming.Dispose(); } - FSM.ChangeState(); + FSM.ChangeState(); + } + + private void FSM_OnStateChanged() + { + OnStateChanged?.Invoke(); } public void Update() @@ -145,6 +169,8 @@ namespace AxibugEmuOnline.Client public unsafe void Save(uint sequence, byte[] savData, byte[] screenShotData) { + if (IsBusy) return; + var filePath = FilePath; var header = new Header @@ -190,9 +216,9 @@ namespace AxibugEmuOnline.Client /// public void TrySync() { - if (FSM.CurrentState is not UnkownState && FSM.CurrentState is not SyncedState) return; + if (FSM.CurrentState is not IdleState && FSM.CurrentState is not SyncedState) return; - FSM.ChangeState(); + FSM.ChangeState(); } @@ -210,14 +236,5 @@ namespace AxibugEmuOnline.Client [FieldOffset(20)] public uint ScreenShotLength; } - - public enum EnumState - { - Unkown, - Checking, - Downloading, - Uploading, - Synced - } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingNetworkState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingNetworkState.cs new file mode 100644 index 00000000..70f95926 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingNetworkState.cs @@ -0,0 +1,21 @@ +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Tools; +using System; + +namespace AxibugEmuOnline.Client +{ + public partial class SaveFile + { + + public class CheckingNetworkState : SimpleFSM.State + { + public override void OnUpdate() + { + if (App.network.isConnected) + { + FSM.ChangeState(); + } + } + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingNetworkState.cs.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingNetworkState.cs.meta new file mode 100644 index 00000000..91f6544a --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingNetworkState.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 288e73ce3cb773e46b7d37a53a3b43ee \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingState.cs index 2dbf54a7..5ae92843 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingState.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/CheckingState.cs @@ -4,45 +4,48 @@ using UnityEngine; namespace AxibugEmuOnline.Client { - public class CheckingState : SimpleFSM.State + public partial class SaveFile { - private float m_timeOut; - - public Protobuf_Mine_GameSavInfo NetData { get; private set; } - - public override void OnEnter(SimpleFSM.State preState) + public class CheckingState : SimpleFSM.State { - m_timeOut = 5f; - Host.CloudAPI.OnFetchGameSavList += CloudAPI_OnFetchGameSavList; - Host.CloudAPI.SendGetGameSavList(Host.RomID); - } + private float m_timeOut; - public override void OnExit(SimpleFSM.State nextState) - { - Host.CloudAPI.OnFetchGameSavList -= CloudAPI_OnFetchGameSavList; - } + public Protobuf_Mine_GameSavInfo NetData { get; private set; } - public override void OnUpdate() - { - m_timeOut -= Time.deltaTime; - if (m_timeOut < 0) //已超时 + public override void OnEnter(SimpleFSM.State preState) { - FSM.ChangeState(); + m_timeOut = 5f; + Host.CloudAPI.OnFetchGameSavList += CloudAPI_OnFetchGameSavList; + Host.CloudAPI.SendGetGameSavList(Host.RomID); } - } - private void CloudAPI_OnFetchGameSavList(int romID, Protobuf_Mine_GameSavInfo[] savSlotData) - { - if (romID != Host.RomID) return; - NetData = savSlotData[Host.SlotIndex]; - - if (NetData == null) //云存档不存在,上传本地存档 + public override void OnExit(SimpleFSM.State nextState) { - FSM.ChangeState(); + Host.CloudAPI.OnFetchGameSavList -= CloudAPI_OnFetchGameSavList; } - else + + public override void OnUpdate() { - FSM.ChangeState(); + m_timeOut -= Time.deltaTime; + if (m_timeOut < 0) //已超时 + { + FSM.ChangeState(); + } + } + + private void CloudAPI_OnFetchGameSavList(int romID, Protobuf_Mine_GameSavInfo[] savSlotData) + { + if (romID != Host.RomID) return; + NetData = savSlotData[Host.SlotIndex]; + + if (NetData == null) //云存档不存在,上传本地存档 + { + FSM.ChangeState(); + } + else + { + FSM.ChangeState(); + } } } } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/ConflictState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/ConflictState.cs index 5bd1b593..e35f1ee7 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/ConflictState.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/ConflictState.cs @@ -2,8 +2,11 @@ namespace AxibugEmuOnline.Client { - public class ConflictState : SimpleFSM.State + public partial class SaveFile { + public class ConflictState : SimpleFSM.State + { + } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/DownloadingState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/DownloadingState.cs index e0e9e2df..7884f129 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/DownloadingState.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/DownloadingState.cs @@ -3,51 +3,54 @@ using AxibugEmuOnline.Client.Tools; namespace AxibugEmuOnline.Client { - public class DownloadingState : SimpleFSM.State + public partial class SaveFile { - uint m_sequece; - private AxiHttpProxy.SendDownLoadProxy m_downloadTask; - private AxiHttpProxy.SendDownLoadProxy m_downloadTaskImg; - - public override void OnEnter(SimpleFSM.State preState) + public class DownloadingState : SimpleFSM.State { - var checkState = preState as CheckingState; + uint m_sequece; + private AxiHttpProxy.SendDownLoadProxy m_downloadTask; + private AxiHttpProxy.SendDownLoadProxy m_downloadTaskImg; - var netData = checkState.NetData; - - if (Host.Sequecen >= (uint)netData.Sequence) + public override void OnEnter(SimpleFSM.State preState) { - FSM.ChangeState(); - return; + var checkState = preState as CheckingState; + + var netData = checkState.NetData; + + if (Host.Sequecen >= (uint)netData.Sequence) + { + FSM.ChangeState(); + return; + } + + m_sequece = (uint)netData.Sequence; + m_downloadTask = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{netData.SavUrl}"); + m_downloadTaskImg = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{netData.SavImgUrl}"); } - m_sequece = (uint)netData.Sequence; - m_downloadTask = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{netData.SavUrl}"); - m_downloadTaskImg = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{netData.SavImgUrl}"); - } - - public override void OnUpdate() - { - if (!m_downloadTask.downloadHandler.isDone) return; - - if (m_downloadTask.downloadHandler.bHadErr) //下载失败 + public override void OnUpdate() { - FSM.ChangeState(); - return; + if (!m_downloadTask.downloadHandler.isDone) return; + + if (m_downloadTask.downloadHandler.bHadErr) //下载失败 + { + FSM.ChangeState(); + return; + } + + if (!m_downloadTaskImg.downloadHandler.isDone) return; + + if (m_downloadTaskImg.downloadHandler.bHadErr) //下载失败 + { + FSM.ChangeState(); + return; + } + + var savData = Host.CloudAPI.UnGzipData(m_downloadTask.downloadHandler.data); + var imgData = Host.CloudAPI.UnGzipData(m_downloadTaskImg.downloadHandler.data); + Host.Save(m_sequece, savData, imgData); + FSM.ChangeState(); } - - if (!m_downloadTaskImg.downloadHandler.isDone) return; - - if (m_downloadTaskImg.downloadHandler.bHadErr) //下载失败 - { - FSM.ChangeState(); - return; - } - - var savData = Host.CloudAPI.UnGzipData(m_downloadTask.downloadHandler.data); - var imgData = Host.CloudAPI.UnGzipData(m_downloadTaskImg.downloadHandler.data); - Host.Save(m_sequece, savData, imgData); - FSM.ChangeState(); } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/IdleState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/IdleState.cs new file mode 100644 index 00000000..68e014f7 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/IdleState.cs @@ -0,0 +1,11 @@ +using AxibugEmuOnline.Client.Tools; + +namespace AxibugEmuOnline.Client +{ + public partial class SaveFile + { + public class IdleState : SimpleFSM.State + { + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UnkownState.cs.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/IdleState.cs.meta similarity index 100% rename from AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UnkownState.cs.meta rename to AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/IdleState.cs.meta diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/SyncedState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/SyncedState.cs index 00c031e9..46bb251f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/SyncedState.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/SyncedState.cs @@ -2,7 +2,10 @@ namespace AxibugEmuOnline.Client { - public class SyncedState : SimpleFSM.State + public partial class SaveFile { + public class SyncedState : SimpleFSM.State + { + } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UnkownState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UnkownState.cs deleted file mode 100644 index 81061ba4..00000000 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UnkownState.cs +++ /dev/null @@ -1,8 +0,0 @@ -using AxibugEmuOnline.Client.Tools; - -namespace AxibugEmuOnline.Client -{ - public class UnkownState : SimpleFSM.State - { - } -} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UploadingState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UploadingState.cs index da9f426b..8276411f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UploadingState.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/UploadingState.cs @@ -2,27 +2,30 @@ namespace AxibugEmuOnline.Client { - public class UploadingState : SimpleFSM.State + public partial class SaveFile { - public override void OnEnter(SimpleFSM.State preState) + public class UploadingState : SimpleFSM.State { - Host.CloudAPI.OnUploadedSavData += Api_OnUploadedSavData; + public override void OnEnter(SimpleFSM.State preState) + { + Host.CloudAPI.OnUploadedSavData += Api_OnUploadedSavData; - Host.GetSavData(out byte[] savData, out byte[] screenData); - Host.CloudAPI.SendUpLoadGameSav(Host.RomID, Host.SlotIndex, Host.Sequecen, savData, screenData); - } + Host.GetSavData(out byte[] savData, out byte[] screenData); + Host.CloudAPI.SendUpLoadGameSav(Host.RomID, Host.SlotIndex, Host.Sequecen, savData, screenData); + } - public override void OnExit(SimpleFSM.State nextState) - { - Host.CloudAPI.OnUploadedSavData -= Api_OnUploadedSavData; - } + public override void OnExit(SimpleFSM.State nextState) + { + Host.CloudAPI.OnUploadedSavData -= Api_OnUploadedSavData; + } - private void Api_OnUploadedSavData(int romID, int slotIndex, AxibugProtobuf.Protobuf_Mine_GameSavInfo savInfo) - { - if (Host.RomID != romID) return; - if (Host.SlotIndex != slotIndex) return; + private void Api_OnUploadedSavData(int romID, int slotIndex, AxibugProtobuf.Protobuf_Mine_GameSavInfo savInfo) + { + if (Host.RomID != romID) return; + if (Host.SlotIndex != slotIndex) return; - FSM.ChangeState(); + FSM.ChangeState(); + } } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SimpleSFM.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SimpleSFM.cs index 4ad5a06f..814207ee 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SimpleSFM.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SimpleSFM.cs @@ -4,10 +4,10 @@ using System.Linq; namespace AxibugEmuOnline.Client.Tools { - public class SimpleFSM + public partial class SimpleFSM { + public event Action OnStateChanged; private Dictionary m_states = new Dictionary(); - private State m_current; public HOST Host { get; private set; } @@ -16,7 +16,18 @@ namespace AxibugEmuOnline.Client.Tools Host = host; } - public State CurrentState => m_current; + private State m_current; + public State CurrentState + { + get => m_current; + set + { + if (m_current == value) return; + + m_current = value; + OnStateChanged?.Invoke(); + } + } public T AddState() where T : State, new() { var stateType = typeof(T); diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateMenu.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateMenu.cs index b20d5c56..1da77c5f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateMenu.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateMenu.cs @@ -46,6 +46,13 @@ namespace AxibugEmuOnline.Client m_subOptions.Add(new LoadMenuItem(inGameui, savFile)); } + public override void OnShow(OptionUI_MenuItem ui) + { + base.OnShow(ui); + + SavFile.TrySync(); + } + protected override List GetOptionMenus() { return m_subOptions; @@ -65,9 +72,16 @@ namespace AxibugEmuOnline.Client public override void OnExcute(OptionUI optionUI, ref bool cancelHide) { + if (m_savFile.IsBusy) + { + OverlayManager.PopTip("存档正在同步中"); + cancelHide = true; + return; + } + var stateData = m_ingameUI.Core.GetStateBytes(); var tex = m_ingameUI.Core.OutputPixel; - var screenData = tex.ToJPG(); + var screenData = tex.ToJPG(m_ingameUI.Core.DrawCanvas.transform.localScale); m_savFile.Save(m_savFile.Sequecen, stateData, screenData); } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI.cs index b52e8316..029ae216 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI.cs @@ -439,7 +439,6 @@ namespace AxibugEmuOnline.Client public abstract string Name { get; } public virtual Sprite Icon { get; } public virtual bool Visible => true; - public virtual bool Enable => true; public virtual void OnFocus() { } public virtual void OnShow(OptionUI_MenuItem ui) { } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_SavSlotItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_SavSlotItem.cs index d0fc9d20..5286eadc 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_SavSlotItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_SavSlotItem.cs @@ -1,4 +1,7 @@ -using UnityEngine; +using AxibugEmuOnline.Client.Tools; +using System; +using System.Collections.Generic; +using UnityEngine; using UnityEngine.UI; using static AxibugEmuOnline.Client.InGameUI_SaveStateMenu; @@ -10,15 +13,38 @@ namespace AxibugEmuOnline.Client public Image UI_Empty; public Text UI_SavTime; + public GameObject UI_Disconnect; + public GameObject UI_Syncing; + public GameObject UI_Conflict; + public GameObject UI_Synced; + Texture2D m_screenTex; + Dictionary m_stateNodes = new Dictionary(); + + private void Awake() + { + m_stateNodes[typeof(SaveFile.CheckingState)] = UI_Syncing; + m_stateNodes[typeof(SaveFile.ConflictState)] = UI_Conflict; + m_stateNodes[typeof(SaveFile.DownloadingState)] = UI_Syncing; + m_stateNodes[typeof(SaveFile.SyncedState)] = UI_Synced; + m_stateNodes[typeof(SaveFile.UploadingState)] = UI_Syncing; + m_stateNodes[typeof(SaveFile.CheckingNetworkState)] = UI_Disconnect; + } + protected override void OnSetData(InternalOptionMenu menuData) { base.OnSetData(menuData); RefreshUI(); + MenuData.SavFile.OnSavSuccessed += SavFile_OnSavSuccessed; + MenuData.SavFile.OnStateChanged += UpdateStateNode; + } - MenuData.SavFile.OnSavSuccessed += RefreshUI; + private void SavFile_OnSavSuccessed() + { + MenuData.SavFile.TrySync(); + RefreshUI(); } private void RefreshUI() @@ -48,6 +74,21 @@ namespace AxibugEmuOnline.Client m_screenTex.LoadImage(screenShotData); UI_ScreenShot.texture = m_screenTex; } + + UpdateStateNode(); + } + + private void UpdateStateNode() + { + var stateType = MenuData.SavFile.GetState().GetType(); + + foreach (var item in m_stateNodes) + { + var type = item.Key; + var nodeGo = item.Value; + + nodeGo.SetActiveEx(type == stateType); + } } public override void OnHide() @@ -60,7 +101,8 @@ namespace AxibugEmuOnline.Client m_screenTex = null; } - MenuData.SavFile.OnSavSuccessed -= RefreshUI; + MenuData.SavFile.OnSavSuccessed -= SavFile_OnSavSuccessed; + MenuData.SavFile.OnStateChanged -= UpdateStateNode; } public override void OnExecute(OptionUI optionUI, ref bool cancelHide) diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Utility.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Utility.cs index 1a233978..c7c630cd 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Utility.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Utility.cs @@ -55,29 +55,26 @@ namespace AxibugEmuOnline.Client } - public static byte[] ToJPG(this Texture texture) + public static byte[] ToJPG(this Texture texture, Vector2 scale) { - Texture2D outputTex = null; - if (texture is RenderTexture rt) - { - outputTex = ConvertFromRenderTexture(rt); - } - else if (texture is Texture2D) - { - outputTex = texture as Texture2D; - } + Texture2D outputTex = ConvertFromRenderTexture(texture, scale); return outputTex.EncodeToJPG(); } - private static Texture2D ConvertFromRenderTexture(RenderTexture rt) + private static Texture2D ConvertFromRenderTexture(Texture src, Vector2 scale) { + float offsetX = (scale.x < 0) ? 1 : 0; + float offsetY = (scale.y < 0) ? 1 : 0; + + var offset = new Vector2(offsetX, offsetY); + // 创建临时RenderTexture并拷贝内容 - RenderTexture tempRT = RenderTexture.GetTemporary(rt.width, rt.height, 0, RenderTextureFormat.ARGB32); - Graphics.Blit(rt, tempRT); + RenderTexture tempRT = RenderTexture.GetTemporary(src.width, src.height, 0, RenderTextureFormat.ARGB32); + Graphics.Blit(src, tempRT, scale, offset); // 读取到Texture2D - Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false); + Texture2D tex = new Texture2D(src.width, src.height, TextureFormat.RGBA32, false); RenderTexture.active = tempRT; tex.ReadPixels(new Rect(0, 0, tempRT.width, tempRT.height), 0, 0); tex.Apply();