1
1
using System ;
2
+ using System . Collections . Concurrent ;
2
3
using System . Collections . Generic ;
3
4
using System . Collections . Immutable ;
5
+ using System . Linq ;
4
6
using System . Threading . Tasks ;
7
+ using System . Xml . Linq ;
5
8
using Barotrauma . LuaCs . Configuration ;
6
9
using Barotrauma . LuaCs . Data ;
10
+ using Barotrauma . LuaCs . Events ;
11
+ using Barotrauma . LuaCs . Services . Processing ;
7
12
using Barotrauma . Networking ;
8
13
using FluentResults ;
9
14
using Microsoft . Xna . Framework ;
10
15
11
16
namespace Barotrauma . LuaCs . Services ;
12
17
13
- public partial class ConfigService : IConfigService
18
+ public partial class ConfigService : IConfigService , IEventAssemblyContextUnloading
14
19
{
15
20
//--- Internals
16
- private readonly IService _base ;
17
- private int _isDisposed = 0 ;
18
-
19
- public ConfigService ( )
21
+ public ConfigService ( IConverterServiceAsync < IConfigProfileResourceInfo , IReadOnlyList < IConfigProfileInfo > > configProfileResourceConverter ,
22
+ IConverterServiceAsync < IConfigResourceInfo , IReadOnlyList < IConfigInfo > > configResourceConverter )
20
23
{
24
+ _configProfileResourceConverter = configProfileResourceConverter ;
25
+ _configResourceConverter = configResourceConverter ;
21
26
this . _base = this ;
22
27
}
23
28
29
+ // data, states
30
+ private readonly IService _base ;
31
+ private int _isDisposed = 0 ;
32
+ private readonly ConcurrentDictionary < Type , IConfigTypeInitializer < IConfigBase > > _configTypeInitializers = new ( ) ;
33
+ private readonly ConcurrentDictionary < ( ContentPackage Package , string ConfigName ) , IConfigBase > _configs = new ( ) ;
34
+ private readonly ConcurrentDictionary < ContentPackage , ConcurrentBag < ( ContentPackage Package , string ConfigName ) > > _packageConfigReverseLookup = new ( ) ;
35
+ private readonly ConcurrentDictionary < ( ContentPackage Package , string ProfileName ) , ImmutableArray < ( string ConfigName , OneOf . OneOf < string , XElement > Value ) > > _configProfiles = new ( ) ;
36
+ private readonly ConcurrentDictionary < ContentPackage , ConcurrentBag < ( ContentPackage Package , string ProfileName ) > > _packageProfilesReverseLookup = new ( ) ;
37
+
38
+ // converters
39
+ private readonly IConverterServiceAsync < IConfigResourceInfo , IReadOnlyList < IConfigInfo > > _configResourceConverter ;
40
+ private readonly IConverterServiceAsync < IConfigProfileResourceInfo , IReadOnlyList < IConfigProfileInfo > > _configProfileResourceConverter ;
41
+
24
42
//--- GC
25
43
public bool IsDisposed => ModUtils . Threading . GetBool ( ref _isDisposed ) ;
26
44
27
45
public void Dispose ( )
28
46
{
29
47
ModUtils . Threading . SetBool ( ref _isDisposed , true ) ;
48
+ _configTypeInitializers . Clear ( ) ;
30
49
throw new NotImplementedException ( ) ;
31
50
}
32
51
@@ -150,44 +169,117 @@ public void SetConfigList(string packageName, string configName, string value)
150
169
151
170
#endregion
152
171
153
- public void RegisterTypeInitializer < TData , TConfig > ( IConfigTypeInitializer < TData , TConfig > initializer ) where TData : IEquatable < TData > where TConfig : IConfigBase
154
- {
155
- throw new NotImplementedException ( ) ;
156
- }
157
-
158
- public async Task < FluentResults . Result > LoadConfigsAsync ( ImmutableArray < IConfigResourceInfo > configResources )
172
+ public void RegisterTypeInitializer < TData , TConfig > ( IConfigTypeInitializer < TConfig > initializer , bool replaceIfExists = false )
173
+ where TData : IConvertible , IEquatable < TData > where TConfig : IConfigBase
159
174
{
160
175
_base . CheckDisposed ( ) ;
161
- throw new NotImplementedException ( ) ;
176
+ Type dataType = typeof ( TData ) ;
177
+ if ( _configTypeInitializers . ContainsKey ( dataType ) && ! replaceIfExists )
178
+ return ;
179
+ _configTypeInitializers [ dataType ] = ( IConfigTypeInitializer < IConfigBase > ) initializer ;
162
180
}
163
181
164
- public async Task < FluentResults . Result > LoadConfigsProfilesAsync ( ImmutableArray < IConfigProfileResourceInfo > configProfileResources )
182
+ private void AddConfigInstance ( ( ContentPackage Package , string ConfigName ) key , IConfigBase instance )
165
183
{
166
- _base . CheckDisposed ( ) ;
167
- throw new NotImplementedException ( ) ;
184
+ _configs [ key ] = instance ;
185
+ if ( ! _packageConfigReverseLookup . TryGetValue ( key . Package , out var list ) )
186
+ {
187
+ list = new ConcurrentBag < ( ContentPackage Package , string ConfigName ) > ( ) ;
188
+ _packageConfigReverseLookup [ key . Package ] = list ;
189
+ }
190
+ list . Add ( key ) ;
168
191
}
169
192
170
- public Result < IConfigEntry < T > > AddConfigEntry < T > ( ContentPackage package , string name , T defaultValue , NetSync syncMode = NetSync . None ,
171
- ClientPermissions permissions = ClientPermissions . None , Func < T , bool > valueChangePredicate = null ,
172
- Action < IConfigEntry < T > > onValueChanged = null ) where T : IConvertible , IEquatable < T >
193
+ private void AddProfileInstance ( ( ContentPackage Package , string ProfileName ) key , IConfigProfileInfo profile )
194
+ {
195
+ _configProfiles [ key ] = profile . ProfileValues . ToImmutableArray ( ) ;
196
+ if ( ! _packageProfilesReverseLookup . TryGetValue ( key . Package , out var list ) )
197
+ {
198
+ list = new ConcurrentBag < ( ContentPackage Package , string ProfileName ) > ( ) ;
199
+ _packageProfilesReverseLookup [ key . Package ] = list ;
200
+ }
201
+ list . Add ( key ) ;
202
+ }
203
+
204
+ public async Task < FluentResults . Result > LoadConfigsAsync ( ImmutableArray < IConfigResourceInfo > configResources )
173
205
{
174
206
_base . CheckDisposed ( ) ;
175
- throw new NotImplementedException ( ) ;
207
+
208
+ if ( configResources . IsDefaultOrEmpty )
209
+ return FluentResults . Result . Fail ( $ "{ nameof ( LoadConfigsAsync ) } : Array is empty.") ;
210
+
211
+ var results = await _configResourceConverter . TryParseResourcesAsync ( configResources ) ;
212
+ var ret = new FluentResults . Result ( ) ;
213
+
214
+ foreach ( var result in results )
215
+ {
216
+ if ( result . Errors . Any ( ) )
217
+ ret . Errors . AddRange ( result . Errors ) ;
218
+ if ( result . IsFailed || result . Value is not { Count : > 0 } res )
219
+ continue ;
220
+
221
+ foreach ( var configInfo in res )
222
+ {
223
+ if ( _configs . ContainsKey ( ( configInfo . OwnerPackage , configInfo . InternalName ) ) )
224
+ {
225
+ ret . Errors . Add ( new Error ( $ "{ nameof ( LoadConfigsAsync ) } : Config already exists for the compound key { configInfo . OwnerPackage . Name } | { configInfo . InternalName } ") ) ;
226
+ continue ;
227
+ }
228
+
229
+ if ( ! _configTypeInitializers . TryGetValue ( configInfo . DataType , out var initializer ) )
230
+ {
231
+ ret . Errors . Add ( new Error ( $ "{ nameof ( LoadConfigsAsync ) } No type initializer for { configInfo . DataType } ") ) ;
232
+ continue ;
233
+ }
234
+
235
+ var cfg = initializer . Initialize ( configInfo ) ;
236
+ if ( cfg . Errors . Any ( ) )
237
+ ret . Errors . AddRange ( cfg . Errors ) ;
238
+ if ( cfg . IsFailed || cfg . Value is not { } val )
239
+ continue ;
240
+
241
+ AddConfigInstance ( ( configInfo . OwnerPackage , configInfo . InternalName ) , val ) ;
242
+ }
243
+ }
244
+
245
+ return ret ;
176
246
}
177
247
178
- public Result < IConfigList > AddConfigList ( ContentPackage package , string name , int defaultIndex , IReadOnlyList < string > values ,
179
- NetSync syncMode = NetSync . None , ClientPermissions permissions = ClientPermissions . None ,
180
- Func < IConfigList , int , bool > valueChangePredicate = null , Action < IConfigList , int > onValueChanged = null )
248
+ public async Task < FluentResults . Result > LoadConfigsProfilesAsync ( ImmutableArray < IConfigProfileResourceInfo > configProfileResources )
181
249
{
182
250
_base . CheckDisposed ( ) ;
183
- throw new NotImplementedException ( ) ;
251
+
252
+ if ( configProfileResources . IsDefaultOrEmpty )
253
+ return FluentResults . Result . Fail ( $ "{ nameof ( LoadConfigsProfilesAsync ) } : Array is empty.") ;
254
+
255
+ var results = await _configProfileResourceConverter . TryParseResourcesAsync ( configProfileResources ) ;
256
+ var ret = new FluentResults . Result ( ) ;
257
+
258
+ foreach ( var result in results )
259
+ {
260
+ if ( result . Errors . Any ( ) )
261
+ ret . Errors . AddRange ( result . Errors ) ;
262
+ if ( result . IsFailed || result . Value is not { Count : > 0 } res )
263
+ continue ;
264
+
265
+ foreach ( var profileInfo in res )
266
+ {
267
+ if ( _configProfiles . ContainsKey ( ( profileInfo . OwnerPackage , profileInfo . InternalName ) ) )
268
+ {
269
+ ret . Errors . Add ( new Error ( $ "{ nameof ( LoadConfigsProfilesAsync ) } : Config already exists for the compound key { profileInfo . OwnerPackage . Name } | { profileInfo . InternalName } ") ) ;
270
+ continue ;
271
+ }
272
+
273
+ AddProfileInstance ( ( profileInfo . OwnerPackage , profileInfo . ProfileName ) , profileInfo ) ;
274
+ }
275
+ }
276
+
277
+ return ret ;
184
278
}
185
279
186
- public Result < IConfigRangeEntry < T > > AddConfigRangeEntry < T > ( ContentPackage package , string name , T defaultValue , T minValue , T maxValue ,
187
- Func < IConfigRangeEntry < T > , int > getStepCount , NetSync syncMode = NetSync . None , ClientPermissions permissions = ClientPermissions . None ,
188
- Func < T , bool > valueChangePredicate = null , Action < IConfigEntry < T > > onValueChanged = null ) where T : IConvertible , IEquatable < T >
280
+ public Result < TConfig > AddConfig < T , TConfig > ( ContentPackage package , string name , T defaultValue , NetSync syncMode = NetSync . None ,
281
+ ClientPermissions permissions = ClientPermissions . None ) where T : IConvertible , IEquatable < T > where TConfig : IConfigBase
189
282
{
190
- _base . CheckDisposed ( ) ;
191
283
throw new NotImplementedException ( ) ;
192
284
}
193
285
@@ -220,6 +312,11 @@ public Result<IReadOnlyDictionary<string, IConfigBase>> GetConfigsForPackage(str
220
312
throw new NotImplementedException ( ) ;
221
313
}
222
314
315
+ public bool TryGetConfig < T > ( ContentPackage package , string name , out T config ) where T : IConfigBase
316
+ {
317
+ throw new NotImplementedException ( ) ;
318
+ }
319
+
223
320
public T GetConfig < T > ( ContentPackage package , string name ) where T : IConfigBase
224
321
{
225
322
_base . CheckDisposed ( ) ;
@@ -231,4 +328,9 @@ public T GetConfig<T>(string packageName, string name) where T : IConfigBase
231
328
_base . CheckDisposed ( ) ;
232
329
throw new NotImplementedException ( ) ;
233
330
}
331
+
332
+ public void OnAssemblyUnloading ( WeakReference < IAssemblyLoaderService > loaderService )
333
+ {
334
+ throw new NotImplementedException ( ) ;
335
+ }
234
336
}
0 commit comments