@@ -74,14 +74,20 @@ public static void Initialize()
7474 FactoryManager . Init ( ) ;
7575 EventManager . Init ( ) ;
7676
77+ Log . Info ( "<---< Loading global dependencies <---<" ) ;
78+ // Load dependencies from the Global directory inside "configs".
79+ LoadDependencies ( Paths . GlobalPlugins . Dependencies ) ;
80+
81+ Log . Info ( "<---< Loading server dependencies <---<" ) ;
82+ // Load dependencies from the [Server port] directory inside "configs".
83+ LoadDependencies ( Paths . LocalPlugins . Dependencies ) ;
84+
7785 Log . Info ( "<---< Loading global plugins <---<" ) ;
7886 // Load plugins from the Global directory inside "configs".
79- LoadDependencies ( Paths . GlobalPlugins . Dependencies ) ;
8087 LoadPlugins ( Paths . GlobalPlugins ) ;
8188
8289 Log . Info ( "<---< Loading server plugins <---<" ) ;
8390 // Load plugins from the [Server port] directory inside "configs".
84- LoadDependencies ( Paths . LocalPlugins . Dependencies ) ;
8591 LoadPlugins ( Paths . LocalPlugins ) ;
8692
8793 Log . Info ( "<---< Load all plugins <---<" ) ;
@@ -107,89 +113,120 @@ public static void Initialize()
107113 /// <param name="directory">The paths from which to load plugins and their configs from.</param>
108114 private static void LoadPlugins ( PluginDirectory directory )
109115 {
110- string [ ] files = Directory . GetFiles ( directory . Plugins , "*.dll" ) ;
111-
112- Log . Info ( $ "Loading &2{ files . Length } &r plugins...") ;
113- int successes = 0 ;
114-
115- var loadedAssemblies = AppDomain . CurrentDomain
116- . GetAssemblies ( )
117- . Select ( x =>
118- $ "{ x . GetName ( ) . Name } &r v&6{ x . GetName ( ) . Version . ToString ( 3 ) } ") ;
119-
120- foreach ( string pluginPath in files )
116+ try
121117 {
122- if ( ! TryGetAssembly ( pluginPath , out Assembly assembly ) )
123- continue ;
118+ string [ ] files = Directory . GetFiles ( directory . Plugins , "*.dll" ) ;
124119
125- Type [ ] types = null ;
120+ Log . Info ( $ "Loading &2{ files . Length } &r plugins...") ;
121+ int successes = 0 ;
126122
127- var missingDependencies = assembly
128- . GetReferencedAssemblies ( )
129- . Select ( x =>
130- $ "{ x . Name } &r v&6{ x . Version . ToString ( 3 ) } ")
131- . Where ( x => ! loadedAssemblies . Contains ( x ) ) . ToArray ( ) ;
123+ var loadedAssemblies = AppDomain . CurrentDomain
124+ . GetAssemblies ( )
125+ . ToDictionary ( x => x . GetName ( ) . Name , x => x . GetName ( ) . Version ) ;
132126
133- try
134- {
135- if ( missingDependencies . Length != 0 )
136- ResolveAssemblyEmbeddedResources ( assembly ) ;
137- types = assembly . GetTypes ( ) ;
138- }
139- catch ( Exception e )
127+ var loadedPluginAssemblies = new List < PluginAssemblyInformation > ( ) ;
128+ var pluginsToInitialize = new List < PluginAssemblyInformation > ( ) ;
129+
130+ foreach ( string pluginPath in files )
140131 {
141- if ( missingDependencies . Length != 0 )
142- {
143- Log . Error ( $ "Failed loading plugin &2{ Path . GetFileNameWithoutExtension ( pluginPath ) } &r, missing dependencies\n &2{ string . Join ( "\n " , missingDependencies . Select ( x => $ "&r - &2{ x } &r") ) } \n \n { e } ", "Loader" ) ;
132+ if ( ! TryGetAssembly ( pluginPath , out Assembly assembly ) )
144133 continue ;
145- }
146-
147- Log . Error ( $ "Failed loading plugin &2{ Path . GetFileNameWithoutExtension ( pluginPath ) } &r, { e . ToString ( ) } ") ;
148- continue ;
134+ loadedPluginAssemblies . Add ( new PluginAssemblyInformation ( pluginPath , assembly ) ) ;
135+ loadedAssemblies [ assembly . GetName ( ) . Name ] = assembly . GetName ( ) . Version ;
149136 }
150137
151- foreach ( var entryType in types )
138+ foreach ( var pluginInfo in loadedPluginAssemblies )
152139 {
140+ var missingDependencies = pluginInfo . Assembly
141+ . GetReferencedAssemblies ( )
142+ . Where ( x => ! loadedAssemblies . ContainsKey ( x . Name ) )
143+ . ToDictionary ( x => x . Name , x => x . Version ) ;
144+ var versionMismatch = pluginInfo . Assembly
145+ . GetReferencedAssemblies ( )
146+ . Where ( x => loadedAssemblies . ContainsKey ( x . Name ) && loadedAssemblies [ x . Name ] != x . Version )
147+ . ToDictionary ( x => x . Name , x => ( Expected : x . Version , Actual : loadedAssemblies [ x . Name ] ) ) ;
148+
153149 try
154150 {
155- if ( ! entryType . IsValidEntrypoint ( ) ) continue ;
151+ if ( missingDependencies . Count != 0 )
152+ ResolveAssemblyEmbeddedResources ( pluginInfo . Assembly , missingDependencies ) ;
153+
154+ pluginInfo . Types = pluginInfo . Assembly . GetTypes ( ) ;
155+ pluginsToInitialize . Add ( pluginInfo ) ;
156156 }
157- catch ( Exception ex )
157+ catch ( Exception e )
158158 {
159- Log . Error ( $ "Failed checking entrypoint for plugin &2{ Path . GetFileNameWithoutExtension ( pluginPath ) } &r.\n { ex } ") ;
159+ if ( missingDependencies . Count != 0 )
160+ {
161+ Log . Error ( $ "Failed loading plugin &2{ Path . GetFileNameWithoutExtension ( pluginInfo . Path ) } &r, missing dependencies\n &2{ string . Join ( "\n " , missingDependencies . Select ( x => "&r - &2" + x . Key + " v" + x . Value . ToString ( 3 ) + "&r" ) ) } \n \n { e } ", "Loader" ) ;
162+ }
163+ else
164+ {
165+ Log . Error ( "Failed loading plugin &2" + Path . GetFileNameWithoutExtension ( pluginInfo . Path ) + "&r, " + e , "Loader" ) ;
166+ }
167+
160168 continue ;
161169 }
162170
163- if ( ! Plugins . ContainsKey ( assembly ) ) Plugins . Add ( assembly , new Dictionary < Type , PluginHandler > ( ) ) ;
171+ if ( versionMismatch . Count != 0 )
172+ {
173+ Log . Warning ( $ "Dependency version mismatch in plugin &2{ Path . GetFileNameWithoutExtension ( pluginInfo . Path ) } &r\n &2{ string . Join ( "\n " , versionMismatch . Select ( x => "&r - &2" + x . Key + " v" + x . Value . Actual . ToString ( 3 ) + " (expected version by plugin: " + x . Value . Expected . ToString ( 3 ) + ")" + "&r" ) ) } ", "Loader" ) ;
174+ }
175+ }
164176
165- if ( ! Plugins [ assembly ] . ContainsKey ( entryType ) )
177+ Log . Info ( $ "Initializing &2{ pluginsToInitialize . Count } &r plugins...") ;
178+ foreach ( var pluginInfo in pluginsToInitialize )
179+ {
180+ var pluginPath = pluginInfo . Path ;
181+ var assembly = pluginInfo . Assembly ;
182+ var types = pluginInfo . Types ;
183+ foreach ( var entryType in types )
166184 {
167- object plugin = null ;
168185 try
169186 {
170- plugin = Activator . CreateInstance ( entryType ) ;
187+ if ( ! entryType . IsValidEntrypoint ( ) ) continue ;
171188 }
172189 catch ( Exception ex )
173190 {
174- Log . Error ( $ "Failed creating instance of plugin &2{ Path . GetFileNameWithoutExtension ( pluginPath ) } &r.\n { ex } " , "Loader ") ;
191+ Log . Error ( $ "Failed checking entrypoint for plugin &2{ Path . GetFileNameWithoutExtension ( pluginPath ) } &r.\n { ex } ") ;
175192 continue ;
176193 }
177194
178- PluginToAssembly . Add ( plugin , assembly ) ;
195+ if ( ! Plugins . ContainsKey ( assembly ) ) Plugins . Add ( assembly , new Dictionary < Type , PluginHandler > ( ) ) ;
179196
180- Plugins [ assembly ] . Add ( entryType , new PluginHandler ( directory , plugin , entryType , types )
197+ if ( ! Plugins [ assembly ] . ContainsKey ( entryType ) )
181198 {
182- PluginFilePath = pluginPath
183- } ) ;
184- successes ++ ;
199+ object plugin = null ;
200+ try
201+ {
202+ plugin = Activator . CreateInstance ( entryType ) ;
203+ }
204+ catch ( Exception ex )
205+ {
206+ Log . Error ( $ "Failed creating instance of plugin &2{ Path . GetFileNameWithoutExtension ( pluginPath ) } &r.\n { ex } ", "Loader" ) ;
207+ continue ;
208+ }
209+
210+ PluginToAssembly . Add ( plugin , assembly ) ;
211+
212+ Plugins [ assembly ] . Add ( entryType , new PluginHandler ( directory , plugin , entryType , types )
213+ {
214+ PluginFilePath = pluginPath
215+ } ) ;
216+ successes ++ ;
217+ }
185218 }
186219 }
187- }
188220
189- if ( successes > 0 )
190- CustomNetworkManager . Modded = true ;
221+ if ( successes > 0 )
222+ CustomNetworkManager . Modded = true ;
191223
192- Log . Info ( $ "Loaded &2{ successes } &r/&2{ files . Length } &r plugins.") ;
224+ Log . Info ( $ "Loaded &2{ successes } &r/&2{ files . Length } &r plugins.") ;
225+ }
226+ catch ( Exception e )
227+ {
228+ Log . Error ( e . ToString ( ) ) ;
229+ }
193230 }
194231
195232 /// <summary>
@@ -217,6 +254,7 @@ private static void LoadDependencies(string path)
217254 Log . Error ( $ "Failed loading dependency &2{ Path . GetFileNameWithoutExtension ( dependencyPath ) } &r.\n { ex } ") ;
218255 continue ;
219256 }
257+
220258 successes ++ ;
221259 }
222260
@@ -249,7 +287,8 @@ private static bool TryGetAssembly(string path, out Assembly assembly)
249287 /// Attempts to load Embedded assemblies (compressed) from the target
250288 /// </summary>
251289 /// <param name="target">Assembly to check for embedded assemblies</param>
252- private static void ResolveAssemblyEmbeddedResources ( Assembly target )
290+ /// <param name="missingDependencies"></param>
291+ private static void ResolveAssemblyEmbeddedResources ( Assembly target , Dictionary < string , Version > missingDependencies )
253292 {
254293 Log . Debug ( $ "Attempting to load embedded resources for { target . FullName } ", Log . DebugMode ) ;
255294
@@ -271,7 +310,8 @@ private static void ResolveAssemblyEmbeddedResources(Assembly target)
271310 }
272311
273312 dataStream . CopyTo ( stream ) ;
274- Assembly . Load ( stream . ToArray ( ) ) ;
313+ var assemblyName = Assembly . Load ( stream . ToArray ( ) ) . GetName ( ) ;
314+ missingDependencies . Remove ( assemblyName . Name ) ;
275315 Log . Debug ( $ "Loaded { name } ", Log . DebugMode ) ;
276316 }
277317 }
@@ -289,7 +329,8 @@ private static void ResolveAssemblyEmbeddedResources(Assembly target)
289329 {
290330 Log . Debug ( $ "Loading { name } ", Log . DebugMode ) ;
291331 stream . CopyTo ( memStream ) ;
292- Assembly . Load ( memStream . ToArray ( ) ) ;
332+ var assemblyName = Assembly . Load ( memStream . ToArray ( ) ) . GetName ( ) ;
333+ missingDependencies . Remove ( assemblyName . Name ) ;
293334 Log . Debug ( $ "Loaded { name } ", Log . DebugMode ) ;
294335 }
295336 }
0 commit comments