Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
ExternalContentManager.cs
浏览该文件的文档.
1using System.Text;
2using Engine;
3
4namespace Game {
5 public static class ExternalContentManager {
6 public static List<IExternalContentProvider> m_providers;
7 public static string fName = "ExternalContentManager";
8
9 //在游戏进入主菜单之前,如果openFilePath为一个文件(存档、模组)路径,那么在进入游戏后,会进行对文件的安装操作
10 [Obsolete]
11 public static string openFilePath = string.Empty;
12 public static IExternalContentProvider DefaultProvider => Providers.Count <= 0 ? null : Providers[0];
13
14 public static ReadOnlyList<IExternalContentProvider> Providers => new(m_providers);
15
16 public static void Initialize() {
17 m_providers = [
18#if !ANDROID
20#endif
21#if ANDROID
22 new AndroidSdCardExternalContentProvider(),
23#endif
26 ];
27 }
28
29 public static ExternalContentType ExtensionToType(string extension) {
30 extension = extension.ToLower();
31 foreach (ExternalContentType value in Enum.GetValues<ExternalContentType>()) {
32 if (GetEntryTypeExtensions(value).FirstOrDefault(e => e == extension) != null) {
33 return value;
34 }
35 }
36 return ExternalContentType.Unknown;
37 }
38
39 public static IEnumerable<string> GetEntryTypeExtensions(ExternalContentType type) {
40 switch (type) {
41 case ExternalContentType.World: yield return ".scworld"; break;
42 case ExternalContentType.BlocksTexture:
43 yield return ".scbtex";
44 yield return ".webp";
45 yield return ".png";
46 yield return ".astc";
47 yield return ".astcsrgb";
48 break;
49 case ExternalContentType.CharacterSkin: yield return ".scskin"; break;
50 case ExternalContentType.FurniturePack: yield return ".scfpack"; break;
51 case ExternalContentType.Mod: yield return ".scmod"; break;
52 case ExternalContentType.ModList: yield return ".scmodList"; break;
53 }
54 }
55
57 return type switch {
58 ExternalContentType.Directory => ContentManager.Get<Subtexture>("Textures/Atlas/FolderIcon"),
59 ExternalContentType.World => ContentManager.Get<Subtexture>("Textures/Atlas/WorldIcon"),
60 ExternalContentType.BlocksTexture => ContentManager.Get<Subtexture>("Textures/Atlas/TexturePackIcon"),
61 ExternalContentType.CharacterSkin => ContentManager.Get<Subtexture>("Textures/Atlas/CharacterSkinIcon"),
62 ExternalContentType.FurniturePack => ContentManager.Get<Subtexture>("Textures/Atlas/FurnitureIcon"),
63 ExternalContentType.Mod => ContentManager.Get<Subtexture>("Textures/Gui/DefaultModIcon"),
64 _ => ContentManager.Get<Subtexture>("Textures/Atlas/QuestionMarkIcon")
65 };
66 }
67
68 public static string GetEntryTypeDescription(ExternalContentType type) {
69 return type switch {
76 _ => string.Empty
77 };
78 }
79
81 return type switch {
87 _ => false
88 };
89 }
90
92 return type switch {
96 _ => false
97 };
98 }
99
100 public static Exception VerifyExternalContentName(string name) {
101 if (string.IsNullOrEmpty(name)) {
102 return new InvalidOperationException(LanguageControl.Get(fName, 1));
103 }
104 if (name.Length > 50) {
105 return new InvalidOperationException(LanguageControl.Get(fName, 2));
106 }
107 if (name[0] == ' '
108 || name[^1] == ' ') {
109 return new InvalidOperationException(LanguageControl.Get(fName, 3));
110 }
111 return null;
112 }
113
114 public static void DeleteExternalContent(ExternalContentType type, string name) {
115 switch (type) {
116 case ExternalContentType.World: WorldsManager.DeleteWorld(name); break;
117 case ExternalContentType.BlocksTexture: BlocksTexturesManager.DeleteBlocksTexture(name); break;
118 case ExternalContentType.CharacterSkin: CharacterSkinsManager.DeleteCharacterSkin(name); break;
119 case ExternalContentType.FurniturePack: FurniturePacksManager.DeleteFurniturePack(name); break;
120 default: throw new InvalidOperationException(LanguageControl.Get(fName, 4));
121 }
122 }
123
124 public static void ImportExternalContent(Stream stream,
126 string name,
127 Action<string> success,
128 Action<Exception> failure) {
129 Task.Run(
130 delegate {
131 try {
132 success?.Invoke(ImportExternalContentSync(stream, type, name));
133 }
134 catch (Exception obj) {
135 failure?.Invoke(obj);
136 }
137 }
138 );
139 }
140
141 public static string ImportExternalContentSync(Stream stream, ExternalContentType type, string name) {
142 switch (type) {
143 case ExternalContentType.World: return WorldsManager.ImportWorld(stream);
144 case ExternalContentType.BlocksTexture: return BlocksTexturesManager.ImportBlocksTexture(name, stream);
145 case ExternalContentType.CharacterSkin: return CharacterSkinsManager.ImportCharacterSkin(name, stream);
146 case ExternalContentType.FurniturePack: return FurniturePacksManager.ImportFurniturePack(name, stream);
147 case ExternalContentType.Mod: return ModsManager.ImportMod(name, stream);
148 default: throw new InvalidOperationException(LanguageControl.Get(fName, 4));
149 }
150 }
151
152 public static async Task ImportExternalContentsAsync(List<(Stream stream, string fileName)> files, bool showResultDialog) {
153 string successFormat = LanguageControl.Get(fName, 18);
154 string failureFormat = LanguageControl.Get(fName, 19);
155 string unsupportedString = LanguageControl.Get(fName, 12);
156
157 async Task<string> Import(Stream stream, string fileName) {
158 return await Task.Run(() => {
161 try {
162 ImportExternalContentSync(stream, type, fileName);
163 }
164 catch (Exception e) {
165 return string.Format(failureFormat, fileName, e.Message);
166 }
167 finally {
168 stream.Dispose();
169 }
170 return string.Format(successFormat, fileName);
171 }
172 return string.Format(failureFormat, fileName, unsupportedString);
173 }
174 );
175 }
176
177 Task<string>[] tasks = new Task<string>[files.Count];
178 for (int i = 0; i < files.Count; i++) {
179 (Stream stream, string fileName) = files[i];
180 tasks[i] = Import(stream, fileName);
181 }
182 string[] results = await Task.WhenAll(tasks);
183 StringBuilder sb = new();
184 foreach (string result in results) {
185 sb.AppendLine(result);
186 }
187 string finalResult = sb.ToString();
188 Log.Information(finalResult);
189 if (showResultDialog) {
190 Dispatcher.Dispatch(() => {
192 null,
193 new MessageDialog(LanguageControl.Get(fName, 20), finalResult, LanguageControl.Ok, null, null)
194 );
195 }
196 );
197 }
198 }
199
200 public static void ImportExternalContentsSync(List<(Stream stream, string fileName)> files, bool showResultDialog) {
201 string successFormat = LanguageControl.Get(fName, 18);
202 string failureFormat = LanguageControl.Get(fName, 19);
203 string unsupportedString = LanguageControl.Get(fName, 12);
204 StringBuilder sb = new();
205 foreach ((Stream stream, string fileName) in files) {
208 try {
209 ImportExternalContentSync(stream, type, fileName);
210 sb.AppendLine(string.Format(successFormat, fileName));
211 }
212 catch (Exception e) {
213 sb.AppendLine(string.Format(failureFormat, fileName, e.Message));
214 }
215 }
216 else {
217 sb.AppendLine(string.Format(failureFormat, fileName, unsupportedString));
218 }
219 }
220 string finalResult = sb.ToString();
221 Log.Information(finalResult);
222 if (showResultDialog) {
223 DialogsManager.ShowDialog(null, new MessageDialog(LanguageControl.Get(fName, 20), finalResult, LanguageControl.Ok, null, null));
224 }
225 }
226
227 public static void ShowLoginUiIfNeeded(IExternalContentProvider provider, bool showWarningDialog, Action handler) {
228 if (provider.RequiresLogin
229 && !provider.IsLoggedIn) {
230 void LoginAction() {
231 CancellableBusyDialog busyDialog = new(LanguageControl.Get(fName, 5), true);
232 DialogsManager.ShowDialog(null, busyDialog);
233 provider.Login(
234 busyDialog.Progress,
235 delegate {
236 DialogsManager.HideDialog(busyDialog);
237 handler?.Invoke();
238 },
239 delegate(Exception error) {
240 DialogsManager.HideDialog(busyDialog);
241 if (error != null) {
243 null,
244 new MessageDialog(LanguageControl.Error, error.Message, LanguageControl.Ok, null, null)
245 );
246 }
247 }
248 );
249 }
250
251 if (showWarningDialog) {
253 null,
254 new MessageDialog(
256 string.Format(LanguageControl.Get(fName, 7), provider.DisplayName),
259 delegate(MessageDialogButton b) {
260 if (b == MessageDialogButton.Button1) {
261 LoginAction();
262 }
263 }
264 )
265 );
266 }
267 else {
268 LoginAction();
269 }
270 }
271 else {
272 handler?.Invoke();
273 }
274 }
275
276 public static void ShowUploadUi(ExternalContentType type, string name) {
278 null,
281 false,
282 delegate(IExternalContentProvider provider) {
283 try {
284 if (provider != null) {
286 provider,
287 true,
288 delegate {
289 CancellableBusyDialog busyDialog = new(LanguageControl.Get(fName, 10), false);
290 DialogsManager.ShowDialog(null, busyDialog);
291 Task.Run(
292 delegate {
293 bool needsDelete = false;
294 string sourcePath = null;
295 Stream stream = null;
296
297 void Cleanup() {
298 // ReSharper disable AccessToModifiedClosure
299 Utilities.Dispose(ref stream);
300 // ReSharper restore AccessToModifiedClosure
301 if (needsDelete && sourcePath != null) {
302 try {
303 Storage.DeleteFile(sourcePath);
304 }
305 catch {
306 // ignored
307 }
308 }
309 }
310
311 try {
312 string path;
313 if (type == ExternalContentType.BlocksTexture) {
314 sourcePath = BlocksTexturesManager.GetFileName(name);
315 if (sourcePath == null) {
316 throw new InvalidOperationException(LanguageControl.Get(fName, 11));
317 }
318 path = Storage.GetFileName(sourcePath);
319 }
320 else if (type == ExternalContentType.CharacterSkin) {
321 sourcePath = CharacterSkinsManager.GetFileName(name);
322 if (sourcePath == null) {
323 throw new InvalidOperationException(LanguageControl.Get(fName, 11));
324 }
325 path = Storage.GetFileName(sourcePath);
326 }
327 else if (type == ExternalContentType.FurniturePack) {
328 sourcePath = FurniturePacksManager.GetFileName(name);
329 if (sourcePath == null) {
330 throw new InvalidOperationException(LanguageControl.Get(fName, 11));
331 }
332 path = Storage.GetFileName(sourcePath);
333 }
334 else {
335 if (type != ExternalContentType.World) {
336 throw new InvalidOperationException(LanguageControl.Get(fName, 12));
337 }
338 busyDialog.LargeMessage = LanguageControl.Get(fName, 13);
339 sourcePath = Storage.CombinePaths(ModsManager.ExternalPath, "WorldUpload.tmp");
340 needsDelete = true;
341 string name2 = WorldsManager.GetWorldInfo(name).WorldSettings.Name;
342 path = $"{name2}.scworld";
343 using (Stream targetStream = Storage.OpenFile(sourcePath, OpenFileMode.Create)) {
344 WorldsManager.ExportWorld(name, targetStream);
345 }
346 }
347 busyDialog.LargeMessage = LanguageControl.Get(fName, 14);
348 stream = Storage.OpenFile(sourcePath, OpenFileMode.Read);
349 provider.Upload(
350 path,
351 stream,
352 busyDialog.Progress,
353 delegate(string link) {
354 // ReSharper disable AccessToModifiedClosure
355 long length = stream.Length;
356 // ReSharper restore AccessToModifiedClosure
357 Cleanup();
358 DialogsManager.HideDialog(busyDialog);
359 if (provider.IsLocalProvider) {
360#if ANDROID || BROWSER
362 null,
363 new MessageDialog(
365 $"{string.Format(LanguageControl.Get(fName, 15), DataSizeFormatter.Format(length))}\n{LanguageControl.Get(fName, "21")}{link}",
368 button => {
369 if (button == MessageDialogButton.Button1) {
370 Task.Run(async () => {
371 try {
372 await Storage.ShareFile(link);
373 }
374 catch (Exception e) {
375 Dispatcher.Dispatch(() => DialogsManager.ShowDialog(
376 null,
377 new MessageDialog(
378 LanguageControl.Error,
379 e.Message,
380 LanguageControl.Ok,
381 null,
382 null
383 )
384 )
385 );
386 }
387 });
388 }
389 }
390 )
391 );
392#else
394 null,
395 new MessageDialog(
397 $"{string.Format(LanguageControl.Get(fName, 15), DataSizeFormatter.Format(length))}\n{LanguageControl.Get(fName, "21")}{link}",
399 null,
400 null
401 )
402 );
403#endif
404 }
405 else {
407 }
408 },
409 delegate(Exception error) {
410 Cleanup();
411 DialogsManager.HideDialog(busyDialog);
413 null,
414 new MessageDialog(
416 error.Message,
418 null,
419 null
420 )
421 );
422 }
423 );
424 }
425 catch (Exception ex2) {
426 Cleanup();
427 DialogsManager.HideDialog(busyDialog);
429 null,
430 new MessageDialog(LanguageControl.Error, ex2.Message, LanguageControl.Ok, null, null)
431 );
432 }
433 }
434 );
435 }
436 );
437 }
438 }
439 catch (Exception ex) {
441 }
442 }
443 )
444 );
445 }
446 }
447}
static void Dispatch(Action action, bool waitUntilCompleted=false)
static void Information(object message)
定义 Log.cs:56
static Stream OpenFile(string path, OpenFileMode openFileMode)
static string GetExtension(string path)
static string GetFileName(string path)
static void DeleteFile(string path)
static string CombinePaths(params string[] paths)
static string ImportBlocksTexture(string name, Stream stream)
static string GetFileName(string name)
static void DeleteBlocksTexture(string name)
static string GetFileName(string name)
static void DeleteCharacterSkin(string name)
static string ImportCharacterSkin(string name, Stream stream)
static object Get(Type type, string name)
static void HideDialog(Dialog dialog)
static void ShowDialog(ContainerWidget parentWidget, Dialog dialog)
static void ImportExternalContent(Stream stream, ExternalContentType type, string name, Action< string > success, Action< Exception > failure)
static bool IsEntryTypeDownloadSupported(ExternalContentType type)
static async Task ImportExternalContentsAsync(List<(Stream stream, string fileName)> files, bool showResultDialog)
static void ShowUploadUi(ExternalContentType type, string name)
static ReadOnlyList< IExternalContentProvider > Providers
static Exception VerifyExternalContentName(string name)
static ExternalContentType ExtensionToType(string extension)
static IEnumerable< string > GetEntryTypeExtensions(ExternalContentType type)
static void ImportExternalContentsSync(List<(Stream stream, string fileName)> files, bool showResultDialog)
static void ShowLoginUiIfNeeded(IExternalContentProvider provider, bool showWarningDialog, Action handler)
static List< IExternalContentProvider > m_providers
static bool DoesEntryTypeRequireName(ExternalContentType type)
static Subtexture GetEntryTypeIcon(ExternalContentType type)
static void DeleteExternalContent(ExternalContentType type, string name)
static string GetEntryTypeDescription(ExternalContentType type)
static IExternalContentProvider DefaultProvider
static string ImportExternalContentSync(Stream stream, ExternalContentType type, string name)
static string GetFileName(string name)
static void DeleteFurniturePack(string name)
static string ImportFurniturePack(string name, Stream stream)
static string Get(string className, int key)
获取在当前语言类名键对应的字符串
WorldSettings WorldSettings
static string ImportWorld(Stream sourceStream)
static void ExportWorld(string directoryName, Stream targetStream)
static WorldInfo GetWorldInfo(string directoryName)
static void DeleteWorld(string directoryName)
static string ExternalPath
static string ImportMod(string name, Stream stream)
void Upload(string path, Stream stream, CancellableProgress progress, Action< string > success, Action< Exception > failure)
void Login(CancellableProgress progress, Action success, Action< Exception > failure)