This repository has been archived by the owner on Jan 4, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 98
/
LoadService.cs
executable file
·471 lines (344 loc) · 15.2 KB
/
LoadService.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
//
// Copyright (c) Jesse Freeman, Pixel Vision 8. All rights reserved.
//
// Licensed under the Microsoft Public License (MS-PL) except for a few
// portions of the code. See LICENSE file in the project root for full
// license information. Third-party libraries used by Pixel Vision 8 are
// under their own licenses. Please refer to those libraries for details
// on the license they use.
//
// Contributors
// --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors:
//
// Jesse Freeman - @JesseFreeman
// Christina-Antoinette Neofotistou @CastPixel
// Christer Kaitila - @McFunkypants
// Pedro Medeiros - @saint11
// Shawn Rakowski - @shwany
//
using Microsoft.Xna.Framework;
using PixelVision8.Engine;
using PixelVision8.Engine.Chips;
using PixelVision8.Engine.Services;
using PixelVision8.Engine.Utils;
using PixelVision8.Runner.Importers;
using PixelVision8.Runner.Parsers;
using PixelVision8.Runner.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
namespace PixelVision8.Runner.Services
{
public class LoadService : AbstractService
{
protected readonly List<IAbstractParser> parsers = new List<IAbstractParser>();
protected int currentParserID;
public int currentStep;
protected BackgroundWorker loadingWorker;
protected Color maskColor = ColorUtils.HexToColor("#ff00ff"); // TODO this shouldn't be hard coded
protected AbstractParser parser;
public IEngine targetEngine;
public List<string> textExtensions = new List<string>
{
".txt",
".json",
".lua",
".cs"
};
protected int TotalParsers => parsers.Count;
public int TotalSteps;
private readonly IFileLoadHelper _fileLoadHelper;
public LoadService(IFileLoadHelper fileLoadHelper)
{
_fileLoadHelper = fileLoadHelper;
}
public bool Completed => currentParserID >= TotalParsers;
public float Percent => TotalSteps == 0 ? 1f : currentStep / (float)TotalSteps;
/// <summary>
/// This can be used to display a message while preloading
/// </summary>
public string Message { get; protected set; }
public void Reset()
{
parsers.Clear();
currentParserID = 0;
TotalSteps = 0;
currentStep = 0;
}
public virtual void ParseFiles(string[] files, IEngine engine, SaveFlags saveFlags)
{
Reset();
// Save the engine so we can work with it during loading
targetEngine = engine;
// Step 1. Load the system snapshot
if ((saveFlags & SaveFlags.System) == SaveFlags.System) LoadSystem(files);
// Step 3 (optional). Look for new colors
if ((saveFlags & SaveFlags.Colors) == SaveFlags.Colors)
{
// Add the color parser
parser = LoadColors(files);
if (parser != null) AddParser(parser);
}
// Step 4 (optional). Look for color map for sprites and tile map
if ((saveFlags & SaveFlags.ColorMap) == SaveFlags.ColorMap)
{
// TODO this is a legacy parcer and should be depricated
parser = LoadColorMap(files);
if (parser != null) AddParser(parser);
}
// Step 5 (optional). Look for new sprites
if ((saveFlags & SaveFlags.Sprites) == SaveFlags.Sprites)
{
parser = LoadSprites(files);
if (parser != null) AddParser(parser);
}
// Step 6 (optional). Look for tile map to load
if ((saveFlags & SaveFlags.Tilemap) == SaveFlags.Tilemap) LoadTilemap(files);
// Step 7 (optional). Look for fonts to load
if ((saveFlags & SaveFlags.Fonts) == SaveFlags.Fonts)
{
// these are the defaul font names
var defaultFonts = new string[]{
"large",
"medium",
"small",
};
// Get the list of fonts in the directory
var paths = files.Where(s => s.EndsWith(".font.png")).ToList();
// Make sure the default fonts are either in the project or in /Tools/Fonts/*
foreach (var font in defaultFonts)
{
if(paths.Contains("/Game/" + font + ".font.png") == false)
{
paths.Add("/PixelVisionOS/Tools/Fonts/" + font + ".font.png");
}
}
// Loop through each of the fonts and load them up
foreach (var fileName in paths)
{
var imageParser = new PNGFileReader(fileName, _fileLoadHelper, targetEngine.ColorChip.maskColor);
AddParser(new FontParser(imageParser, targetEngine.ColorChip, targetEngine.FontChip));
}
}
// Step 8 (optional). Look for meta data and override the game
if ((saveFlags & SaveFlags.Meta) == SaveFlags.Meta)
{
parser = LoadMetaData(files);
if (parser != null) AddParser(parser);
}
// Step 9 (optional). Look for meta data and override the game
if ((saveFlags & SaveFlags.Sounds) == SaveFlags.Sounds)
{
LoadSounds(files);
// Get all of the wav files
var wavFiles = files.Where(x => x.EndsWith(".wav")).ToArray();
if (wavFiles.Length > 0)
AddParser(new WavParser(wavFiles, _fileLoadHelper, targetEngine));
}
// Step 10 (optional). Look for meta data and override the game
if ((saveFlags & SaveFlags.Music) == SaveFlags.Music) LoadMusic(files);
// Step 11 (optional). Look for meta data and override the game
if ((saveFlags & SaveFlags.SaveData) == SaveFlags.SaveData) LoadSaveData(files);
// Step 12 (optional). Look for meta sprites
if ((saveFlags & SaveFlags.MetaSprites) == SaveFlags.MetaSprites) LoadMetaSprites(files);
ParseExtraFileTypes(files, engine, saveFlags);
}
public virtual void ParseExtraFileTypes(string[] files, IEngine engine, SaveFlags saveFlags)
{
// TODO Override and add extra file parsers here.
}
public void AddParser(IAbstractParser parser)
{
parser.CalculateSteps();
parsers.Add(parser);
TotalSteps += parser.totalSteps;
}
public void LoadAll()
{
while (Completed == false) NextParser();
parsers.Clear();
}
public void NextParser()
{
if (Completed)
{
parsers.Clear();
return;
}
var parser = parsers[currentParserID];
parser.NextStep();
currentStep++;
if (parser.completed)
{
parser.Dispose();
currentParserID++;
}
}
public void StartLoading()
{
loadingWorker = new BackgroundWorker
{
// TODO need a way to of locking this.
WorkerSupportsCancellation = true,
WorkerReportsProgress = true
};
loadingWorker.DoWork += WorkerLoaderSteps;
// bgw.ProgressChanged += WorkerLoaderProgressChanged;
loadingWorker.RunWorkerCompleted += WorkerLoaderCompleted;
// bgw.WorkerReportsProgress = true;
loadingWorker.RunWorkerAsync();
}
protected void WorkerLoaderSteps(object sender, DoWorkEventArgs e)
{
for (var i = 0; i <= TotalSteps; i++) //some number (total)
{
NextParser();
Thread.Sleep(1);
loadingWorker.ReportProgress((int)(Percent * 100), i);
}
}
protected void WorkerLoaderCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// TODO need a way to tell if this failed
if (e.Error != null)
{
// DisplayError(RunnerGame.ErrorCode.Exception, new Dictionary<string, string>(){{"@{error}","There was a error while loading. See the log for more information."}}, e.Error);
}
}
protected AbstractParser LoadMetaData(string[] files)
{
var file = files.FirstOrDefault(x => x.EndsWith("info.json"));
if (!string.IsNullOrEmpty(file))
{
// var fileContents = Encoding.UTF8.GetString(ReadAllBytes(file));
return new MetaDataParser(file, _fileLoadHelper, ((PixelVisionEngine)targetEngine));
}
return null;
}
protected void LoadTilemap(string[] files)
{
// If a tilemap json file exists, try to load that
var file = files.FirstOrDefault(x => x.EndsWith("tilemap.json"));
if (!string.IsNullOrEmpty(file))
{
// var fileContents = Encoding.UTF8.GetString(ReadAllBytes(file));
var jsonParser = new TilemapJsonParser(file, _fileLoadHelper, targetEngine);
AddParser(jsonParser);
return;
}
// Try to load the tilemap png file next
file = files.FirstOrDefault(x => x.EndsWith("tilemap.png"));
if (!string.IsNullOrEmpty(file))
{
var imageParser = new PNGFileReader(file, _fileLoadHelper, targetEngine.ColorChip.maskColor);
AddParser(new TilemapParser(imageParser, targetEngine.ColorChip, targetEngine.SpriteChip, targetEngine.TilemapChip));
}
}
protected AbstractParser LoadSprites(string[] files)
{
// // TODO need to tell if the cache should be ignore, important when in tools
// var srcFile = "sprites.png";
//
// // TODO this in here to support legacy games but can be removed in future releases
// var cacheFile = "sprites.cache.png";
// string fileName = null;
// TODO need to depricate this
var file = files.FirstOrDefault(x => x.EndsWith("sprites.png"));
// If there is no sprites cache file, load the png file instead
// if (string.IsNullOrEmpty(file))
// {
// file = files.FirstOrDefault(x => x.EndsWith("sprites.png"));
// }
if (!string.IsNullOrEmpty(file))
{
var imageParser = new PNGFileReader(file, _fileLoadHelper, targetEngine.ColorChip.maskColor);
var colorChip = targetEngine.GetChip(ColorMapParser.chipName, false) is ColorChip colorMapChip
? colorMapChip
: targetEngine.ColorChip;
return new SpriteImageParser(imageParser, colorChip, targetEngine.SpriteChip);
}
return null;
}
protected AbstractParser LoadColorMap(string[] files)
{
// var fileName = "color-map.png";
var file = files.FirstOrDefault(x => x.EndsWith("color-map.png"));
if (!string.IsNullOrEmpty(file))
{
// Create new color map chip
var colorMapChip = new ColorChip();
// Add the chip to the engine
targetEngine.ActivateChip(ColorMapParser.chipName, colorMapChip, false);
// targetEngine.colorMapChip = colorMapChip;
var imageParser = new PNGFileReader(file, _fileLoadHelper, targetEngine.ColorChip.maskColor);
// Pass the chip to the new parser
return new ColorMapParser(imageParser, colorMapChip, maskColor);
}
return null;
}
protected AbstractParser LoadColors(string[] files)
{
// var fileName = "colors.png";
var file = files.FirstOrDefault(x => x.EndsWith("colors.png"));
if (!string.IsNullOrEmpty(file))
{
// var tex = ReadTexture(ReadAllBytes(file));
var imageParser = new PNGFileReader(file, _fileLoadHelper, targetEngine.ColorChip.maskColor);
return new ColorParser(imageParser, targetEngine.ColorChip);
}
return null;
}
protected void LoadSystem(string[] files)
{
// var fileName = ;
var file = files.FirstOrDefault(x => x.EndsWith("data.json"));
if (!string.IsNullOrEmpty(file))
{
// var fileContents = Encoding.UTF8.GetString(ReadAllBytes(file));
var jsonParser = new SystemParser(file, _fileLoadHelper, targetEngine);
jsonParser.CalculateSteps();
while (jsonParser.completed == false) jsonParser.NextStep();
}
}
protected void LoadSounds(string[] files)
{
var file = files.FirstOrDefault(x => x.EndsWith("sounds.json"));
if (!string.IsNullOrEmpty(file))
{
// var fileContents = Encoding.UTF8.GetString(ReadAllBytes(file));
AddParser(new SystemParser(file, _fileLoadHelper, targetEngine));
}
}
protected void LoadMusic(string[] files)
{
// var fileName = ;
var file = files.FirstOrDefault(x => x.EndsWith("music.json"));
if (!string.IsNullOrEmpty(file))
{
// var fileContents = Encoding.UTF8.GetString(ReadAllBytes(file));
AddParser(new SystemParser(file, _fileLoadHelper, targetEngine));
}
}
protected void LoadMetaSprites(string[] files)
{
// var fileName = ;
var file = files.FirstOrDefault(x => x.EndsWith("meta-sprites.json"));
if (!string.IsNullOrEmpty(file))
{
AddParser(new SystemParser(file, _fileLoadHelper, targetEngine));
}
}
protected void LoadSaveData(string[] files)
{
var file = files.FirstOrDefault(x => x.EndsWith("saves.json"));
if (!string.IsNullOrEmpty(file))
{
// var fileContents = Encoding.UTF8.GetString(ReadAllBytes(file));
AddParser(new SystemParser(file, _fileLoadHelper, targetEngine));
}
}
}
}