1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . IO ;
4+ using System . Threading . Tasks ;
5+ using UnityEditor ;
6+ using UnityEngine ;
7+ using VirtueSky . Inspector ;
8+
9+
10+ #if VIRTUESKY_FIREBASE
11+ using Firebase ;
12+ using Firebase . Extensions ;
13+ #endif
14+
15+ #if VIRTUESKY_FIREBASE_REMOTECONFIG
16+ using Firebase . RemoteConfig ;
17+ #endif
18+
19+ namespace VirtueSky . RemoteConfigs
20+ {
21+ public class FirebaseRemoteConfigManager : MonoBehaviour
22+ {
23+ [ SerializeField ] private bool dontDestroyOnLoad ;
24+ #if VIRTUESKY_FIREBASE
25+ [ Space , ReadOnly , SerializeField ] private DependencyStatus dependencyStatus = DependencyStatus . UnavailableOther ;
26+ #endif
27+ [ SerializeField ] private bool isSetupDefaultData = true ;
28+ [ Space ( 10 ) , SerializeField ] private List < FirebaseRemoteConfigData > listRemoteConfigData ;
29+
30+ private bool _isFetchRemoteConfigCompleted = false ;
31+ private static FirebaseRemoteConfigManager _instance ;
32+
33+ private void Awake ( )
34+ {
35+ if ( dontDestroyOnLoad )
36+ {
37+ DontDestroyOnLoad ( this . gameObject ) ;
38+ }
39+
40+ if ( _instance == null )
41+ {
42+ _instance = this ;
43+ }
44+ else
45+ {
46+ Destroy ( gameObject ) ;
47+ }
48+ }
49+
50+ #region API
51+
52+ public static bool IsFetchRemoteConfigCompleted => _instance . _isFetchRemoteConfigCompleted ;
53+ public static List < FirebaseRemoteConfigData > ListRemoteConfigData => _instance . listRemoteConfigData ;
54+
55+ #endregion
56+
57+ #if VIRTUESKY_FIREBASE
58+ private void Start ( )
59+ {
60+ _isFetchRemoteConfigCompleted = false ;
61+ if ( isSetupDefaultData )
62+ {
63+ foreach ( var remoteConfigData in listRemoteConfigData )
64+ {
65+ remoteConfigData . SetupDataDefault ( ) ;
66+ }
67+ }
68+
69+ FirebaseApp . CheckAndFixDependenciesAsync ( ) . ContinueWithOnMainThread ( task =>
70+ {
71+ dependencyStatus = task . Result ;
72+ if ( dependencyStatus == DependencyStatus . Available )
73+ {
74+ #if VIRTUESKY_FIREBASE_REMOTECONFIG
75+ FetchDataAsync ( ) ;
76+ #endif
77+ }
78+ else
79+ {
80+ Debug . LogError ( "Could not resolve all Firebase dependencies: " +
81+ dependencyStatus ) ;
82+ }
83+ } ) ;
84+ }
85+ #endif
86+
87+ #if VIRTUESKY_FIREBASE_REMOTECONFIG && VIRTUESKY_FIREBASE
88+ private Task FetchDataAsync ( )
89+ {
90+ Debug . Log ( "Fetching data..." ) ;
91+ Task fetchTask = FirebaseRemoteConfig . DefaultInstance
92+ . FetchAsync ( TimeSpan . Zero ) ;
93+ if ( fetchTask . IsCanceled )
94+ {
95+ Debug . Log ( "Fetch canceled." ) ;
96+ }
97+ else if ( fetchTask . IsFaulted )
98+ {
99+ Debug . Log ( "Fetch encountered an error." ) ;
100+ }
101+ else if ( fetchTask . IsCompleted )
102+ {
103+ Debug . Log ( "Fetch completed successfully!" ) ;
104+ }
105+
106+ return fetchTask . ContinueWithOnMainThread ( tast =>
107+ {
108+ var info = FirebaseRemoteConfig . DefaultInstance . Info ;
109+ if ( info . LastFetchStatus == LastFetchStatus . Success )
110+ {
111+ FirebaseRemoteConfig . DefaultInstance . ActivateAsync ( ) . ContinueWithOnMainThread (
112+ task =>
113+ {
114+ Debug . Log ( String . Format (
115+ "Remote data loaded and ready (last fetch time {0})." ,
116+ info . FetchTime ) ) ;
117+ foreach ( var remoteConfigData in listRemoteConfigData )
118+ {
119+ if ( string . IsNullOrEmpty ( remoteConfigData . key ) ) continue ;
120+ remoteConfigData . SetupData ( FirebaseRemoteConfig . DefaultInstance
121+ . GetValue ( remoteConfigData . key . ToString ( ) ) ) ;
122+ }
123+
124+ _isFetchRemoteConfigCompleted = true ;
125+ } ) ;
126+
127+ Debug . Log ( "<color=Green>Firebase Remote Config Fetching completed!</color>" ) ;
128+ }
129+ else
130+ {
131+ Debug . Log ( "Fetching data did not completed!" ) ;
132+ }
133+ } ) ;
134+ }
135+ #endif
136+
137+ #if UNITY_EDITOR
138+ private const string pathDefaultScript = "Assets/_Root/Scripts" ;
139+ [ Button ]
140+ private void GenerateRemoteData ( )
141+ {
142+ if ( ! Directory . Exists ( pathDefaultScript ) )
143+ {
144+ Directory . CreateDirectory ( pathDefaultScript ) ;
145+ }
146+
147+ var productImplPath = $ "{ pathDefaultScript } /RemoteData.cs";
148+ var str = "namespace VirtueSky.RemoteConfigs\n {" ;
149+ str += "\n \t public struct RemoteData\n \t {" ;
150+
151+ var listRmcData = listRemoteConfigData ;
152+ for ( int i = 0 ; i < listRmcData . Count ; i ++ )
153+ {
154+ var rmcKey = listRmcData [ i ] . key ;
155+
156+ str += $ "\n \t \t public const string KEY_{ rmcKey . ToUpper ( ) } = \" { rmcKey } \" ;";
157+
158+ switch ( listRmcData [ i ] . typeRemoteConfigData )
159+ {
160+ case TypeRemoteConfigData . StringData :
161+ str +=
162+ $ "\n \t \t public const string DEFAULT_{ rmcKey . ToUpper ( ) } = \" { listRmcData [ i ] . defaultValueString } \" ;";
163+ str += "\n \t \t #if VIRTUESKY_DATA" ;
164+ str +=
165+ $ "\n \t \t public static string { rmcKey . ToUpper ( ) } => VirtueSky.DataStorage.GameData.Get(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
166+ str += "\n \t \t #else" ;
167+ str +=
168+ $ "\n \t \t public static string { rmcKey . ToUpper ( ) } => UnityEngine.PlayerPrefs.GetString(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
169+ str += "\n \t \t #endif" ;
170+ break ;
171+ case TypeRemoteConfigData . BooleanData :
172+ str +=
173+ $ "\n \t \t public const bool DEFAULT_{ rmcKey . ToUpper ( ) } = { GetBool ( listRmcData [ i ] . defaultValueBool ) } ;";
174+ str += "\n \t \t #if VIRTUESKY_DATA" ;
175+ str +=
176+ $ "\n \t \t public static bool { rmcKey . ToUpper ( ) } => VirtueSky.DataStorage.GameData.Get(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
177+ str += "\n \t \t #else" ;
178+ str +=
179+ $ "\n \t \t public static bool { rmcKey . ToUpper ( ) } => UnityEngine.PlayerPrefs.GetInt(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } ? 1 : 0) > 0;";
180+ str += "\n \t \t #endif" ;
181+ break ;
182+ case TypeRemoteConfigData . IntData :
183+ str +=
184+ $ "\n \t \t public const int DEFAULT_{ rmcKey . ToUpper ( ) } = { listRmcData [ i ] . defaultValueInt } ;";
185+ str += "\n \t \t #if VIRTUESKY_DATA" ;
186+ str +=
187+ $ "\n \t \t public static int { rmcKey . ToUpper ( ) } => VirtueSky.DataStorage.GameData.Get(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
188+ str += "\n \t \t #else" ;
189+ str +=
190+ $ "\n \t \t public static int { rmcKey . ToUpper ( ) } => UnityEngine.PlayerPrefs.GetInt(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
191+ str += "\n \t \t #endif" ;
192+ break ;
193+ }
194+ }
195+
196+ str += "\n \t }" ;
197+ str += "\n }" ;
198+
199+ var writer = new StreamWriter ( productImplPath , false ) ;
200+ writer . Write ( str ) ;
201+ writer . Close ( ) ;
202+ AssetDatabase . ImportAsset ( productImplPath ) ;
203+
204+ string GetBool ( bool condition )
205+ {
206+ return condition ? "true" : "false" ;
207+ }
208+ }
209+ #endif
210+ }
211+ }
0 commit comments